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 package com.android.angle.common; 17 18 import android.content.ContentResolver; 19 import android.content.Context; 20 import android.content.pm.PackageInfo; 21 import android.provider.Settings; 22 import android.util.Log; 23 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.List; 27 28 class GlobalSettings 29 { 30 31 private final String TAG = this.getClass().getSimpleName(); 32 33 private Context mContext; 34 private List<PackageInfo> mInstalledPkgs = new ArrayList<>(); 35 private List<String> mGlobalSettingsDriverPkgs = new ArrayList<>(); 36 private List<String> mGlobalSettingsDriverValues = new ArrayList<>(); 37 GlobalSettings(Context context, List<PackageInfo> installedPkgs)38 GlobalSettings(Context context, List<PackageInfo> installedPkgs) 39 { 40 mContext = context; 41 42 setInstalledPkgs(installedPkgs); 43 } 44 clearAllGlobalSettings(Context context)45 static void clearAllGlobalSettings(Context context) 46 { 47 // angle_gl_driver_all_angle 48 updateAllUseAngle(context, false); 49 // show_angle_in_use_dialog_box 50 updateShowAngleInUseDialog(context, false); 51 // angle_gl_driver_selection_pkgs, angle_gl_driver_selection_values 52 ContentResolver contentResolver = context.getContentResolver(); 53 Settings.Global.putString(contentResolver, 54 context.getString(R.string.global_settings_driver_selection_pkgs), "\"\""); 55 Settings.Global.putString(contentResolver, 56 context.getString(R.string.global_settings_driver_selection_values), "\"\""); 57 58 // For completeness, we'll clear the angle_debug_package, but we don't allow setting 59 // it via the APK (currently) 60 Settings.Global.putString(contentResolver, 61 context.getString(R.string.global_settings_angle_debug_package), ""); 62 63 // Skip angle_allowlist; not updatable via Developer Options 64 } 65 getAllUseAngle()66 Boolean getAllUseAngle() 67 { 68 ContentResolver contentResolver = mContext.getContentResolver(); 69 try 70 { 71 int allUseAngle = Settings.Global.getInt( 72 contentResolver, mContext.getString(R.string.global_settings_driver_all_angle)); 73 return (allUseAngle == 1); 74 } 75 catch (Settings.SettingNotFoundException e) 76 { 77 return false; 78 } 79 } 80 getShowAngleInUseDialogBox()81 Boolean getShowAngleInUseDialogBox() 82 { 83 ContentResolver contentResolver = mContext.getContentResolver(); 84 try 85 { 86 int showAngleInUseDialogBox = Settings.Global.getInt(contentResolver, 87 mContext.getString(R.string.global_settings_show_angle_in_use_dialog_box)); 88 return (showAngleInUseDialogBox == 1); 89 } 90 catch (Settings.SettingNotFoundException e) 91 { 92 return false; 93 } 94 } 95 updateAllUseAngle(Context context, Boolean allUseAngle)96 static void updateAllUseAngle(Context context, Boolean allUseAngle) 97 { 98 ContentResolver contentResolver = context.getContentResolver(); 99 Settings.Global.putInt(contentResolver, 100 context.getString(R.string.global_settings_driver_all_angle), allUseAngle ? 1 : 0); 101 } 102 updateShowAngleInUseDialog(Context context, Boolean showAngleInUseDialog)103 static void updateShowAngleInUseDialog(Context context, Boolean showAngleInUseDialog) 104 { 105 ContentResolver contentResolver = context.getContentResolver(); 106 Settings.Global.putInt(contentResolver, 107 context.getString(R.string.global_settings_show_angle_in_use_dialog_box), 108 showAngleInUseDialog ? 1 : 0); 109 } 110 updateAngleAllowlist(Context context, String packageNames)111 static void updateAngleAllowlist(Context context, String packageNames) 112 { 113 ContentResolver contentResolver = context.getContentResolver(); 114 Settings.Global.putString(contentResolver, 115 context.getString(R.string.global_settings_angle_allowlist), packageNames); 116 } 117 updatePkg(String pkgName, String driver)118 void updatePkg(String pkgName, String driver) 119 { 120 int pkgIndex = getGlobalSettingsPkgIndex(pkgName); 121 122 if (!isValidDiverValue(driver)) 123 { 124 Log.e(TAG, "Attempting to update a PKG with an invalid driver: '" + driver + "'"); 125 return; 126 } 127 128 String defaultDriver = mContext.getString(R.string.default_driver); 129 if (driver.equals(defaultDriver)) 130 { 131 if (pkgIndex >= 0) 132 { 133 // We only store global settings for driver values other than the default 134 mGlobalSettingsDriverPkgs.remove(pkgIndex); 135 mGlobalSettingsDriverValues.remove(pkgIndex); 136 } 137 } 138 else 139 { 140 if (pkgIndex >= 0) 141 { 142 mGlobalSettingsDriverValues.set(pkgIndex, driver); 143 } 144 else 145 { 146 mGlobalSettingsDriverPkgs.add(pkgName); 147 mGlobalSettingsDriverValues.add(driver); 148 } 149 } 150 151 writeGlobalSettings(); 152 } 153 getDriverForPkg(String pkgName)154 String getDriverForPkg(String pkgName) 155 { 156 int pkgIndex = getGlobalSettingsPkgIndex(pkgName); 157 158 if (pkgIndex >= 0) 159 { 160 return mGlobalSettingsDriverValues.get(pkgIndex); 161 } 162 163 return null; 164 } 165 setInstalledPkgs(List<PackageInfo> installedPkgs)166 void setInstalledPkgs(List<PackageInfo> installedPkgs) 167 { 168 mInstalledPkgs = installedPkgs; 169 170 updateGlobalSettings(); 171 } 172 updateGlobalSettings()173 private void updateGlobalSettings() 174 { 175 readGlobalSettings(); 176 177 validateGlobalSettings(); 178 179 writeGlobalSettings(); 180 } 181 readGlobalSettings()182 private void readGlobalSettings() 183 { 184 mGlobalSettingsDriverPkgs = getGlobalSettingsString( 185 mContext.getString(R.string.global_settings_driver_selection_pkgs)); 186 mGlobalSettingsDriverValues = getGlobalSettingsString( 187 mContext.getString(R.string.global_settings_driver_selection_values)); 188 } 189 getGlobalSettingsString(String globalSetting)190 private List<String> getGlobalSettingsString(String globalSetting) 191 { 192 List<String> valueList; 193 ContentResolver contentResolver = mContext.getContentResolver(); 194 String settingsValue = Settings.Global.getString(contentResolver, globalSetting); 195 196 if (settingsValue != null) 197 { 198 valueList = new ArrayList<>(Arrays.asList(settingsValue.split(","))); 199 } 200 else 201 { 202 valueList = new ArrayList<>(); 203 } 204 205 return valueList; 206 } 207 writeGlobalSettings()208 private void writeGlobalSettings() 209 { 210 String driverPkgs = String.join(",", mGlobalSettingsDriverPkgs); 211 String driverValues = String.join(",", mGlobalSettingsDriverValues); 212 213 ContentResolver contentResolver = mContext.getContentResolver(); 214 Settings.Global.putString(contentResolver, 215 mContext.getString(R.string.global_settings_driver_selection_pkgs), driverPkgs); 216 Settings.Global.putString(contentResolver, 217 mContext.getString(R.string.global_settings_driver_selection_values), driverValues); 218 } 219 validateGlobalSettings()220 private void validateGlobalSettings() 221 { 222 // Verify lengths 223 if (mGlobalSettingsDriverPkgs.size() != mGlobalSettingsDriverValues.size()) 224 { 225 // The lengths don't match, so clear the values out and rebuild later. 226 mGlobalSettingsDriverPkgs.clear(); 227 mGlobalSettingsDriverValues.clear(); 228 return; 229 } 230 231 String defaultDriver = mContext.getString(R.string.default_driver); 232 // Use a temp list, since we're potentially modifying the original list. 233 List<String> globalSettingsDriverPkgs = new ArrayList<>(mGlobalSettingsDriverPkgs); 234 for (String pkgName : globalSettingsDriverPkgs) 235 { 236 // Remove any uninstalled packages. 237 if (!isPkgInstalled(pkgName)) 238 { 239 removePkgFromGlobalSettings(pkgName); 240 } 241 // Remove any packages with invalid driver values 242 else if (!isValidDiverValue(getDriverForPkg(pkgName))) 243 { 244 removePkgFromGlobalSettings(pkgName); 245 } 246 // Remove any packages with the 'default' driver selected 247 else if (defaultDriver.equals(getDriverForPkg(pkgName))) 248 { 249 removePkgFromGlobalSettings(pkgName); 250 } 251 } 252 } 253 removePkgFromGlobalSettings(String pkgName)254 private void removePkgFromGlobalSettings(String pkgName) 255 { 256 int pkgIndex = getGlobalSettingsPkgIndex(pkgName); 257 258 mGlobalSettingsDriverPkgs.remove(pkgIndex); 259 mGlobalSettingsDriverValues.remove(pkgIndex); 260 } 261 getGlobalSettingsPkgIndex(String pkgName)262 private int getGlobalSettingsPkgIndex(String pkgName) 263 { 264 for (int pkgIndex = 0; pkgIndex < mGlobalSettingsDriverPkgs.size(); pkgIndex++) 265 { 266 if (mGlobalSettingsDriverPkgs.get(pkgIndex).equals(pkgName)) 267 { 268 return pkgIndex; 269 } 270 } 271 272 return -1; 273 } 274 isPkgInstalled(String pkgName)275 private Boolean isPkgInstalled(String pkgName) 276 { 277 for (PackageInfo pkg : mInstalledPkgs) 278 { 279 if (pkg.packageName.equals(pkgName)) 280 { 281 return true; 282 } 283 } 284 285 return false; 286 } 287 isValidDiverValue(String driverValue)288 private Boolean isValidDiverValue(String driverValue) 289 { 290 CharSequence[] drivers = mContext.getResources().getStringArray(R.array.driver_values); 291 292 for (CharSequence driver : drivers) 293 { 294 if (driverValue.equals(driver.toString())) 295 { 296 return true; 297 } 298 } 299 300 return false; 301 } 302 } 303