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: I945ec51df5cd63de548a8ffdd1acc4f09f2301e5
This commit is contained in:
Hani Kazmi
2024-01-29 14:59:22 +00:00
parent 96ab2b9e25
commit 206300962f
23 changed files with 215 additions and 129 deletions

View File

@@ -21,7 +21,6 @@ import android.app.AppOpsManager;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
public class ActionDisabledByAppOpsDialog extends Activity public class ActionDisabledByAppOpsDialog extends Activity
implements DialogInterface.OnDismissListener { implements DialogInterface.OnDismissListener {

View File

@@ -43,6 +43,7 @@ import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment; import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.accessibility.AccessibilityUtils; import com.android.settingslib.accessibility.AccessibilityUtils;
import java.util.List; import java.util.List;
@@ -164,16 +165,9 @@ public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
if (permittedServices != null && !permittedServices.contains(packageName)) { if (permittedServices != null && !permittedServices.contains(packageName)) {
return false; return false;
} }
try {
final int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, return !RestrictedLockUtilsInternal.isEnhancedConfirmationRestricted(getContext(),
uid, packageName); packageName, AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
final boolean ecmEnabled = getContext().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 true;
}
} }
private AccessibilityServiceInfo getAccessibilityServiceInfo(ComponentName componentName) { private AccessibilityServiceInfo getAccessibilityServiceInfo(ComponentName componentName) {

View File

@@ -235,10 +235,11 @@ public class RestrictedPreferenceHelper {
boolean serviceAllowed = permittedServices == null || permittedServices.contains( boolean serviceAllowed = permittedServices == null || permittedServices.contains(
preference.getPackageName()); preference.getPackageName());
if (android.security.Flags.extendEcmToAllSettings()) { if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
&& android.security.Flags.extendEcmToAllSettings()) {
preference.checkEcmRestrictionAndSetDisabled( preference.checkEcmRestrictionAndSetDisabled(
AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE, AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE,
preference.getPackageName(), preference.getUid()); preference.getPackageName());
if (preference.isDisabledByEcm()) { if (preference.isDisabledByEcm()) {
serviceAllowed = false; serviceAllowed = false;
} }
@@ -257,40 +258,39 @@ public class RestrictedPreferenceHelper {
preference.setEnabled(false); preference.setEnabled(false);
} }
} }
return;
}
boolean appOpsAllowed;
if (serviceAllowed) {
try {
final int mode = mAppOps.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
preference.getUid(), preference.getPackageName());
final boolean ecmEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
serviceAllowed = appOpsAllowed;
} catch (Exception e) {
// Allow service in case if app ops is not available in testing.
appOpsAllowed = true;
}
} else { } else {
appOpsAllowed = false; boolean appOpsAllowed;
} if (serviceAllowed) {
if (serviceAllowed || serviceEnabled) { try {
preference.setEnabled(true); final int mode = mAppOps.noteOpNoThrow(
} else { AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
// Disable accessibility service that are not permitted. preference.getUid(), preference.getPackageName());
final RestrictedLockUtils.EnforcedAdmin admin = final boolean ecmEnabled = mContext.getResources().getBoolean(
RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed( com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
mContext, preference.getPackageName(), UserHandle.myUserId()); appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
serviceAllowed = appOpsAllowed;
if (admin != null) { } catch (Exception e) {
preference.setDisabledByAdmin(admin); // Allow service in case if app ops is not available in testing.
} else if (!appOpsAllowed) { appOpsAllowed = true;
preference.setDisabledByAppOps(true); }
} else { } else {
preference.setEnabled(false); appOpsAllowed = false;
}
if (serviceAllowed || serviceEnabled) {
preference.setEnabled(true);
} else {
// Disable accessibility service that are not permitted.
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
mContext, preference.getPackageName(), UserHandle.myUserId());
if (admin != null) {
preference.setDisabledByAdmin(admin);
} else if (!appOpsAllowed) {
preference.setDisabledByAppOps(true);
} else {
preference.setEnabled(false);
}
} }
} }
} }

View File

