1df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh/* 2df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* Copyright (C) 2015 The Android Open Source Project 3df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* 4df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* Licensed under the Apache License, Version 2.0 (the "License"); 5df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* you may not use this file except in compliance with the License. 6df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* You may obtain a copy of the License at 7df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* 8df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* http://www.apache.org/licenses/LICENSE-2.0 9df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* 10df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* Unless required by applicable law or agreed to in writing, software 11df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* distributed under the License is distributed on an "AS IS" BASIS, 12df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* See the License for the specific language governing permissions and 14df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh* limitations under the License. 15df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh*/ 16df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 17df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughpackage com.android.packageinstaller.permission.ui.wear; 18df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 190c49c07f1c83e9998fa0af2cd157633644358611Anthony Hughimport android.Manifest; 20df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.app.Activity; 21df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.app.Fragment; 22df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.content.Intent; 23df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.content.pm.PackageInfo; 24df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.content.pm.PackageManager; 251019d73896ca8ec9baac1492c08443c7a6339380Shijian Liimport android.content.pm.PermissionInfo; 26df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.os.Bundle; 27df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeonimport android.os.UserHandle; 28a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwanimport android.preference.Preference; 29a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwanimport android.preference.PreferenceFragment; 30df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeonimport android.preference.PreferenceScreen; 31a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwanimport android.preference.SwitchPreference; 32a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwanimport android.support.wearable.view.WearableDialogHelper; 33df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.util.Log; 34df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.view.LayoutInflater; 35df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.view.View; 36df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.view.ViewGroup; 37df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport android.widget.Toast; 38df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 39df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport com.android.packageinstaller.R; 40df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport com.android.packageinstaller.permission.model.AppPermissionGroup; 41df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport com.android.packageinstaller.permission.model.AppPermissions; 421019d73896ca8ec9baac1492c08443c7a6339380Shijian Liimport com.android.packageinstaller.permission.model.Permission; 43df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport com.android.packageinstaller.permission.utils.LocationUtils; 44df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport com.android.packageinstaller.permission.utils.SafetyNetLogger; 45275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Liimport com.android.packageinstaller.permission.utils.ArrayUtils; 46f9bf4f795615bac03d1b35a0138318473b1ef6bfSvet Ganovimport com.android.packageinstaller.permission.utils.Utils; 47df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeonimport com.android.settingslib.RestrictedLockUtils; 48df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeonimport com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 49df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 50df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport java.util.ArrayList; 51df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hughimport java.util.List; 52df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 53a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwanpublic final class AppPermissionsFragmentWear extends PreferenceFragment { 54a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private static final String LOG_TAG = "AppPermFragWear"; 55df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 56a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private static final String KEY_NO_PERMISSIONS = "no_permissions"; 57df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 58df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh public static AppPermissionsFragmentWear newInstance(String packageName) { 59df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh return setPackageName(new AppPermissionsFragmentWear(), packageName); 60df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 61df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 62df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh private static <T extends Fragment> T setPackageName(T fragment, String packageName) { 63df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh Bundle arguments = new Bundle(); 64df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); 65df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh fragment.setArguments(arguments); 66df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh return fragment; 67df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 68df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 691019d73896ca8ec9baac1492c08443c7a6339380Shijian Li private PackageManager mPackageManager; 70a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private List<AppPermissionGroup> mToggledGroups; 71a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private AppPermissions mAppPermissions; 72a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan 73a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private boolean mHasConfirmedRevoke; 74a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan 75df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon /** 76df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon * Provides click behavior for disabled preferences. 77df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon * We can't use {@link PreferenceFragment#onPreferenceTreeClick}, as the base 78df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon * {@link SwitchPreference} doesn't delegate to that method if the preference is disabled. 79df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon */ 80df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon private static class PermissionSwitchPreference extends SwitchPreference { 81df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon 82df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon private final Activity mActivity; 83df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon 84df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon public PermissionSwitchPreference(Activity activity) { 85df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon super(activity); 86df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon this.mActivity = activity; 87df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon } 88df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon 89df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon @Override 90df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon public void performClick(PreferenceScreen preferenceScreen) { 91df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon super.performClick(preferenceScreen); 92df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon if (!isEnabled()) { 93df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon // If setting the permission is disabled, it must have been locked 94df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon // by the device or profile owner. So get that info and pass it to 95df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon // the support details dialog. 96df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon EnforcedAdmin deviceOrProfileOwner = RestrictedLockUtils.getProfileOrDeviceOwner( 97df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon mActivity, UserHandle.myUserId()); 98df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon RestrictedLockUtils.sendShowAdminSupportDetailsIntent( 99df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon mActivity, deviceOrProfileOwner); 100df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon } 101df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon } 102df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon } 103df5a889da09c2584ef143b02198f9e38b28a223fMatt McKeon 104df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh @Override 105df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh public void onCreate(Bundle savedInstanceState) { 106df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh super.onCreate(savedInstanceState); 107df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 108df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); 109df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh Activity activity = getActivity(); 1101019d73896ca8ec9baac1492c08443c7a6339380Shijian Li mPackageManager = activity.getPackageManager(); 1111019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 112df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh PackageInfo packageInfo; 113df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 114df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh try { 1151019d73896ca8ec9baac1492c08443c7a6339380Shijian Li packageInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); 116df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } catch (PackageManager.NameNotFoundException e) { 117df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); 118df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh packageInfo = null; 119df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 120df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 121df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh if (packageInfo == null) { 122df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); 123df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh activity.finish(); 124df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh return; 125df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 126df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 127a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan mAppPermissions = new AppPermissions( 128a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan activity, packageInfo, null, true, () -> getActivity().finish()); 129df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 130a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan addPreferencesFromResource(R.xml.watch_permissions); 131df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh initializePermissionGroupList(); 132df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 133df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 134df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh @Override 135df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh public void onResume() { 136df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh super.onResume(); 137df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh mAppPermissions.refresh(); 138df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 139df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh // Also refresh the UI 140a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan for (final AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { 1418bb255379818d819589fb8ee63927042a4464da2Shijian Li if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) { 1428bb255379818d819589fb8ee63927042a4464da2Shijian Li for (PermissionInfo perm : getPermissionInfosFromGroup(group)) { 1438bb255379818d819589fb8ee63927042a4464da2Shijian Li setPreferenceCheckedIfPresent(perm.name, 1448bb255379818d819589fb8ee63927042a4464da2Shijian Li group.areRuntimePermissionsGranted(new String[]{ perm.name })); 1458bb255379818d819589fb8ee63927042a4464da2Shijian Li } 1468bb255379818d819589fb8ee63927042a4464da2Shijian Li } else { 1478bb255379818d819589fb8ee63927042a4464da2Shijian Li setPreferenceCheckedIfPresent(group.getName(), group.areRuntimePermissionsGranted()); 148a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan } 149df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 150df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 151df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 152df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh @Override 153a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan public void onPause() { 154a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan super.onPause(); 155a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan logAndClearToggledGroups(); 156df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 157df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 158df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh private void initializePermissionGroupList() { 159df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh final String packageName = mAppPermissions.getPackageInfo().packageName; 160df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups(); 1611019d73896ca8ec9baac1492c08443c7a6339380Shijian Li List<SwitchPreference> nonSystemPreferences = new ArrayList<>(); 162a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan 163a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan if (!groups.isEmpty()) { 164a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan getPreferenceScreen().removePreference(findPreference(KEY_NO_PERMISSIONS)); 165a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan } 166736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh 167a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan for (final AppPermissionGroup group : groups) { 168df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh if (!Utils.shouldShowPermission(group, packageName)) { 169df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh continue; 170df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 171df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 172736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); 173736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh 1741019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) { 1751019d73896ca8ec9baac1492c08443c7a6339380Shijian Li // If permission is controlled individually, we show all requested permission 1761019d73896ca8ec9baac1492c08443c7a6339380Shijian Li // inside this group. 1771019d73896ca8ec9baac1492c08443c7a6339380Shijian Li for (PermissionInfo perm : getPermissionInfosFromGroup(group)) { 1781019d73896ca8ec9baac1492c08443c7a6339380Shijian Li final SwitchPreference pref = createSwitchPreferenceForPermission(group, perm); 1791019d73896ca8ec9baac1492c08443c7a6339380Shijian Li showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform); 1801019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 181a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan } else { 1821019d73896ca8ec9baac1492c08443c7a6339380Shijian Li final SwitchPreference pref = createSwitchPreferenceForGroup(group); 1831019d73896ca8ec9baac1492c08443c7a6339380Shijian Li showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform); 1841019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 1851019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 186a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan 1871019d73896ca8ec9baac1492c08443c7a6339380Shijian Li // Now add the non-system settings to the end of the list 1881019d73896ca8ec9baac1492c08443c7a6339380Shijian Li for (SwitchPreference nonSystemPreference : nonSystemPreferences) { 1891019d73896ca8ec9baac1492c08443c7a6339380Shijian Li getPreferenceScreen().addPreference(nonSystemPreference); 1901019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 1911019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 192a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan 1931019d73896ca8ec9baac1492c08443c7a6339380Shijian Li private void showOrAddToNonSystemPreferences(SwitchPreference pref, 1941019d73896ca8ec9baac1492c08443c7a6339380Shijian Li List<SwitchPreference> nonSystemPreferences, // Mutate 1951019d73896ca8ec9baac1492c08443c7a6339380Shijian Li boolean isPlatform) { 1961019d73896ca8ec9baac1492c08443c7a6339380Shijian Li // The UI shows System settings first, then non-system settings 1971019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (isPlatform) { 1981019d73896ca8ec9baac1492c08443c7a6339380Shijian Li getPreferenceScreen().addPreference(pref); 1991019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } else { 2001019d73896ca8ec9baac1492c08443c7a6339380Shijian Li nonSystemPreferences.add(pref); 2011019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 2021019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 203736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh 2041019d73896ca8ec9baac1492c08443c7a6339380Shijian Li private SwitchPreference createSwitchPreferenceForPermission(AppPermissionGroup group, 2051019d73896ca8ec9baac1492c08443c7a6339380Shijian Li PermissionInfo perm) { 2061019d73896ca8ec9baac1492c08443c7a6339380Shijian Li final SwitchPreference pref = new PermissionSwitchPreference(getActivity()); 2071019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setKey(perm.name); 2081019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setTitle(perm.loadLabel(mPackageManager)); 2091019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setChecked(group.areRuntimePermissionsGranted(new String[]{ perm.name })); 2101019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setOnPreferenceChangeListener((p, newVal) -> { 2111019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if((Boolean) newVal) { 2121019d73896ca8ec9baac1492c08443c7a6339380Shijian Li group.grantRuntimePermissions(false, new String[]{ perm.name }); 213736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh } else { 214b8e4193e57bcaca51b08a88f3a67ef1d0641b75aShijian Li group.revokeRuntimePermissions(true, new String[]{ perm.name }); 215736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh } 216275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li 217275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName()) 218275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li && group.hasRuntimePermission()) { 219275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li // As long as one permission is changed in individually controlled group 220275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li // permissions, we will set user_fixed for non-granted permissions in that group. 221275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li // This avoids the system to automatically grant runtime permissions based on the 222275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li // fact that one of dangerous permission in that group is already granted. 223275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li String[] revokedPermissionsToFix = null; 224275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li final int permissionCount = group.getPermissions().size(); 225275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li 226275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li for (int i = 0; i < permissionCount; i++) { 227275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li Permission current = group.getPermissions().get(i); 228275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li if (!current.isGranted() && !current.isUserFixed()) { 229275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li revokedPermissionsToFix = ArrayUtils.appendString( 230275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li revokedPermissionsToFix, current.getName()); 231275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li } 232275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li } 233275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li 234275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li if (revokedPermissionsToFix != null) { 235275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li group.revokeRuntimePermissions(true, revokedPermissionsToFix); 236275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li } 237275897a5a576e8d16ebc245c0a299c5d9448a5a6Shijian Li } 2381019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return true; 2391019d73896ca8ec9baac1492c08443c7a6339380Shijian Li }); 2401019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return pref; 2411019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 242736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh 2431019d73896ca8ec9baac1492c08443c7a6339380Shijian Li private SwitchPreference createSwitchPreferenceForGroup(AppPermissionGroup group) { 2441019d73896ca8ec9baac1492c08443c7a6339380Shijian Li final SwitchPreference pref = new PermissionSwitchPreference(getActivity()); 2451019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 2461019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setKey(group.getName()); 2471019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setTitle(group.getLabel()); 2481019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setChecked(group.areRuntimePermissionsGranted()); 2491019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 2501019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (group.isPolicyFixed()) { 2511019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setEnabled(false); 2521019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } else { 2531019d73896ca8ec9baac1492c08443c7a6339380Shijian Li pref.setOnPreferenceChangeListener((p, newVal) -> { 2541019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (LocationUtils.isLocationGroupAndProvider( 2551019d73896ca8ec9baac1492c08443c7a6339380Shijian Li group.getName(), group.getApp().packageName)) { 2561019d73896ca8ec9baac1492c08443c7a6339380Shijian Li LocationUtils.showLocationDialog( 2571019d73896ca8ec9baac1492c08443c7a6339380Shijian Li getContext(), mAppPermissions.getAppLabel()); 2581019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return false; 2591019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 2601019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 2611019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if ((Boolean) newVal) { 2621019d73896ca8ec9baac1492c08443c7a6339380Shijian Li setPermission(group, pref, true); 2631019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } else { 2641019d73896ca8ec9baac1492c08443c7a6339380Shijian Li final boolean grantedByDefault = group.hasGrantedByDefaultPermission(); 2651019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (grantedByDefault 2661019d73896ca8ec9baac1492c08443c7a6339380Shijian Li || (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) { 2671019d73896ca8ec9baac1492c08443c7a6339380Shijian Li new WearableDialogHelper.DialogBuilder(getContext()) 2681019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .setNegativeIcon(R.drawable.confirm_button) 2691019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .setPositiveIcon(R.drawable.cancel_button) 2701019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .setNegativeButton(R.string.grant_dialog_button_deny_anyway, 2711019d73896ca8ec9baac1492c08443c7a6339380Shijian Li (dialog, which) -> { 2721019d73896ca8ec9baac1492c08443c7a6339380Shijian Li setPermission(group, pref, false); 2731019d73896ca8ec9baac1492c08443c7a6339380Shijian Li if (!group.hasGrantedByDefaultPermission()) { 2741019d73896ca8ec9baac1492c08443c7a6339380Shijian Li mHasConfirmedRevoke = true; 2751019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 2761019d73896ca8ec9baac1492c08443c7a6339380Shijian Li }) 2771019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .setPositiveButton(R.string.cancel, (dialog, which) -> {}) 2781019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .setMessage(grantedByDefault ? 2791019d73896ca8ec9baac1492c08443c7a6339380Shijian Li R.string.system_warning : R.string.old_sdk_deny_warning) 2801019d73896ca8ec9baac1492c08443c7a6339380Shijian Li .show(); 2811019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return false; 2821019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } else { 2831019d73896ca8ec9baac1492c08443c7a6339380Shijian Li setPermission(group, pref, false); 2841019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 2851019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 2861019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 2871019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return true; 2881019d73896ca8ec9baac1492c08443c7a6339380Shijian Li }); 289df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 2901019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return pref; 291df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 292df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 293a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan private void setPermission(AppPermissionGroup group, SwitchPreference pref, boolean grant) { 294a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan if (grant) { 295df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh group.grantRuntimePermissions(false); 296df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } else { 297a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan group.revokeRuntimePermissions(false); 2984b7427563d334dab50eb77028a78e709ea58880bAnthony Hugh } 299a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan addToggledGroup(group); 300a5d853c3bd4e4e84872fc802decd18e9c18408d2Michael Kwan pref.setChecked(grant); 301df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 302df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 303df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh private void addToggledGroup(AppPermissionGroup group) { 304df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh if (mToggledGroups == null) { 305df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh mToggledGroups = new ArrayList<>(); 306df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 307df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh // Double toggle is back to initial state. 308df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh if (mToggledGroups.contains(group)) { 309df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh mToggledGroups.remove(group); 310df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } else { 311df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh mToggledGroups.add(group); 312df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 313df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 314df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh 315736c82ba577f8f972ea4277357ae440b192dcd13Anthony Hugh private void logAndClearToggledGroups() { 316df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh if (mToggledGroups != null) { 317df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh String packageName = mAppPermissions.getPackageInfo().packageName; 318df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh SafetyNetLogger.logPermissionsToggled(packageName, mToggledGroups); 319df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh mToggledGroups = null; 320df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 321df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh } 3221019d73896ca8ec9baac1492c08443c7a6339380Shijian Li 3231019d73896ca8ec9baac1492c08443c7a6339380Shijian Li private List<PermissionInfo> getPermissionInfosFromGroup(AppPermissionGroup group) { 3241019d73896ca8ec9baac1492c08443c7a6339380Shijian Li ArrayList<PermissionInfo> permInfos = new ArrayList<>(group.getPermissions().size()); 3251019d73896ca8ec9baac1492c08443c7a6339380Shijian Li for(Permission perm : group.getPermissions()) { 3261019d73896ca8ec9baac1492c08443c7a6339380Shijian Li try { 3271019d73896ca8ec9baac1492c08443c7a6339380Shijian Li permInfos.add(mPackageManager.getPermissionInfo(perm.getName(), 0)); 3281019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } catch (PackageManager.NameNotFoundException e) { 3291019d73896ca8ec9baac1492c08443c7a6339380Shijian Li Log.w(LOG_TAG, "No permission:" + perm.getName()); 3301019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 3311019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 3321019d73896ca8ec9baac1492c08443c7a6339380Shijian Li return permInfos; 3331019d73896ca8ec9baac1492c08443c7a6339380Shijian Li } 3348bb255379818d819589fb8ee63927042a4464da2Shijian Li 3358bb255379818d819589fb8ee63927042a4464da2Shijian Li private void setPreferenceCheckedIfPresent(String preferenceKey, boolean checked) { 3368bb255379818d819589fb8ee63927042a4464da2Shijian Li Preference pref = findPreference(preferenceKey); 3378bb255379818d819589fb8ee63927042a4464da2Shijian Li if (pref instanceof SwitchPreference) { 3388bb255379818d819589fb8ee63927042a4464da2Shijian Li ((SwitchPreference) pref).setChecked(checked); 3398bb255379818d819589fb8ee63927042a4464da2Shijian Li } 3408bb255379818d819589fb8ee63927042a4464da2Shijian Li } 341df4d4542c2cf2fa0a7539412af2a99d60b1c2a15Anthony Hugh} 342