/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.development.graphicsdriver; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.development.DevelopmentSettingsEnabler; import dalvik.system.VMRuntime; import java.util.ArrayList; import java.util.List; /** * Controller of global switch to enable updatable driver for all Apps. */ public class GraphicsDriverEnableForAllAppsPreferenceController extends BasePreferenceController implements Preference.OnPreferenceChangeListener, GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener, LifecycleObserver, OnStart, OnStop { public static final int UPDATABLE_DRIVER_DEFAULT = 0; public static final int UPDATABLE_DRIVER_PRODUCTION_ALL_APPS = 1; public static final int UPDATABLE_DRIVER_PRERELEASE_ALL_APPS = 2; public static final int UPDATABLE_DRIVER_OFF = 3; public static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0"; public static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1"; private final Context mContext; private final ContentResolver mContentResolver; private final String mPreferenceDefault; private final String mPreferenceProductionDriver; private final String mPreferencePrereleaseDriver; @VisibleForTesting CharSequence[] mEntryList; @VisibleForTesting GraphicsDriverContentObserver mGraphicsDriverContentObserver; private ListPreference mPreference; public GraphicsDriverEnableForAllAppsPreferenceController(Context context, String key) { super(context, key); mContext = context; mContentResolver = context.getContentResolver(); final Resources resources = context.getResources(); mPreferenceDefault = resources.getString(R.string.graphics_driver_app_preference_default); mPreferenceProductionDriver = resources.getString(R.string.graphics_driver_app_preference_production_driver); mPreferencePrereleaseDriver = resources.getString(R.string.graphics_driver_app_preference_prerelease_driver); mEntryList = constructEntryList(mContext, false); mGraphicsDriverContentObserver = new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this); } @Override public int getAvailabilityStatus() { return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext) && (Settings.Global.getInt(mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, UPDATABLE_DRIVER_DEFAULT) != UPDATABLE_DRIVER_OFF) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); mPreference.setEntries(mEntryList); mPreference.setEntryValues(mEntryList); mPreference.setOnPreferenceChangeListener(this); } @Override public void onStart() { mGraphicsDriverContentObserver.register(mContentResolver); } @Override public void onStop() { mGraphicsDriverContentObserver.unregister(mContentResolver); } @Override public void updateState(Preference preference) { final ListPreference listPref = (ListPreference) preference; listPref.setVisible(isAvailable()); final int currentChoice = Settings.Global.getInt( mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, UPDATABLE_DRIVER_DEFAULT); if (currentChoice == UPDATABLE_DRIVER_PRODUCTION_ALL_APPS) { listPref.setValue(mPreferenceProductionDriver); listPref.setSummary(mPreferenceProductionDriver); } else if (currentChoice == UPDATABLE_DRIVER_PRERELEASE_ALL_APPS) { listPref.setValue(mPreferencePrereleaseDriver); listPref.setSummary(mPreferencePrereleaseDriver); } else { listPref.setValue(mPreferenceDefault); listPref.setSummary(mPreferenceDefault); } } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final ListPreference listPref = (ListPreference) preference; final String value = newValue.toString(); final int currentChoice = Settings.Global.getInt( mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, UPDATABLE_DRIVER_DEFAULT); final int userChoice; if (value.equals(mPreferenceProductionDriver)) { userChoice = UPDATABLE_DRIVER_PRODUCTION_ALL_APPS; } else if (value.equals(mPreferencePrereleaseDriver)) { userChoice = UPDATABLE_DRIVER_PRERELEASE_ALL_APPS; } else { userChoice = UPDATABLE_DRIVER_DEFAULT; } listPref.setValue(value); listPref.setSummary(value); if (userChoice != currentChoice) { Settings.Global.putInt( mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, userChoice); } return true; } @Override public void onGraphicsDriverContentChanged() { updateState(mPreference); } /** * Constructs and returns a list of graphics driver choices. */ public static CharSequence[] constructEntryList(Context context, boolean withSystem) { final Resources resources = context.getResources(); final String prereleaseDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE); final String productionDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER_PRODUCTION); List entryList = new ArrayList<>(); entryList.add(resources.getString(R.string.graphics_driver_app_preference_default)); final PackageManager pm = context.getPackageManager(); if (!TextUtils.isEmpty(prereleaseDriverPackageName) && hasDriverPackage(pm, prereleaseDriverPackageName)) { entryList.add(resources.getString( R.string.graphics_driver_app_preference_prerelease_driver)); } if (!TextUtils.isEmpty(productionDriverPackageName) && hasDriverPackage(pm, productionDriverPackageName)) { entryList.add(resources.getString( R.string.graphics_driver_app_preference_production_driver)); } if (withSystem) { entryList.add(resources.getString(R.string.graphics_driver_app_preference_system)); } CharSequence[] filteredEntryList = new CharSequence[entryList.size()]; filteredEntryList = entryList.toArray(filteredEntryList); return filteredEntryList; } private static boolean hasDriverPackage(PackageManager pm, String driverPackageName) { final ApplicationInfo driverAppInfo; try { driverAppInfo = pm.getApplicationInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { return false; } if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) { return false; } final String abi = chooseAbi(driverAppInfo); if (abi == null) { return false; } return true; } private static String chooseAbi(ApplicationInfo ai) { final String isa = VMRuntime.getCurrentInstructionSet(); if (ai.primaryCpuAbi != null && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { return ai.primaryCpuAbi; } if (ai.secondaryCpuAbi != null && isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) { return ai.secondaryCpuAbi; } return null; } }