@@ -174,7 +174,7 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
if (shouldEnable && !hasAccess) { if (shouldEnable && !hasAccess) {
mSwitchPref.checkEcmRestrictionAndSetDisabled(AppOpsManager.OPSTR_GET_USAGE_STATS, mSwitchPref.checkEcmRestrictionAndSetDisabled(AppOpsManager.OPSTR_GET_USAGE_STATS,
mPackageName, mPackageInfo.applicationInfo.uid); mPackageName);
shouldEnable = !mSwitchPref.isDisabledByEcm(); shouldEnable = !mSwitchPref.isDisabledByEcm();
} }

View File

@@ -24,6 +24,7 @@ import android.app.Activity;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.ecm.EnhancedConfirmationManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -490,12 +491,23 @@ public class AppInfoDashboardFragment extends DashboardFragment
return true; return true;
case ACCESS_RESTRICTED_SETTINGS: case ACCESS_RESTRICTED_SETTINGS:
showLockScreen(getContext(), () -> { showLockScreen(getContext(), () -> {
final AppOpsManager appOpsManager = getContext().getSystemService( if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
AppOpsManager.class); && android.security.Flags.extendEcmToAllSettings()) {
appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, EnhancedConfirmationManager manager = getContext().getSystemService(
getUid(), EnhancedConfirmationManager.class);
getPackageName(), try {
AppOpsManager.MODE_ALLOWED); manager.clearRestriction(getPackageName());
} catch (NameNotFoundException e) {
Log.e(TAG, "Exception when retrieving package:" + getPackageName(), e);
}
} else {
final AppOpsManager appOpsManager = getContext().getSystemService(
AppOpsManager.class);
appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
getUid(),
getPackageName(),
AppOpsManager.MODE_ALLOWED);
}
getActivity().invalidateOptionsMenu(); getActivity().invalidateOptionsMenu();
final String toastString = getContext().getString( final String toastString = getContext().getString(
R.string.toast_allows_restricted_settings_successfully, R.string.toast_allows_restricted_settings_successfully,
@@ -527,14 +539,25 @@ public class AppInfoDashboardFragment extends DashboardFragment
} }
private boolean shouldShowAccessRestrictedSettings() { private boolean shouldShowAccessRestrictedSettings() {
try { if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
final int mode = getSystemService(AppOpsManager.class).noteOpNoThrow( && android.security.Flags.extendEcmToAllSettings()) {
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, getUid(), try {
getPackageName()); return getSystemService(EnhancedConfirmationManager.class)
return mode == AppOpsManager.MODE_IGNORED; .isClearRestrictionAllowed(getPackageName());
} catch (Exception e) { } catch (NameNotFoundException e) {
// Fallback in case if app ops is not available in testing. Log.e(TAG, "Exception when retrieving package:" + getPackageName(), e);
return false; return false;
}
} else {
try {
final int mode = getSystemService(AppOpsManager.class).noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, getUid(),
getPackageName());
return mode == AppOpsManager.MODE_IGNORED;
} catch (Exception e) {
// Fallback in case if app ops is not available in testing.
return false;
}
} }
} }

View File

