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.IntentFilter; 19 import android.content.SharedPreferences; 20 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 21 import android.content.pm.ApplicationInfo; 22 import android.content.pm.PackageInfo; 23 import android.os.Bundle; 24 import android.os.Process; 25 import android.util.Log; 26 import androidx.preference.ListPreference; 27 import androidx.preference.Preference; 28 import androidx.preference.PreferenceCategory; 29 import androidx.preference.PreferenceFragment; 30 import androidx.preference.PreferenceManager; 31 import androidx.preference.SwitchPreference; 32 33 import java.text.Collator; 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.Comparator; 37 import java.util.List; 38 import java.util.Map; 39 40 public class MainFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener 41 { 42 43 private final String TAG = this.getClass().getSimpleName(); 44 45 private SharedPreferences mPrefs; 46 private GlobalSettings mGlobalSettings; 47 private Receiver mRefreshReceiver = new Receiver(); 48 private SwitchPreference mAllAngleSwitchPref; 49 private SwitchPreference mShowAngleInUseDialogSwitchPref; 50 private List<PackageInfo> mInstalledPkgs = new ArrayList<>(); 51 private List<ListPreference> mDriverListPrefs = new ArrayList<>(); 52 53 SharedPreferences.OnSharedPreferenceChangeListener listener = 54 new SharedPreferences.OnSharedPreferenceChangeListener() { 55 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) 56 { 57 // Nothing to do yet 58 } 59 }; 60 61 @Override onCreate(Bundle savedInstanceState)62 public void onCreate(Bundle savedInstanceState) 63 { 64 super.onCreate(savedInstanceState); 65 66 getInstalledPkgsList(); 67 68 mPrefs = PreferenceManager.getDefaultSharedPreferences( 69 getActivity().getApplicationContext()); 70 validatePreferences(); 71 72 mGlobalSettings = new GlobalSettings(getContext(), mInstalledPkgs); 73 mergeGlobalSettings(); 74 75 createAllUseAnglePreference(); 76 createShowAngleInUseDialogPreference(); 77 78 updatePreferencesFromGlobalSettings(); 79 } 80 81 @Override onResume()82 public void onResume() 83 { 84 super.onResume(); 85 86 updatePreferencesFromGlobalSettings(); 87 88 getActivity().registerReceiver(mRefreshReceiver, 89 new IntentFilter( 90 getContext().getString(R.string.intent_angle_for_android_toast_message))); 91 getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener( 92 listener); 93 } 94 95 @Override onPause()96 public void onPause() 97 { 98 getActivity().unregisterReceiver(mRefreshReceiver); 99 getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener( 100 listener); 101 102 super.onPause(); 103 } 104 105 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)106 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) 107 { 108 addPreferencesFromResource(R.xml.main); 109 } 110 111 @Override onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)112 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) 113 { 114 Log.v(TAG, "Shared preference changed: key = '" + key + "'"); 115 } 116 updatePreferencesFromGlobalSettings()117 private void updatePreferencesFromGlobalSettings() 118 { 119 mAllAngleSwitchPref.setChecked(mGlobalSettings.getAllUseAngle()); 120 mShowAngleInUseDialogSwitchPref.setChecked(mGlobalSettings.getShowAngleInUseDialogBox()); 121 createInstalledAppsListPreference(); 122 } 123 createAllUseAnglePreference()124 private void createAllUseAnglePreference() 125 { 126 String allUseAngleKey = getContext().getString(R.string.pref_key_all_angle); 127 Boolean allUseAngle = mPrefs.getBoolean(allUseAngleKey, false); 128 mAllAngleSwitchPref = (SwitchPreference) findPreference(allUseAngleKey); 129 mAllAngleSwitchPref.setOnPreferenceClickListener( 130 new Preference.OnPreferenceClickListener() { 131 @Override 132 public boolean onPreferenceClick(Preference preference) 133 { 134 Receiver.updateAllUseAngle(getContext()); 135 return true; 136 } 137 }); 138 } 139 createShowAngleInUseDialogPreference()140 private void createShowAngleInUseDialogPreference() 141 { 142 String showAngleInUseDialogKey = 143 getContext().getString(R.string.pref_key_angle_in_use_dialog); 144 Boolean showAngleInUseDialogBox = mPrefs.getBoolean(showAngleInUseDialogKey, false); 145 mShowAngleInUseDialogSwitchPref = 146 (SwitchPreference) findPreference(showAngleInUseDialogKey); 147 mShowAngleInUseDialogSwitchPref.setOnPreferenceClickListener( 148 new Preference.OnPreferenceClickListener() { 149 @Override 150 public boolean onPreferenceClick(Preference preference) 151 { 152 Receiver.updateShowAngleInUseDialogBox(getContext()); 153 return true; 154 } 155 }); 156 } 157 createInstalledAppsListPreference()158 private void createInstalledAppsListPreference() 159 { 160 getInstalledPkgsList(); 161 mGlobalSettings.setInstalledPkgs(mInstalledPkgs); 162 mergeGlobalSettings(); 163 164 String selectDriverCatKey = 165 getContext().getString(R.string.pref_key_select_opengl_driver_category); 166 PreferenceCategory installedPkgsCat = 167 (PreferenceCategory) findPreference(selectDriverCatKey); 168 installedPkgsCat.removeAll(); 169 mDriverListPrefs.clear(); 170 if (mInstalledPkgs.isEmpty()) 171 { 172 ListPreference listPreference = new ListPreference(installedPkgsCat.getContext()); 173 initEmptyListPreference(listPreference); 174 installedPkgsCat.addPreference(listPreference); 175 } 176 else 177 { 178 for (PackageInfo packageInfo : mInstalledPkgs) 179 { 180 ListPreference listPreference = new ListPreference(installedPkgsCat.getContext()); 181 initListPreference(packageInfo, listPreference); 182 installedPkgsCat.addPreference(listPreference); 183 } 184 } 185 } 186 validatePreferences()187 private void validatePreferences() 188 { 189 Map<String, ?> allPrefs = mPrefs.getAll(); 190 191 // Remove Preference values for any uninstalled PKGs 192 for (String key : allPrefs.keySet()) 193 { 194 // Remove any uninstalled PKGs 195 PackageInfo packageInfo = getPackageInfoForPackageName(key); 196 197 if (packageInfo != null) 198 { 199 removePkgPreference(key); 200 } 201 } 202 } 203 getInstalledPkgsList()204 private void getInstalledPkgsList() 205 { 206 List<PackageInfo> pkgs = getActivity().getPackageManager().getInstalledPackages(0); 207 208 mInstalledPkgs.clear(); 209 210 for (PackageInfo packageInfo : pkgs) 211 { 212 if (packageInfo.applicationInfo.uid == Process.SYSTEM_UID) 213 { 214 continue; 215 } 216 217 // Filter out apps that are system apps 218 if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) 219 { 220 continue; 221 } 222 223 mInstalledPkgs.add(packageInfo); 224 } 225 226 Collections.sort(mInstalledPkgs, displayNameComparator); 227 } 228 229 private final Comparator<PackageInfo> displayNameComparator = new Comparator<PackageInfo>() { 230 public final int compare(PackageInfo a, PackageInfo b) 231 { 232 return collator.compare(getAppName(a), getAppName(b)); 233 } 234 235 private final Collator collator = Collator.getInstance(); 236 }; 237 getAppName(PackageInfo packageInfo)238 private String getAppName(PackageInfo packageInfo) 239 { 240 return packageInfo.applicationInfo.loadLabel(getActivity().getPackageManager()).toString(); 241 } 242 initEmptyListPreference(ListPreference listPreference)243 private void initEmptyListPreference(ListPreference listPreference) 244 { 245 String noAppsInstalledTitle = getContext().getString(R.string.no_apps_installed_title); 246 listPreference.setTitle(noAppsInstalledTitle); 247 248 String noAppsInstalledSummary = getContext().getString(R.string.no_apps_installed_summary); 249 listPreference.setSummary(noAppsInstalledSummary); 250 251 listPreference.setSelectable(false); 252 253 mDriverListPrefs.add(listPreference); 254 } 255 initListPreference(PackageInfo packageInfo, ListPreference listPreference)256 private void initListPreference(PackageInfo packageInfo, ListPreference listPreference) 257 { 258 CharSequence[] drivers = getResources().getStringArray(R.array.driver_values); 259 listPreference.setEntryValues(drivers); 260 listPreference.setEntries(drivers); 261 262 String defaultDriver = getContext().getString(R.string.default_driver); 263 listPreference.setDefaultValue(defaultDriver); 264 265 String dialogTitleKey = getContext().getString(R.string.select_opengl_driver_title); 266 listPreference.setDialogTitle(dialogTitleKey); 267 listPreference.setKey(packageInfo.packageName); 268 269 listPreference.setTitle(getAppName(packageInfo)); 270 listPreference.setSummary(mPrefs.getString(packageInfo.packageName, defaultDriver)); 271 272 listPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 273 @Override 274 public boolean onPreferenceChange(Preference preference, Object newValue) 275 { 276 ListPreference listPreference = (ListPreference) preference; 277 278 listPreference.setSummary(newValue.toString()); 279 mGlobalSettings.updatePkg(preference.getKey(), newValue.toString()); 280 281 return true; 282 } 283 }); 284 285 mDriverListPrefs.add(listPreference); 286 } 287 removePkgPreference(String key)288 private void removePkgPreference(String key) 289 { 290 SharedPreferences.Editor editor = mPrefs.edit(); 291 292 editor.remove(key); 293 editor.apply(); 294 295 for (ListPreference listPreference : mDriverListPrefs) 296 { 297 if (listPreference.getKey().equals(key)) 298 { 299 mDriverListPrefs.remove(listPreference); 300 } 301 } 302 } 303 getPackageInfoForPackageName(String pkgName)304 private PackageInfo getPackageInfoForPackageName(String pkgName) 305 { 306 PackageInfo foundPackageInfo = null; 307 308 for (PackageInfo packageInfo : mInstalledPkgs) 309 { 310 if (pkgName.equals(getAppName(packageInfo))) 311 { 312 foundPackageInfo = packageInfo; 313 break; 314 } 315 } 316 317 return foundPackageInfo; 318 } 319 mergeGlobalSettings()320 private void mergeGlobalSettings() 321 { 322 SharedPreferences.Editor editor = mPrefs.edit(); 323 324 for (PackageInfo packageInfo : mInstalledPkgs) 325 { 326 String driver = mGlobalSettings.getDriverForPkg(packageInfo.packageName); 327 328 if (driver != null) 329 { 330 editor.putString(packageInfo.packageName, driver); 331 } 332 else 333 { 334 // No Global.Setting driver value for this package, so must be 'default' 335 String defaultDriver = getContext().getString(R.string.default_driver); 336 editor.putString(packageInfo.packageName, defaultDriver); 337 } 338 } 339 340 editor.apply(); 341 } 342 } 343