1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.development.graphicsdriver; 18 19 import android.content.ContentResolver; 20 import android.content.Context; 21 import android.content.pm.ApplicationInfo; 22 import android.content.pm.PackageManager; 23 import android.content.res.Resources; 24 import android.os.Build; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.os.SystemProperties; 28 import android.provider.Settings; 29 import android.text.TextUtils; 30 31 import androidx.annotation.VisibleForTesting; 32 import androidx.preference.ListPreference; 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceScreen; 35 36 import com.android.settings.R; 37 import com.android.settings.core.BasePreferenceController; 38 import com.android.settingslib.core.lifecycle.LifecycleObserver; 39 import com.android.settingslib.core.lifecycle.events.OnStart; 40 import com.android.settingslib.core.lifecycle.events.OnStop; 41 import com.android.settingslib.development.DevelopmentSettingsEnabler; 42 43 import dalvik.system.VMRuntime; 44 45 import java.util.ArrayList; 46 import java.util.List; 47 48 /** 49 * Controller of global switch to enable updatable driver for all Apps. 50 */ 51 public class GraphicsDriverEnableForAllAppsPreferenceController extends BasePreferenceController 52 implements Preference.OnPreferenceChangeListener, 53 GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener, 54 LifecycleObserver, OnStart, OnStop { 55 56 public static final int UPDATABLE_DRIVER_DEFAULT = 0; 57 public static final int UPDATABLE_DRIVER_PRODUCTION_ALL_APPS = 1; 58 public static final int UPDATABLE_DRIVER_PRERELEASE_ALL_APPS = 2; 59 public static final int UPDATABLE_DRIVER_OFF = 3; 60 public static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0"; 61 public static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1"; 62 63 private final Context mContext; 64 private final ContentResolver mContentResolver; 65 private final String mPreferenceDefault; 66 private final String mPreferenceProductionDriver; 67 private final String mPreferencePrereleaseDriver; 68 @VisibleForTesting 69 CharSequence[] mEntryList; 70 @VisibleForTesting 71 GraphicsDriverContentObserver mGraphicsDriverContentObserver; 72 73 private ListPreference mPreference; 74 GraphicsDriverEnableForAllAppsPreferenceController(Context context, String key)75 public GraphicsDriverEnableForAllAppsPreferenceController(Context context, String key) { 76 super(context, key); 77 mContext = context; 78 mContentResolver = context.getContentResolver(); 79 80 final Resources resources = context.getResources(); 81 mPreferenceDefault = resources.getString(R.string.graphics_driver_app_preference_default); 82 mPreferenceProductionDriver = 83 resources.getString(R.string.graphics_driver_app_preference_production_driver); 84 mPreferencePrereleaseDriver = 85 resources.getString(R.string.graphics_driver_app_preference_prerelease_driver); 86 mEntryList = constructEntryList(mContext, false); 87 mGraphicsDriverContentObserver = 88 new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this); 89 } 90 91 @Override getAvailabilityStatus()92 public int getAvailabilityStatus() { 93 return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext) 94 && (Settings.Global.getInt(mContentResolver, 95 Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 96 UPDATABLE_DRIVER_DEFAULT) 97 != UPDATABLE_DRIVER_OFF) 98 ? AVAILABLE 99 : CONDITIONALLY_UNAVAILABLE; 100 } 101 102 @Override displayPreference(PreferenceScreen screen)103 public void displayPreference(PreferenceScreen screen) { 104 super.displayPreference(screen); 105 mPreference = screen.findPreference(getPreferenceKey()); 106 mPreference.setEntries(mEntryList); 107 mPreference.setEntryValues(mEntryList); 108 mPreference.setOnPreferenceChangeListener(this); 109 } 110 111 @Override onStart()112 public void onStart() { 113 mGraphicsDriverContentObserver.register(mContentResolver); 114 } 115 116 @Override onStop()117 public void onStop() { 118 mGraphicsDriverContentObserver.unregister(mContentResolver); 119 } 120 121 @Override updateState(Preference preference)122 public void updateState(Preference preference) { 123 final ListPreference listPref = (ListPreference) preference; 124 listPref.setVisible(isAvailable()); 125 final int currentChoice = Settings.Global.getInt( 126 mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 127 UPDATABLE_DRIVER_DEFAULT); 128 if (currentChoice == UPDATABLE_DRIVER_PRODUCTION_ALL_APPS) { 129 listPref.setValue(mPreferenceProductionDriver); 130 listPref.setSummary(mPreferenceProductionDriver); 131 } else if (currentChoice == UPDATABLE_DRIVER_PRERELEASE_ALL_APPS) { 132 listPref.setValue(mPreferencePrereleaseDriver); 133 listPref.setSummary(mPreferencePrereleaseDriver); 134 } else { 135 listPref.setValue(mPreferenceDefault); 136 listPref.setSummary(mPreferenceDefault); 137 } 138 } 139 140 @Override onPreferenceChange(Preference preference, Object newValue)141 public boolean onPreferenceChange(Preference preference, Object newValue) { 142 final ListPreference listPref = (ListPreference) preference; 143 final String value = newValue.toString(); 144 final int currentChoice = Settings.Global.getInt( 145 mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 146 UPDATABLE_DRIVER_DEFAULT); 147 final int userChoice; 148 if (value.equals(mPreferenceProductionDriver)) { 149 userChoice = UPDATABLE_DRIVER_PRODUCTION_ALL_APPS; 150 } else if (value.equals(mPreferencePrereleaseDriver)) { 151 userChoice = UPDATABLE_DRIVER_PRERELEASE_ALL_APPS; 152 } else { 153 userChoice = UPDATABLE_DRIVER_DEFAULT; 154 } 155 listPref.setValue(value); 156 listPref.setSummary(value); 157 158 if (userChoice != currentChoice) { 159 Settings.Global.putInt( 160 mContentResolver, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, userChoice); 161 } 162 163 return true; 164 } 165 166 @Override onGraphicsDriverContentChanged()167 public void onGraphicsDriverContentChanged() { 168 updateState(mPreference); 169 } 170 171 /** 172 * Constructs and returns a list of graphics driver choices. 173 */ constructEntryList(Context context, boolean withSystem)174 public static CharSequence[] constructEntryList(Context context, boolean withSystem) { 175 final Resources resources = context.getResources(); 176 final String prereleaseDriverPackageName = 177 SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE); 178 final String productionDriverPackageName = 179 SystemProperties.get(PROPERTY_GFX_DRIVER_PRODUCTION); 180 181 List<CharSequence> entryList = new ArrayList<>(); 182 entryList.add(resources.getString(R.string.graphics_driver_app_preference_default)); 183 final PackageManager pm = context.getPackageManager(); 184 if (!TextUtils.isEmpty(prereleaseDriverPackageName) 185 && hasDriverPackage(pm, prereleaseDriverPackageName)) { 186 entryList.add(resources.getString( 187 R.string.graphics_driver_app_preference_prerelease_driver)); 188 } 189 if (!TextUtils.isEmpty(productionDriverPackageName) 190 && hasDriverPackage(pm, productionDriverPackageName)) { 191 entryList.add(resources.getString( 192 R.string.graphics_driver_app_preference_production_driver)); 193 } 194 if (withSystem) { 195 entryList.add(resources.getString(R.string.graphics_driver_app_preference_system)); 196 } 197 CharSequence[] filteredEntryList = new CharSequence[entryList.size()]; 198 filteredEntryList = entryList.toArray(filteredEntryList); 199 return filteredEntryList; 200 } 201 hasDriverPackage(PackageManager pm, String driverPackageName)202 private static boolean hasDriverPackage(PackageManager pm, String driverPackageName) { 203 final ApplicationInfo driverAppInfo; 204 try { 205 driverAppInfo = pm.getApplicationInfo(driverPackageName, 206 PackageManager.MATCH_SYSTEM_ONLY); 207 } catch (PackageManager.NameNotFoundException e) { 208 return false; 209 } 210 if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) { 211 return false; 212 } 213 final String abi = chooseAbi(driverAppInfo); 214 if (abi == null) { 215 return false; 216 } 217 return true; 218 } 219 chooseAbi(ApplicationInfo ai)220 private static String chooseAbi(ApplicationInfo ai) { 221 final String isa = VMRuntime.getCurrentInstructionSet(); 222 if (ai.primaryCpuAbi != null 223 && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { 224 return ai.primaryCpuAbi; 225 } 226 if (ai.secondaryCpuAbi != null 227 && isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) { 228 return ai.secondaryCpuAbi; 229 } 230 return null; 231 } 232 } 233