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 Game 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 GAME_DRIVER_DEFAULT = 0; 57 public static final int GAME_DRIVER_ALL_APPS = 1; 58 public static final int GAME_DRIVER_PRERELEASE_ALL_APPS = 2; 59 public static final int GAME_DRIVER_OFF = 3; 60 public static final String PROPERTY_GFX_DRIVER_GAME = "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 mPreferenceGameDriver; 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 mPreferenceGameDriver = 83 resources.getString(R.string.graphics_driver_app_preference_game_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.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT) 96 != GAME_DRIVER_OFF) 97 ? AVAILABLE 98 : CONDITIONALLY_UNAVAILABLE; 99 } 100 101 @Override displayPreference(PreferenceScreen screen)102 public void displayPreference(PreferenceScreen screen) { 103 super.displayPreference(screen); 104 mPreference = screen.findPreference(getPreferenceKey()); 105 mPreference.setEntries(mEntryList); 106 mPreference.setEntryValues(mEntryList); 107 mPreference.setOnPreferenceChangeListener(this); 108 } 109 110 @Override onStart()111 public void onStart() { 112 mGraphicsDriverContentObserver.register(mContentResolver); 113 } 114 115 @Override onStop()116 public void onStop() { 117 mGraphicsDriverContentObserver.unregister(mContentResolver); 118 } 119 120 @Override updateState(Preference preference)121 public void updateState(Preference preference) { 122 final ListPreference listPref = (ListPreference) preference; 123 listPref.setVisible(isAvailable()); 124 final int currentChoice = Settings.Global.getInt( 125 mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); 126 if (currentChoice == GAME_DRIVER_ALL_APPS) { 127 listPref.setValue(mPreferenceGameDriver); 128 listPref.setSummary(mPreferenceGameDriver); 129 } else if (currentChoice == GAME_DRIVER_PRERELEASE_ALL_APPS) { 130 listPref.setValue(mPreferencePrereleaseDriver); 131 listPref.setSummary(mPreferencePrereleaseDriver); 132 } else { 133 listPref.setValue(mPreferenceDefault); 134 listPref.setSummary(mPreferenceDefault); 135 } 136 } 137 138 @Override onPreferenceChange(Preference preference, Object newValue)139 public boolean onPreferenceChange(Preference preference, Object newValue) { 140 final ListPreference listPref = (ListPreference) preference; 141 final String value = newValue.toString(); 142 final int currentChoice = Settings.Global.getInt( 143 mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); 144 final int userChoice; 145 if (value.equals(mPreferenceGameDriver)) { 146 userChoice = GAME_DRIVER_ALL_APPS; 147 } else if (value.equals(mPreferencePrereleaseDriver)) { 148 userChoice = GAME_DRIVER_PRERELEASE_ALL_APPS; 149 } else { 150 userChoice = GAME_DRIVER_DEFAULT; 151 } 152 listPref.setValue(value); 153 listPref.setSummary(value); 154 155 if (userChoice != currentChoice) { 156 Settings.Global.putInt( 157 mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, userChoice); 158 } 159 160 return true; 161 } 162 163 @Override onGraphicsDriverContentChanged()164 public void onGraphicsDriverContentChanged() { 165 updateState(mPreference); 166 } 167 168 /** 169 * Constructs and returns a list of graphics driver choices. 170 */ constructEntryList(Context context, boolean withSystem)171 public static CharSequence[] constructEntryList(Context context, boolean withSystem) { 172 final Resources resources = context.getResources(); 173 final String prereleaseDriverPackageName = 174 SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE); 175 final String gameDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER_GAME); 176 177 List<CharSequence> entryList = new ArrayList<>(); 178 entryList.add(resources.getString(R.string.graphics_driver_app_preference_default)); 179 final PackageManager pm = context.getPackageManager(); 180 if (!TextUtils.isEmpty(prereleaseDriverPackageName) 181 && hasDriverPackage(pm, prereleaseDriverPackageName)) { 182 entryList.add(resources.getString( 183 R.string.graphics_driver_app_preference_prerelease_driver)); 184 } 185 if (!TextUtils.isEmpty(gameDriverPackageName) 186 && hasDriverPackage(pm, gameDriverPackageName)) { 187 entryList.add(resources.getString(R.string.graphics_driver_app_preference_game_driver)); 188 } 189 if (withSystem) { 190 entryList.add(resources.getString(R.string.graphics_driver_app_preference_system)); 191 } 192 CharSequence[] filteredEntryList = new CharSequence[entryList.size()]; 193 filteredEntryList = entryList.toArray(filteredEntryList); 194 return filteredEntryList; 195 } 196 hasDriverPackage(PackageManager pm, String driverPackageName)197 private static boolean hasDriverPackage(PackageManager pm, String driverPackageName) { 198 final ApplicationInfo driverAppInfo; 199 try { 200 driverAppInfo = pm.getApplicationInfo(driverPackageName, 201 PackageManager.MATCH_SYSTEM_ONLY); 202 } catch (PackageManager.NameNotFoundException e) { 203 return false; 204 } 205 if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) { 206 return false; 207 } 208 final String abi = chooseAbi(driverAppInfo); 209 if (abi == null) { 210 return false; 211 } 212 return true; 213 } 214 chooseAbi(ApplicationInfo ai)215 private static String chooseAbi(ApplicationInfo ai) { 216 final String isa = VMRuntime.getCurrentInstructionSet(); 217 if (ai.primaryCpuAbi != null 218 && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { 219 return ai.primaryCpuAbi; 220 } 221 if (ai.secondaryCpuAbi != null 222 && isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) { 223 return ai.secondaryCpuAbi; 224 } 225 return null; 226 } 227 } 228