@@ -210,7 +210,7 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
pref.setOnPreferenceChangeListener((preference, newValue) -> false); pref.setOnPreferenceChangeListener((preference, newValue) -> false);
pref.setSingleLineTitle(true); pref.setSingleLineTitle(true);
pref.checkEcmRestrictionAndSetDisabled(Manifest.permission.BIND_DEVICE_ADMIN, pref.checkEcmRestrictionAndSetDisabled(Manifest.permission.BIND_DEVICE_ADMIN,
item.getPackageName(), item.getUid()); item.getPackageName());
} }
/** /**

View File

@@ -24,6 +24,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
@@ -42,7 +43,7 @@ public class ApprovalPreferenceController extends BasePreferenceController {
private NotificationManager mNm; private NotificationManager mNm;
private PackageManager mPm; private PackageManager mPm;
// The appOp representing this preference // The appOp representing this preference
private String mAppOpStr; private String mSettingIdentifier;
public ApprovalPreferenceController(Context context, String key) { public ApprovalPreferenceController(Context context, String key) {
super(context, key); super(context, key);
@@ -76,8 +77,9 @@ public class ApprovalPreferenceController extends BasePreferenceController {
/** /**
* Set the associated appOp for the Setting * Set the associated appOp for the Setting
*/ */
public ApprovalPreferenceController setAppOpStr(String appOpStr) { @NonNull
mAppOpStr = appOpStr; public ApprovalPreferenceController setSettingIdentifier(@NonNull String settingIdentifier) {
mSettingIdentifier = settingIdentifier;
return this; return this;
} }
@@ -118,14 +120,15 @@ public class ApprovalPreferenceController extends BasePreferenceController {
} }
}); });
if (android.security.Flags.extendEcmToAllSettings()) { if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
&& android.security.Flags.extendEcmToAllSettings()) {
if (!isAllowedCn && !isEnabled) { if (!isAllowedCn && !isEnabled) {
preference.setEnabled(false); preference.setEnabled(false);
} else if (isEnabled) { } else if (isEnabled) {
preference.setEnabled(true); preference.setEnabled(true);
} else { } else {
preference.checkEcmRestrictionAndSetDisabled(mAppOpStr, preference.checkEcmRestrictionAndSetDisabled(mSettingIdentifier,
mCn.getPackageName(), mPkgInfo.applicationInfo.uid); mCn.getPackageName());
} }
} else { } else {
preference.updateState( preference.updateState(

View File

@@ -103,7 +103,7 @@ public class NotificationAccessDetails extends DashboardFragment {
.setCn(mComponentName) .setCn(mComponentName)
.setNm(context.getSystemService(NotificationManager.class)) .setNm(context.getSystemService(NotificationManager.class))
.setPm(mPm) .setPm(mPm)
.setAppOpStr(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS) .setSettingIdentifier(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS)
.setParent(this); .setParent(this);
use(HeaderPreferenceController.class) use(HeaderPreferenceController.class)
.setFragment(this) .setFragment(this)

View File

@@ -226,8 +226,7 @@ public class PremiumSmsAccess extends EmptyTextSettings
}); });
setValue(String.valueOf(getCurrentValue())); setValue(String.valueOf(getCurrentValue()));
setSummary("%s"); setSummary("%s");
this.checkEcmRestrictionAndSetDisabled(ECM_RESTRICTION_KEY, appEntry.info.packageName, this.checkEcmRestrictionAndSetDisabled(ECM_RESTRICTION_KEY, appEntry.info.packageName);
appEntry.info.uid);
} }
private int getCurrentValue() { private int getCurrentValue() {

View File

@@ -20,6 +20,7 @@ import android.graphics.drawable.Drawable;
import android.os.UserHandle; import android.os.UserHandle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
@@ -37,7 +38,7 @@ import com.android.settingslib.widget.AppSwitchPreference;
public class UnrestrictedDataAccessPreference extends AppSwitchPreference implements public class UnrestrictedDataAccessPreference extends AppSwitchPreference implements
DataSaverBackend.Listener { DataSaverBackend.Listener {
private static final String ECM_RESTRICTION_KEY = "android:unrestricted_data_access"; private static final String ECM_SETTING_IDENTIFIER = "android:unrestricted_data_access";
private final ApplicationsState mApplicationsState; private final ApplicationsState mApplicationsState;
private final AppEntry mEntry; private final AppEntry mEntry;
@@ -60,8 +61,7 @@ public class UnrestrictedDataAccessPreference extends AppSwitchPreference implem
mParentFragment = parentFragment; mParentFragment = parentFragment;
setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled( setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled(
context, entry.info.packageName, UserHandle.getUserId(entry.info.uid))); context, entry.info.packageName, UserHandle.getUserId(entry.info.uid)));
mHelper.checkEcmRestrictionAndSetDisabled(ECM_RESTRICTION_KEY, entry.info.packageName, mHelper.checkEcmRestrictionAndSetDisabled(ECM_SETTING_IDENTIFIER, entry.info.packageName);
entry.info.uid);
updateState(); updateState();
setKey(generateKey(mEntry)); setKey(generateKey(mEntry));
@@ -183,10 +183,9 @@ public class UnrestrictedDataAccessPreference extends AppSwitchPreference implem
* Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
* package. Marks the preference as disabled if so. * package. Marks the preference as disabled if so.
* @param packageName the package to check the restriction for * @param packageName the package to check the restriction for
* @param uid the uid of the package
*/ */
public void checkEcmRestrictionAndSetDisabled(@Nullable String packageName, int uid) { public void checkEcmRestrictionAndSetDisabled(@NonNull String packageName) {
mHelper.checkEcmRestrictionAndSetDisabled(ECM_RESTRICTION_KEY, packageName, uid); mHelper.checkEcmRestrictionAndSetDisabled(ECM_SETTING_IDENTIFIER, packageName);
} }
// Sets UI state based on allowlist/denylist status. // Sets UI state based on allowlist/denylist status.

View File

@@ -151,8 +151,7 @@ public class UnrestrictedDataAccessPreferenceController extends BasePreferenceCo
} else { } else {
preference.setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled(mContext, preference.setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled(mContext,
entry.info.packageName, UserHandle.getUserId(entry.info.uid))); entry.info.packageName, UserHandle.getUserId(entry.info.uid)));
preference.checkEcmRestrictionAndSetDisabled(entry.info.packageName, preference.checkEcmRestrictionAndSetDisabled(entry.info.packageName);
entry.info.uid);
preference.updateState(); preference.updateState();
} }
preference.setOrder(i); preference.setOrder(i);

