diff options
author | 2024-01-29 14:46:13 +0000 | |
---|---|---|
committer | 2024-02-15 15:15:06 +0000 | |
commit | 1f255895e7339c41539d542b746f776a95efb966 (patch) | |
tree | 6f984be95d5ffb1d2a6d755f691fbecb4940bfc4 | |
parent | 65f8b5ac49e1ba00d8365d107bc828d8ab3b33ea (diff) |
Replace ECM AppOps call with service
A new ECM service was introcuded in changeId
I831391e4437b51b3312b5273a2360bd029a3d8ee.
We begin calling it, and update/cleanup method signatures to match.
Note: There are two feature flags:
1. enhancedConfirmationModeApisEnabled - read only, protects the
mainline API.
2. extendEcmToAllSettings - runtime - gates calls to the above APIs.
We use both so we can ramp up in teamfood as needed.
Bug: 297372999
Test: Tested on device
Test: atest SpaPrivilegedLibTests
Test: atest com.android.settings.applications.specialaccess.notificationaccess
Test: atest com.android.settings.datausage
Test: atest PremiumSmsAccessTest
Test: atest RestrictedPreferenceHelperTest
Change-Id: I4125e71078a1a06e954bfc317c344e1016406ffb
11 files changed, 130 insertions, 79 deletions
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java index 5b39f4ee1541..18e8fc38ddb0 100644 --- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java +++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java @@ -219,7 +219,6 @@ public class RestrictedLockUtils { } } - /** * Shows restricted setting dialog. * diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt index 9432d5995151..6b1893c73b3f 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt @@ -31,7 +31,6 @@ import kotlinx.coroutines.flow.flowOn data class EnhancedConfirmation( val key: String, - val uid: Int, val packageName: String, ) data class Restrictions( @@ -91,7 +90,7 @@ internal class RestrictionsProviderImpl( restrictions.enhancedConfirmation?.let { ec -> RestrictedLockUtilsInternal .checkIfRequiresEnhancedConfirmation(context, ec.key, - ec.uid, ec.packageName) + ec.packageName) ?.let { intent -> return BlockedByEcmImpl(context = context, intent = intent) } } diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt index 74b556ea106e..27e00c05c33f 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt @@ -159,7 +159,6 @@ internal fun <T : AppRecord> TogglePermissionAppListModel<T>.TogglePermissionApp keys = switchRestrictionKeys, enhancedConfirmation = enhancedConfirmationKey?.let { EnhancedConfirmation( key = it, - uid = checkNotNull(applicationInfo).uid, packageName = packageName) }) RestrictedSwitchPreference(switchModel, restrictions, restrictionsProviderFactory) InfoPageAdditionalContent(record, isAllowed) diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt index 4b474379c54b..2e8b76a03722 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt @@ -150,15 +150,13 @@ internal class TogglePermissionInternalAppListModel<T : AppRecord>( @Composable fun getSummary(record: T): () -> String { - val restrictions = remember(record.app.userId, - record.app.uid, record.app.packageName) { + val restrictions = remember(record.app.userId, record.app.packageName) { Restrictions( userId = record.app.userId, keys = listModel.switchRestrictionKeys, enhancedConfirmation = listModel.enhancedConfirmationKey?.let { EnhancedConfirmation( key = it, - uid = record.app.uid, packageName = record.app.packageName) }) } diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java index ade40d8b01e2..6578eb7d50a6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java @@ -19,7 +19,6 @@ package com.android.settingslib; import android.content.Context; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.preference.DropDownPreference; import androidx.preference.PreferenceViewHolder; @@ -34,13 +33,12 @@ public class RestrictedDropDownPreference extends DropDownPreference { /** * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * package. Marks the preference as disabled if so. - * @param restriction The key identifying the setting - * @param packageName the package to check the restriction for - * @param uid the uid of the package + * @param settingIdentifier The key identifying the setting + * @param packageName the package to check the settingIdentifier for */ - public void checkEcmRestrictionAndSetDisabled(@NonNull String restriction, - @Nullable String packageName, int uid) { - mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid); + public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier, + @NonNull String packageName) { + mHelper.checkEcmRestrictionAndSetDisabled(settingIdentifier, packageName); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java index d9024575f247..f36da19afd30 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java @@ -23,11 +23,11 @@ import static android.app.role.RoleManager.ROLE_FINANCED_DEVICE_KIOSK; import static com.android.settingslib.Utils.getColorAttrDefaultColor; -import android.Manifest; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.admin.DevicePolicyManager; +import android.app.ecm.EnhancedConfirmationManager; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; @@ -42,12 +42,10 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager.EnforcingUser; -import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; -import android.util.ArraySet; import android.util.Log; import android.view.MenuItem; import android.widget.TextView; @@ -60,7 +58,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import java.util.List; -import java.util.Set; /** * Utility class to host methods usable in adding a restricted padlock icon and showing admin @@ -70,24 +67,11 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { private static final String LOG_TAG = "RestrictedLockUtils"; private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); - private static final Set<String> ECM_KEYS = new ArraySet<>(); // TODO(b/281701062): reference role name from role manager once its exposed. private static final String ROLE_DEVICE_LOCK_CONTROLLER = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; - static { - if (android.security.Flags.extendEcmToAllSettings()) { - ECM_KEYS.add(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW); - ECM_KEYS.add(AppOpsManager.OPSTR_GET_USAGE_STATS); - ECM_KEYS.add(AppOpsManager.OPSTR_LOADER_USAGE_STATS); - ECM_KEYS.add(Manifest.permission.BIND_DEVICE_ADMIN); - } - - ECM_KEYS.add(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS); - ECM_KEYS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE); - } - /** * @return drawables for displaying with settings that are locked by a device admin. */ @@ -112,32 +96,63 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { */ @Nullable public static Intent checkIfRequiresEnhancedConfirmation(@NonNull Context context, - @NonNull String restriction, - int uid, - @Nullable String packageName) { - // TODO(b/297372999): Replace with call to mainline module once ready + @NonNull String settingIdentifier, @NonNull String packageName) { - if (!ECM_KEYS.contains(restriction)) { + if (!android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() + || !android.security.Flags.extendEcmToAllSettings()) { return null; } - final AppOpsManager appOps = (AppOpsManager) context - .getSystemService(Context.APP_OPS_SERVICE); - final int mode = appOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, - uid, packageName, null, null); - final boolean ecmEnabled = context.getResources().getBoolean( - com.android.internal.R.bool.config_enhancedConfirmationModeEnabled); - if (ecmEnabled && mode != AppOpsManager.MODE_ALLOWED) { - final Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(Intent.EXTRA_UID, uid); - return intent; + EnhancedConfirmationManager ecManager = (EnhancedConfirmationManager) context + .getSystemService(Context.ECM_ENHANCED_CONFIRMATION_SERVICE); + try { + if (ecManager.isRestricted(packageName, settingIdentifier)) { + return ecManager.createRestrictedSettingDialogIntent( + packageName, settingIdentifier); + } + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOG_TAG, "package not found: " + packageName, e); } return null; } /** + * <p>This is {@code true} when the setting is a protected setting (i.e., a sensitive resource), + * and the app is restricted (i.e., considered dangerous), and the user has not yet cleared the + * app's restriction status (i.e., by clicking "Allow restricted settings" for this app). * + */ + public static boolean isEnhancedConfirmationRestricted(@NonNull Context context, + @NonNull String settingIdentifier, @NonNull String packageName) { + if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() + && android.security.Flags.extendEcmToAllSettings()) { + try { + return context.getSystemService(EnhancedConfirmationManager.class) + .isRestricted(packageName, settingIdentifier); + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOG_TAG, "Exception when retrieving package:" + packageName, e); + return false; + } + } else { + try { + if (!settingIdentifier.equals(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE)) { + return false; + } + int uid = context.getPackageManager().getPackageUid(packageName, 0); + final int mode = context.getSystemService(AppOpsManager.class) + .noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, + uid, packageName); + final boolean ecmEnabled = context.getResources().getBoolean( + com.android.internal.R.bool.config_enhancedConfirmationModeEnabled); + return ecmEnabled && mode != AppOpsManager.MODE_ALLOWED; + } catch (Exception e) { + // Fallback in case if app ops is not available in testing. + return false; + } + } + } + + /** * Checks if a restriction is enforced on a user and returns the enforced admin and * admin userId. * diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java index 50e3bd08026c..495410b0a8ae 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java @@ -23,6 +23,7 @@ import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; +import androidx.annotation.NonNull; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceViewHolder; @@ -99,12 +100,12 @@ public class RestrictedPreference extends TwoTargetPreference { /** * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * package. Marks the preference as disabled if so. - * @param restriction The key identifying the setting - * @param packageName the package to check the restriction for - * @param uid the uid of the package + * @param settingIdentifier The key identifying the setting + * @param packageName the package to check the settingIdentifier for */ - public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) { - mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid); + public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier, + @NonNull String packageName) { + mHelper.checkEcmRestrictionAndSetDisabled(settingIdentifier, packageName); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 4eed01ccbc33..734b92c7ac6e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -31,6 +31,8 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; @@ -43,9 +45,17 @@ import com.android.settingslib.utils.BuildCompatUtils; * by device admins via user restrictions. */ public class RestrictedPreferenceHelper { + private static final String TAG = "RestrictedPreferenceHelper"; + private final Context mContext; private final Preference mPreference; String packageName; + + /** + * @deprecated TODO(b/308921175): This will be deleted with the + * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new + * code. + */ int uid; private boolean mDisabledByAdmin; @@ -148,14 +158,15 @@ public class RestrictedPreferenceHelper { return true; } if (mDisabledByEcm) { - if (android.security.Flags.extendEcmToAllSettings()) { + if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() + && android.security.Flags.extendEcmToAllSettings()) { mContext.startActivity(mDisabledByEcmIntent); return true; + } else { + RestrictedLockUtilsInternal.sendShowRestrictedSettingDialogIntent(mContext, + packageName, uid); + return true; } - - RestrictedLockUtilsInternal.sendShowRestrictedSettingDialogIntent(mContext, packageName, - uid); - return true; } return false; } @@ -184,14 +195,14 @@ public class RestrictedPreferenceHelper { /** * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * package. Marks the preference as disabled if so. - * @param restriction The key identifying the setting - * @param packageName the package to check the restriction for - * @param uid the uid of the package + * @param settingIdentifier The key identifying the setting + * @param packageName the package to check the settingIdentifier for */ - public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) { - updatePackageDetails(packageName, uid); + public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier, + @NonNull String packageName) { + updatePackageDetails(packageName, android.os.Process.INVALID_UID); Intent intent = RestrictedLockUtilsInternal.checkIfRequiresEnhancedConfirmation( - mContext, restriction, uid, packageName); + mContext, settingIdentifier, packageName); setDisabledByEcm(intent); } @@ -240,7 +251,7 @@ public class RestrictedPreferenceHelper { * be disabled. * @return true if the disabled state was changed. */ - public boolean setDisabledByEcm(Intent disabledIntent) { + public boolean setDisabledByEcm(@Nullable Intent disabledIntent) { boolean disabled = disabledIntent != null; boolean changed = false; if (mDisabledByEcm != disabled) { diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java index 70ece0fa8076..0c54c1903742 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java @@ -200,12 +200,12 @@ public class RestrictedSwitchPreference extends SwitchPreferenceCompat { /** * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * package. Marks the preference as disabled if so. - * @param restriction The key identifying the setting - * @param packageName the package to check the restriction for - * @param uid the uid of the package + * @param settingIdentifier The key identifying the setting + * @param packageName the package to check the settingIdentifier for */ - public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) { - mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid); + public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier, + @NonNull String packageName) { + mHelper.checkEcmRestrictionAndSetDisabled(settingIdentifier, packageName); } @Override diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java index e9f825beb0bc..7ad54e187ae5 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java @@ -94,7 +94,7 @@ public class RestrictedPreferenceHelperTest { when(mViewHolder.itemView.findViewById(android.R.id.summary)) .thenReturn(summaryView); - mHelper.setDisabledByEcm(new Intent()); + mHelper.setDisabledByEcm(mock(Intent.class)); mHelper.onBindViewHolder(mViewHolder); verify(mPreference).setSummary(R.string.disabled_by_app_ops_text); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 3442a6ac56b3..46db624cf3c1 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -64,6 +64,7 @@ import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.RemoteAction; import android.app.admin.DevicePolicyManager; +import android.app.ecm.EnhancedConfirmationManager; import android.appwidget.AppWidgetManagerInternal; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; @@ -112,6 +113,7 @@ import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.ArraySet; import android.util.IntArray; +import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -4394,13 +4396,29 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // permittedServices null means all accessibility services are allowed. boolean allowed = permittedServices == null || permittedServices.contains(packageName); if (allowed) { - final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); - final int mode = appOps.noteOpNoThrow( - AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, - uid, packageName, /* attributionTag= */ null, /* message= */ null); - final boolean ecmEnabled = mContext.getResources().getBoolean( - R.bool.config_enhancedConfirmationModeEnabled); - return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED; + if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() + && android.security.Flags.extendEcmToAllSettings()) { + try { + return !mContext.getSystemService(EnhancedConfirmationManager.class) + .isRestricted(packageName, + AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE); + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOG_TAG, "Exception when retrieving package:" + packageName, e); + return false; + } + } else { + try { + final int mode = mContext.getSystemService(AppOpsManager.class) + .noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, + uid, packageName); + final boolean ecmEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enhancedConfirmationModeEnabled); + return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED; + } catch (Exception e) { + // Fallback in case if app ops is not available in testing. + return false; + } + } } return false; } finally { @@ -4423,8 +4441,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; } - RestrictedLockUtils.sendShowRestrictedSettingDialogIntent(mContext, - packageName, uid); + if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() + && android.security.Flags.extendEcmToAllSettings()) { + try { + Intent settingDialogIntent = mContext + .getSystemService(EnhancedConfirmationManager.class) + .createRestrictedSettingDialogIntent(packageName, + AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE); + mContext.startActivity(settingDialogIntent); + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOG_TAG, "Exception when retrieving package:" + packageName, e); + } + } else { + RestrictedLockUtils.sendShowRestrictedSettingDialogIntent(mContext, + packageName, uid); + } return true; } |