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.Context; 19 import android.content.Intent; 20 import android.content.IntentFilter; 21 import android.content.SharedPreferences; 22 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.ActivityInfo; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.PackageManager.NameNotFoundException; 28 import android.content.pm.ResolveInfo; 29 import android.os.Build; 30 import android.os.Bundle; 31 import android.os.Process; 32 import android.util.Log; 33 import androidx.preference.ListPreference; 34 import androidx.preference.Preference; 35 import androidx.preference.PreferenceCategory; 36 import androidx.preference.PreferenceFragment; 37 import androidx.preference.PreferenceManager; 38 import androidx.preference.SwitchPreference; 39 40 import java.text.Collator; 41 import java.util.ArrayList; 42 import java.util.Collections; 43 import java.util.Comparator; 44 import java.util.List; 45 import java.util.Map; 46 47 import com.android.angle.R; 48 49 public class MainFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener 50 { 51 52 private final String TAG = this.getClass().getSimpleName(); 53 private final boolean DEBUG = false; 54 55 private SharedPreferences mSharedPreferences; 56 private SwitchPreference mShowAngleInUseSwitchPref; 57 private List<ListPreference> mApplicationListPreferences = new ArrayList<>(); 58 59 private GlobalSettings mGlobalSettings; 60 private Receiver mRefreshReceiver = new Receiver(); 61 private List<PackageInfo> mInstalledPackages = new ArrayList<>(); 62 private AngleRuleHelper angleRuleHelper; 63 64 SharedPreferences.OnSharedPreferenceChangeListener listener = 65 new SharedPreferences.OnSharedPreferenceChangeListener() { 66 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) 67 { 68 // Nothing to do yet 69 } 70 }; 71 72 @Override onCreate(Bundle savedInstanceState)73 public void onCreate(Bundle savedInstanceState) 74 { 75 super.onCreate(savedInstanceState); 76 77 queryInstalledPackages(); 78 79 mSharedPreferences = PreferenceManager.getDefaultSharedPreferences( 80 getActivity().getApplicationContext()); 81 if (DEBUG) 82 { 83 Map<String, ?> preferences = PreferenceManager 84 .getDefaultSharedPreferences(getActivity().getApplicationContext()).getAll(); 85 for (String key : preferences.keySet()) 86 { 87 Log.d(TAG, key + ", " + preferences.get(key)); 88 } 89 } 90 mGlobalSettings = new GlobalSettings(getContext(), mSharedPreferences, mInstalledPackages); 91 92 createShowAngleInUseSwitchPreference(); 93 createInstalledAppsListPreference(); 94 } 95 96 @Override onResume()97 public void onResume() 98 { 99 super.onResume(); 100 101 getActivity().registerReceiver(mRefreshReceiver, 102 new IntentFilter( 103 getContext().getString(R.string.intent_angle_for_android_toast_message)), Context.RECEIVER_EXPORTED); 104 getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener( 105 listener); 106 updatePreferences(); 107 } 108 109 @Override onPause()110 public void onPause() 111 { 112 getActivity().unregisterReceiver(mRefreshReceiver); 113 getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener( 114 listener); 115 116 super.onPause(); 117 } 118 119 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)120 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) 121 { 122 addPreferencesFromResource(R.xml.main); 123 } 124 125 @Override onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)126 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) 127 { 128 Log.v(TAG, "Shared preference changed: " + key); 129 } 130 updatePreferences()131 private void updatePreferences() 132 { 133 mShowAngleInUseSwitchPref.setChecked(mGlobalSettings.getShowAngleInUse()); 134 } 135 createShowAngleInUseSwitchPreference()136 private void createShowAngleInUseSwitchPreference() 137 { 138 final String showAngleInUseKey = 139 getContext().getString(R.string.pref_key_angle_in_use_dialog); 140 mShowAngleInUseSwitchPref = 141 (SwitchPreference) findPreference(showAngleInUseKey); 142 143 mShowAngleInUseSwitchPref.setOnPreferenceChangeListener( 144 new Preference.OnPreferenceChangeListener() { 145 @Override 146 public boolean onPreferenceChange(Preference preference, Object newValue) 147 { 148 if (DEBUG) 149 { 150 Log.v(TAG, "Show angle in use switch: " + newValue.toString()); 151 } 152 GlobalSettings.updateShowAngleInUse(getContext(), (Boolean) newValue); 153 return true; 154 } 155 }); 156 } 157 createInstalledAppsListPreference()158 private void createInstalledAppsListPreference() 159 { 160 final String selectDriverCategoryKey = 161 getContext().getString(R.string.pref_key_select_opengl_driver_category); 162 final PreferenceCategory preferenceCategory = 163 (PreferenceCategory) findPreference(selectDriverCategoryKey); 164 preferenceCategory.removeAll(); 165 mApplicationListPreferences.clear(); 166 167 final Context context = preferenceCategory.getContext(); 168 for (PackageInfo packageInfo : mInstalledPackages) 169 { 170 ListPreference listPreference = new ListPreference(context); 171 initListPreference(packageInfo, listPreference); 172 preferenceCategory.addPreference(listPreference); 173 } 174 } 175 queryInstalledPackages()176 private void queryInstalledPackages() 177 { 178 mInstalledPackages.clear(); 179 180 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 181 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 182 final PackageManager packageManager = getActivity().getPackageManager(); 183 184 List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(mainIntent, 0); 185 186 for (ResolveInfo resolveInfo : resolveInfos) 187 { 188 final String packageName = resolveInfo.activityInfo.packageName; 189 if (DEBUG) 190 { 191 Log.d(TAG, "Package found: " + packageName); 192 } 193 try 194 { 195 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) 196 { 197 PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 198 PackageManager.PackageInfoFlags.of(0)); 199 mInstalledPackages.add(packageInfo); 200 } 201 else 202 { 203 PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0); 204 mInstalledPackages.add(packageInfo); 205 } 206 } 207 catch (NameNotFoundException e) 208 { 209 Log.v(TAG, "Package not found: " + packageName); 210 } 211 } 212 213 Collections.sort(mInstalledPackages, displayNameComparator); 214 } 215 216 private final Comparator<PackageInfo> displayNameComparator = new Comparator<PackageInfo>() { 217 public final int compare(PackageInfo a, PackageInfo b) 218 { 219 return collator.compare(getAppName(a), getAppName(b)); 220 } 221 222 private final Collator collator = Collator.getInstance(); 223 }; 224 getAppName(PackageInfo packageInfo)225 private String getAppName(PackageInfo packageInfo) 226 { 227 return packageInfo.applicationInfo.loadLabel(getActivity().getPackageManager()).toString(); 228 } 229 initListPreference(PackageInfo packageInfo, ListPreference listPreference)230 private void initListPreference(PackageInfo packageInfo, ListPreference listPreference) 231 { 232 CharSequence[] drivers = getResources().getStringArray(R.array.driver_values); 233 listPreference.setEntries(drivers); 234 listPreference.setEntryValues(drivers); 235 236 final String packageName = packageInfo.packageName; 237 listPreference.setKey(packageName); 238 listPreference.setTitle(getAppName(packageInfo)); 239 240 final String driverSelectionValue = mSharedPreferences.getString(packageName, 241 GlobalSettings.DRIVER_SELECTION_DEFAULT); 242 listPreference.setDefaultValue(driverSelectionValue); 243 listPreference.setValue(driverSelectionValue); 244 listPreference.setSummary(driverSelectionValue); 245 246 final String dialogTitle = getContext().getString(R.string.select_opengl_driver_title); 247 listPreference.setDialogTitle(dialogTitle); 248 249 listPreference.setDialogIcon(packageInfo.applicationInfo.loadIcon(getActivity().getPackageManager())); 250 251 listPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 252 @Override 253 public boolean onPreferenceChange(Preference preference, Object newValue) 254 { 255 final ListPreference listPreference = (ListPreference) preference; 256 final String newDriverSelectionValue = newValue.toString(); 257 listPreference.setSummary(newDriverSelectionValue); 258 mGlobalSettings.updatePackageDriverSelection(preference.getKey(), newDriverSelectionValue); 259 return true; 260 } 261 }); 262 263 mApplicationListPreferences.add(listPreference); 264 } 265 } 266