View File

@@ -134,7 +134,7 @@ public class ZenAccessSettings extends EmptyTextSettings implements
// Not auto approved, update summary according to notification backend. // Not auto approved, update summary according to notification backend.
pref.setSummary(getPreferenceSummary(pkg)); pref.setSummary(getPreferenceSummary(pkg));
pref.checkEcmRestrictionAndSetDisabled( pref.checkEcmRestrictionAndSetDisabled(
android.Manifest.permission.MANAGE_NOTIFICATIONS, app.packageName, app.uid); android.Manifest.permission.MANAGE_NOTIFICATIONS, app.packageName);
} }
pref.setOnPreferenceClickListener(preference -> { pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment( AppInfoBase.startAppInfoFragment(

View File

@@ -17,6 +17,7 @@
package com.android.settings.spa.app.appinfo package com.android.settings.spa.app.appinfo
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.ecm.EnhancedConfirmationManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.UserManager import android.os.UserManager
@@ -90,12 +91,18 @@ fun AppInfoSettingsMoreOptions(
private fun ApplicationInfo.allowRestrictedSettings(context: Context, onSuccess: () -> Unit) { private fun ApplicationInfo.allowRestrictedSettings(context: Context, onSuccess: () -> Unit) {
AppInfoDashboardFragment.showLockScreen(context) { AppInfoDashboardFragment.showLockScreen(context) {
context.appOpsManager.setMode( if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, && android.security.Flags.extendEcmToAllSettings()) {
uid, val manager = context.getSystemService(EnhancedConfirmationManager::class.java)!!
packageName, manager.clearRestriction(packageName)
AppOpsManager.MODE_ALLOWED, } else {
) context.appOpsManager.setMode(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
uid,
packageName,
AppOpsManager.MODE_ALLOWED,
)
}
onSuccess() onSuccess()
val toastString = context.getString( val toastString = context.getString(
R.string.toast_allows_restricted_settings_successfully, R.string.toast_allows_restricted_settings_successfully,
@@ -137,7 +144,7 @@ private suspend fun ApplicationInfo.getMoreOptionsState(
) )
} }
val shouldShowAccessRestrictedSettingsDeferred = async { val shouldShowAccessRestrictedSettingsDeferred = async {
shouldShowAccessRestrictedSettings(context.appOpsManager) shouldShowAccessRestrictedSettings(context)
} }
val isProfileOrDeviceOwner = val isProfileOrDeviceOwner =
Utils.isProfileOrDeviceOwner(context.userManager, context.devicePolicyManager, packageName) Utils.isProfileOrDeviceOwner(context.userManager, context.devicePolicyManager, packageName)
@@ -169,7 +176,14 @@ private fun ApplicationInfo.isOtherUserHasInstallPackage(
.filter { it.id != userId } .filter { it.id != userId }
.any { packageManagers.isPackageInstalledAsUser(packageName, it.id) } .any { packageManagers.isPackageInstalledAsUser(packageName, it.id) }
private fun ApplicationInfo.shouldShowAccessRestrictedSettings(appOpsManager: AppOpsManager) = private fun ApplicationInfo.shouldShowAccessRestrictedSettings(context: Context): Boolean {
appOpsManager.noteOpNoThrow( return if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid, packageName, null, null && android.security.Flags.extendEcmToAllSettings()) {
) == AppOpsManager.MODE_IGNORED val manager = context.getSystemService(EnhancedConfirmationManager::class.java)!!
manager.isClearRestrictionAllowed(packageName)
} else {
context.appOpsManager.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid, packageName, null, null
) == AppOpsManager.MODE_IGNORED
}
}

View File

@@ -153,8 +153,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
}); });
pref.setKey(cn.flattenToString()); pref.setKey(cn.flattenToString());
if (!pref.isChecked()) { if (!pref.isChecked()) {
pref.checkEcmRestrictionAndSetDisabled(mConfig.permission, service.packageName, pref.checkEcmRestrictionAndSetDisabled(mConfig.permission, service.packageName);
service.applicationInfo.uid);
} }
screen.addPreference(pref); screen.addPreference(pref);
} }

View File

@@ -21,6 +21,7 @@ import android.os.UserHandle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
@@ -128,11 +129,11 @@ public class RestrictedAppPreference extends AppPreference {
/** /**
* Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
* package. Marks the preference as disabled if so. * package. Marks the preference as disabled if so.
* @param restriction The key identifying the setting * @param settingIdentifier The key identifying the setting
* @param packageName the package to check the restriction for * @param packageName the package to check the settingIdentifier for
* @param uid the uid of the package
*/ */
public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) { public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier,
mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid); @NonNull String packageName) {
mHelper.checkEcmRestrictionAndSetDisabled(settingIdentifier, packageName);
} }
} }

View File

@@ -38,6 +38,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -57,7 +58,10 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** Tests for {@link AccessibilityDetailsSettingsFragment}. */ /** Tests for {@link AccessibilityDetailsSettingsFragment}. */
@Config(shadows = ShadowDevicePolicyManager.class) @Config(shadows = {
ShadowDevicePolicyManager.class,
ShadowRestrictedLockUtilsInternal.class
})
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class AccessibilityDetailsSettingsFragmentTest { public class AccessibilityDetailsSettingsFragmentTest {
private static final String PACKAGE_NAME = "com.foo.bar"; private static final String PACKAGE_NAME = "com.foo.bar";

View File

@@ -52,6 +52,7 @@ import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowApplicationPackageManager; import com.android.settings.testutils.shadow.ShadowApplicationPackageManager;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -87,6 +88,7 @@ import java.util.List;
ShadowUserManager.class, ShadowUserManager.class,
ShadowColorDisplayManager.class, ShadowColorDisplayManager.class,
ShadowApplicationPackageManager.class, ShadowApplicationPackageManager.class,
ShadowRestrictedLockUtilsInternal.class,
}) })
public class AccessibilitySettingsTest { public class AccessibilitySettingsTest {
private static final String PACKAGE_NAME = "com.android.test"; private static final String PACKAGE_NAME = "com.android.test";

View File

@@ -31,8 +31,10 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.security.Flags;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -81,6 +83,8 @@ public class RestrictedPreferenceHelperTest {
@Rule @Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Test @Test
public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() { public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
@@ -96,8 +100,9 @@ public class RestrictedPreferenceHelperTest {
} }
@Test @Test
@RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() { public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() {
mSetFlagsRule.enableFlags(Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS);
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs( ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(
mServiceInfo.getResolveInfo().serviceInfo.packageName); mServiceInfo.getResolveInfo().serviceInfo.packageName);
final List<AccessibilityServiceInfo> infoList = new ArrayList<>( final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
@@ -111,8 +116,9 @@ public class RestrictedPreferenceHelperTest {
} }
@Test @Test
@RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() { public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() {
mSetFlagsRule.enableFlags(Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS);
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(); ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
final List<AccessibilityServiceInfo> infoList = new ArrayList<>( final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
singletonList(mServiceInfo)); singletonList(mServiceInfo));

View File

@@ -124,8 +124,6 @@ public class PremiumSmsAccessTest {
doAnswer((invocation) -> { doAnswer((invocation) -> {
final RestrictedDropDownPreference preference = invocation.getArgument(0); final RestrictedDropDownPreference preference = invocation.getArgument(0);
final ApplicationsState.AppEntry entry = ReflectionHelpers
.getField(preference, "mAppEntry");
// Verify preference is disabled by ecm and the summary is changed accordingly. // Verify preference is disabled by ecm and the summary is changed accordingly.
assertThat(preference.isDisabledByEcm()).isTrue(); assertThat(preference.isDisabledByEcm()).isTrue();
assertThat(preference.getSummary().toString()).isEqualTo( assertThat(preference.getSummary().toString()).isEqualTo(
@@ -156,13 +154,11 @@ public class PremiumSmsAccessTest {
doReturn(preferenceManager).when(mFragment).getPreferenceManager(); doReturn(preferenceManager).when(mFragment).getPreferenceManager();
doReturn(preferenceScreen).when(mFragment).getPreferenceScreen(); doReturn(preferenceScreen).when(mFragment).getPreferenceScreen();
final String testPkg = "com.example.enabled"; final String testPkg = "com.example.enabled";
doNothing().when(mContext).startActivity(any());
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(); ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
doAnswer((invocation) -> { doAnswer((invocation) -> {
final RestrictedDropDownPreference preference = invocation.getArgument(0); final RestrictedDropDownPreference preference = invocation.getArgument(0);
final ApplicationsState.AppEntry entry = ReflectionHelpers
.getField(preference, "mAppEntry");
assertThat(preference.isDisabledByEcm()).isFalse(); assertThat(preference.isDisabledByEcm()).isFalse();
assertThat(preference.getSummary().toString()).isEqualTo(""); assertThat(preference.getSummary().toString()).isEqualTo("");
preference.onBindViewHolder(holder); preference.onBindViewHolder(holder);
@@ -195,4 +191,3 @@ public class PremiumSmsAccessTest {
return appEntries; return appEntries;
} }
} }

View File

@@ -167,11 +167,11 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
@Test @Test
public void onRebuildComplete_ecmRestricted_shouldBeDisabled() { public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
mFragment = spy(new UnrestrictedDataAccess()); mFragment = spy(new UnrestrictedDataAccess());
mContext = spy(mContext);
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean()); doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
mController.setParentFragment(mFragment); mController.setParentFragment(mFragment);
final Context context = spy(mContext); mPreferenceManager = new PreferenceManager(mContext);
mPreferenceManager = new PreferenceManager(context); mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(context));
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager(); doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(0).when(mPreferenceScreen).getPreferenceCount(); doReturn(0).when(mPreferenceScreen).getPreferenceCount();
@@ -180,12 +180,11 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen); ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
final String testPkg = "com.example.disabled"; final String testPkg = "com.example.disabled";
doNothing().when(context).startActivity(any()); doNothing().when(mContext).startActivity(any());
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg); ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
doAnswer((invocation) -> { doAnswer((invocation) -> {
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0); final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
final AppEntry entry = preference.getEntry();
// Verify preference is disabled by ecm and the summary is changed accordingly. // Verify preference is disabled by ecm and the summary is changed accordingly.
assertThat(preference.isDisabledByEcm()).isTrue(); assertThat(preference.isDisabledByEcm()).isTrue();
assertThat(preference.getSummary().toString()).isEqualTo( assertThat(preference.getSummary().toString()).isEqualTo(
@@ -195,7 +194,7 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
preference.performClick(); preference.performClick();
// Verify that when the preference is clicked, ecm details intent is launched // Verify that when the preference is clicked, ecm details intent is launched
assertThat(preference.isChecked()).isFalse(); assertThat(preference.isChecked()).isFalse();
verify(context).startActivity(any()); verify(mContext).startActivity(any());
return null; return null;
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class)); }).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
@@ -207,11 +206,11 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
@Test @Test
public void onRebuildComplete_ecmNotRestricted_notDisabled() { public void onRebuildComplete_ecmNotRestricted_notDisabled() {
mFragment = spy(new UnrestrictedDataAccess()); mFragment = spy(new UnrestrictedDataAccess());
mContext = spy(mContext);
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean()); doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
mController.setParentFragment(mFragment); mController.setParentFragment(mFragment);
final Context context = spy(mContext); mPreferenceManager = new PreferenceManager(mContext);
mPreferenceManager = new PreferenceManager(context); mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(context));
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager(); doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(0).when(mPreferenceScreen).getPreferenceCount(); doReturn(0).when(mPreferenceScreen).getPreferenceCount();
@@ -220,19 +219,18 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen); ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
final String testPkg = "com.example.enabled"; final String testPkg = "com.example.enabled";
doNothing().when(context).startActivity(any()); doNothing().when(mContext).startActivity(any());
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(); ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
doAnswer((invocation) -> { doAnswer((invocation) -> {
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0); final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
final AppEntry entry = preference.getEntry();
assertThat(preference.isDisabledByEcm()).isFalse(); assertThat(preference.isDisabledByEcm()).isFalse();
assertThat(preference.getSummary()).isEqualTo(""); assertThat(preference.getSummary()).isEqualTo("");
assertThat(preference.isChecked()).isFalse(); assertThat(preference.isChecked()).isFalse();
preference.performClick(); preference.performClick();
// Verify that when the preference is clicked, ecm details intent is not launched // Verify that when the preference is clicked, ecm details intent is not launched
assertThat(preference.isChecked()).isTrue(); assertThat(preference.isChecked()).isTrue();
verify(context, never()).startActivity(any()); verify(mContext, never()).startActivity(any());
return null; return null;
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class)); }).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));

View File

@@ -16,7 +16,6 @@
package com.android.settings.testutils.shadow; package com.android.settings.testutils.shadow;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
@@ -122,9 +121,7 @@ public class ShadowRestrictedLockUtilsInternal {
@Implementation @Implementation
public static Intent checkIfRequiresEnhancedConfirmation(@NonNull Context context, public static Intent checkIfRequiresEnhancedConfirmation(@NonNull Context context,
@NonNull String restriction, @NonNull String settingIdentifier, @NonNull String packageName) {
int uid,
@Nullable String packageName) {
if (ArrayUtils.contains(sEcmRestrictedPkgs, packageName)) { if (ArrayUtils.contains(sEcmRestrictedPkgs, packageName)) {
return new Intent(); return new Intent();
} }
@@ -132,6 +129,12 @@ public class ShadowRestrictedLockUtilsInternal {
return null; return null;
} }
@Implementation
public static boolean isEnhancedConfirmationRestricted(@NonNull Context context,
@NonNull String settingIdentifier, @NonNull String packageName) {
return false;
}
public static void setRestricted(boolean restricted) { public static void setRestricted(boolean restricted) {
sIsRestricted = restricted; sIsRestricted = restricted;
} }

View File

@@ -19,11 +19,16 @@ package com.android.settings.spa.app.appinfo
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.KeyguardManager import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.app.ecm.EnhancedConfirmationManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.UserInfo import android.content.pm.UserInfo
import android.os.UserManager import android.os.UserManager
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.CheckFlagsRule
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsNotDisplayed import androidx.compose.ui.test.assertIsNotDisplayed
@@ -61,6 +66,9 @@ class AppInfoSettingsMoreOptionsTest {
@get:Rule @get:Rule
val composeTestRule = createComposeRule() val composeTestRule = createComposeRule()
@get:Rule
val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private lateinit var mockSession: MockitoSession private lateinit var mockSession: MockitoSession
@Spy @Spy
@@ -81,6 +89,9 @@ class AppInfoSettingsMoreOptionsTest {
@Mock @Mock
private lateinit var appOpsManager: AppOpsManager private lateinit var appOpsManager: AppOpsManager
@Mock
private lateinit var enhancedConfirmationManager: EnhancedConfirmationManager
@Mock @Mock
private lateinit var keyguardManager: KeyguardManager private lateinit var keyguardManager: KeyguardManager
@@ -103,6 +114,8 @@ class AppInfoSettingsMoreOptionsTest {
whenever(context.devicePolicyManager).thenReturn(devicePolicyManager) whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
whenever(context.appOpsManager).thenReturn(appOpsManager) whenever(context.appOpsManager).thenReturn(appOpsManager)
whenever(context.getSystemService(KeyguardManager::class.java)).thenReturn(keyguardManager) whenever(context.getSystemService(KeyguardManager::class.java)).thenReturn(keyguardManager)
whenever(context.getSystemService(EnhancedConfirmationManager::class.java))
.thenReturn(enhancedConfirmationManager)
whenever(keyguardManager.isKeyguardSecure).thenReturn(false) whenever(keyguardManager.isKeyguardSecure).thenReturn(false)
whenever(Utils.isProfileOrDeviceOwner(userManager, devicePolicyManager, PACKAGE_NAME)) whenever(Utils.isProfileOrDeviceOwner(userManager, devicePolicyManager, PACKAGE_NAME))
.thenReturn(false) .thenReturn(false)
@@ -158,7 +171,9 @@ class AppInfoSettingsMoreOptionsTest {
} }
@Test @Test
fun shouldShowAccessRestrictedSettings() { @RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
fun shouldShowAccessRestrictedSettings_appOp() {
whenever( whenever(
appOpsManager.noteOpNoThrow( appOpsManager.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, UID, PACKAGE_NAME, null, null AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, UID, PACKAGE_NAME, null, null
@@ -186,6 +201,31 @@ class AppInfoSettingsMoreOptionsTest {
) )
} }
@Test
@RequiresFlagsEnabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
fun shouldShowAccessRestrictedSettings() {
whenever(
enhancedConfirmationManager.isClearRestrictionAllowed(PACKAGE_NAME)
).thenReturn(true)
val app = ApplicationInfo().apply {
packageName = PACKAGE_NAME
uid = UID
}
setContent(app)
composeTestRule.onRoot().performClick()
composeTestRule.waitUntilExists(
hasText(context.getString(R.string.app_restricted_settings_lockscreen_title))
)
composeTestRule
.onNodeWithText(context
.getString(R.string.app_restricted_settings_lockscreen_title))
.performClick()
verify(enhancedConfirmationManager).clearRestriction(PACKAGE_NAME)
}
private fun setContent(app: ApplicationInfo) { private fun setContent(app: ApplicationInfo) {
composeTestRule.setContent { composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) { CompositionLocalProvider(LocalContext provides context) {

View File

@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
@@ -37,6 +36,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -46,6 +48,7 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -59,6 +62,8 @@ public class ApprovalPreferenceControllerTest {
@Rule @Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule( public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT); SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private Context mContext; private Context mContext;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
@@ -123,6 +128,7 @@ public class ApprovalPreferenceControllerTest {
} }
@Test @Test
@RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
public void updateState_checked() { public void updateState_checked() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ALLOWED); AppOpsManager.MODE_ALLOWED);
@@ -137,24 +143,26 @@ public class ApprovalPreferenceControllerTest {
} }
@Test @Test
@RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
public void restrictedSettings_appOpsDisabled() { public void restrictedSettings_appOpsDisabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString(), isNull(), isNull())) Assert.assertFalse(android.security.Flags.extendEcmToAllSettings());
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString()))
.thenReturn(AppOpsManager.MODE_ERRORED); .thenReturn(AppOpsManager.MODE_ERRORED);
doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE); doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false); when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference( RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext); mContext);
pref.setAppOps(mAppOpsManager); pref.setAppOps(mAppOpsManager);
mController.setAppOpStr(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS); mController.setSettingIdentifier(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
mController.updateState(pref); mController.updateState(pref);
verify(mContext).getSystemService(Context.APP_OPS_SERVICE); verify(mAppOpsManager).noteOpNoThrow(anyInt(), anyInt(), anyString());
verify(mAppOpsManager).noteOpNoThrow(anyInt(), anyInt(), anyString(), isNull(), isNull());
assertThat(pref.isEnabled()).isFalse(); assertThat(pref.isEnabled()).isFalse();
} }
@Test @Test
@RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
public void restrictedSettings_serviceAlreadyEnabled() { public void restrictedSettings_serviceAlreadyEnabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ERRORED); AppOpsManager.MODE_ERRORED);