diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java index f520f6a9ef492..4dfd9b0763547 100644 --- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java +++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java @@ -19,6 +19,7 @@ package com.android.server.appop; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_SCHEDULE_EXACT_ALARM; +import static android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT; import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES; import static android.app.AppOpsManager.opRestrictsRead; import static android.app.AppOpsManager.opToDefaultMode; @@ -41,6 +42,7 @@ import android.os.Binder; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; +import android.permission.PermissionManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; @@ -107,7 +109,7 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface * {@link #upgradeLocked(int)} below. The first version was 1. */ @VisibleForTesting - static final int CURRENT_VERSION = 3; + static final int CURRENT_VERSION = 4; /** * This stores the version of appops.xml seen at boot. If this is smaller than @@ -1074,7 +1076,12 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface upgradeScheduleExactAlarmLocked(); // fall through case 2: - // for future upgrades + // split the appops.xml into appops.xml to store appop state and apppops_access.xml + // to store app-op access. + // fall through + case 3: + resetUseFullScreenIntentLocked(); + // fall through } scheduleFastWriteLocked(); } @@ -1145,6 +1152,38 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface } } + /** + * A cleanup step for U Beta 2 that reverts the OP_USE_FULL_SCREEN_INTENT's mode to MODE_DEFAULT + * if the permission flags for the USE_FULL_SCREEN_INTENT permission does not have USER_SET. + */ + @VisibleForTesting + @GuardedBy("mLock") + void resetUseFullScreenIntentLocked() { + final PermissionManagerServiceInternal pmsi = LocalServices.getService( + PermissionManagerServiceInternal.class); + final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); + final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); + final PermissionManager permissionManager = + mContext.getSystemService(PermissionManager.class); + + final String permissionName = AppOpsManager.opToPermission(OP_USE_FULL_SCREEN_INTENT); + final String[] packagesDeclaringPermission = + pmsi.getAppOpPermissionPackages(permissionName); + final int[] userIds = umi.getUserIds(); + + for (final String pkg : packagesDeclaringPermission) { + for (int userId : userIds) { + final int uid = pmi.getPackageUid(pkg, 0, userId); + final int flags = permissionManager.getPermissionFlags(pkg, permissionName, + UserHandle.of(userId)); + if ((flags & PackageManager.FLAG_PERMISSION_USER_SET) == 0) { + setUidMode(uid, OP_USE_FULL_SCREEN_INTENT, + AppOpsManager.opToDefaultMode(OP_USE_FULL_SCREEN_INTENT)); + } + } + } + } + @VisibleForTesting List getUidsWithNonDefaultModes() { List result = new ArrayList<>(); diff --git a/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/appops-version-3.xml b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/appops-version-3.xml new file mode 100644 index 0000000000000..1363bf783ac2a --- /dev/null +++ b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/appops-version-3.xml @@ -0,0 +1,801 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java index 5474c20927855..92d1118d0f1eb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java @@ -17,6 +17,7 @@ package com.android.server.appop; import static android.app.AppOpsManager.OP_SCHEDULE_EXACT_ALARM; +import static android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT; import static android.app.AppOpsManager._NUM_OP; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; @@ -31,6 +32,7 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isA; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; @@ -44,6 +46,7 @@ import android.content.pm.UserPackage; import android.content.res.AssetManager; import android.os.Handler; import android.os.UserHandle; +import android.permission.PermissionManager; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; @@ -87,6 +90,10 @@ public class AppOpsUpgradeTest { "AppOpsUpgradeTest/appops-unversioned.xml"; private static final String APP_OPS_VERSION_1_ASSET_PATH = "AppOpsUpgradeTest/appops-version-1.xml"; + + private static final String APP_OPS_VERSION_3_ASSET_PATH = + "AppOpsUpgradeTest/appops-version-3.xml"; + private static final String APP_OPS_FILENAME = "appops-test.xml"; private static final Context sContext = InstrumentationRegistry.getTargetContext(); @@ -105,6 +112,8 @@ public class AppOpsUpgradeTest { private PermissionManagerServiceInternal mPermissionManagerInternal; @Mock private Handler mHandler; + @Mock + private PermissionManager mPermissionManager; private Object mLock = new Object(); private SparseArray mSwitchedOps; @@ -211,7 +220,7 @@ public class AppOpsUpgradeTest { } } - private static int getModeInFile(int uid) { + private static int getModeInFile(int uid, int op) { switch (uid) { case 10198: return 0; @@ -222,7 +231,7 @@ public class AppOpsUpgradeTest { case 1110181: return 2; default: - return AppOpsManager.opToDefaultMode(OP_SCHEDULE_EXACT_ALARM); + return AppOpsManager.opToDefaultMode(op); } } @@ -258,7 +267,7 @@ public class AppOpsUpgradeTest { for (int userId : userIds) { for (int appId : appIds) { final int uid = UserHandle.getUid(userId, appId); - final int previousMode = getModeInFile(uid); + final int previousMode = getModeInFile(uid, OP_SCHEDULE_EXACT_ALARM); final int expectedMode; if (previousMode == AppOpsManager.opToDefaultMode(OP_SCHEDULE_EXACT_ALARM)) { @@ -280,6 +289,55 @@ public class AppOpsUpgradeTest { } } + @Test + public void resetUseFullScreenIntent() { + extractAppOpsFile(APP_OPS_VERSION_3_ASSET_PATH); + + String[] packageNames = {"p1", "package2", "pkg3", "package.4", "pkg-5", "pkg.6"}; + int[] appIds = {10267, 10181, 10198, 10199, 10200, 4213}; + int[] userIds = {0, 10, 11}; + int flag = 0; + + doReturn(userIds).when(mUserManagerInternal).getUserIds(); + + doReturn(packageNames).when(mPermissionManagerInternal).getAppOpPermissionPackages( + AppOpsManager.opToPermission(OP_USE_FULL_SCREEN_INTENT)); + + doReturn(mPermissionManager).when(mTestContext).getSystemService(PermissionManager.class); + + doReturn(flag).when(mPackageManager).getPermissionFlags( + anyString(), anyString(), isA(UserHandle.class)); + + doAnswer(invocation -> { + String pkg = invocation.getArgument(0); + int index = ArrayUtils.indexOf(packageNames, pkg); + if (index < 0) { + return index; + } + int userId = invocation.getArgument(2); + return UserHandle.getUid(userId, appIds[index]); + }).when(mPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt()); + + AppOpsCheckingServiceImpl testService = new AppOpsCheckingServiceImpl(sAppOpsFile, mLock, + mHandler, mTestContext, mSwitchedOps); + testService.readState(); + + synchronized (testService) { + testService.resetUseFullScreenIntentLocked(); + } + + for (int userId : userIds) { + for (int appId : appIds) { + final int uid = UserHandle.getUid(userId, appId); + final int expectedMode = AppOpsManager.opToDefaultMode(OP_USE_FULL_SCREEN_INTENT); + synchronized (testService) { + int mode = testService.getUidMode(uid, OP_USE_FULL_SCREEN_INTENT); + assertEquals(expectedMode, mode); + } + } + } + } + @Test public void upgradeFromNoFile() { assertFalse(sAppOpsFile.exists()); @@ -290,12 +348,14 @@ public class AppOpsUpgradeTest { doNothing().when(testService).upgradeRunAnyInBackgroundLocked(); doNothing().when(testService).upgradeScheduleExactAlarmLocked(); + doNothing().when(testService).resetUseFullScreenIntentLocked(); // trigger upgrade testService.systemReady(); verify(testService, never()).upgradeRunAnyInBackgroundLocked(); verify(testService, never()).upgradeScheduleExactAlarmLocked(); + verify(testService, never()).resetUseFullScreenIntentLocked(); testService.writeState(); @@ -319,12 +379,14 @@ public class AppOpsUpgradeTest { doNothing().when(testService).upgradeRunAnyInBackgroundLocked(); doNothing().when(testService).upgradeScheduleExactAlarmLocked(); + doNothing().when(testService).resetUseFullScreenIntentLocked(); // trigger upgrade testService.systemReady(); verify(testService).upgradeRunAnyInBackgroundLocked(); verify(testService).upgradeScheduleExactAlarmLocked(); + verify(testService).resetUseFullScreenIntentLocked(); testService.writeState(); assertTrue(parser.parse()); @@ -344,12 +406,40 @@ public class AppOpsUpgradeTest { doNothing().when(testService).upgradeRunAnyInBackgroundLocked(); doNothing().when(testService).upgradeScheduleExactAlarmLocked(); + doNothing().when(testService).resetUseFullScreenIntentLocked(); // trigger upgrade testService.systemReady(); verify(testService, never()).upgradeRunAnyInBackgroundLocked(); verify(testService).upgradeScheduleExactAlarmLocked(); + verify(testService).resetUseFullScreenIntentLocked(); + + testService.writeState(); + assertTrue(parser.parse()); + assertEquals(AppOpsCheckingServiceImpl.CURRENT_VERSION, parser.mVersion); + } + + @Test + public void resetFromVersion3() { + extractAppOpsFile(APP_OPS_VERSION_3_ASSET_PATH); + AppOpsDataParser parser = new AppOpsDataParser(sAppOpsFile); + assertTrue(parser.parse()); + assertEquals(3, parser.mVersion); + + AppOpsCheckingServiceImpl testService = spy(new AppOpsCheckingServiceImpl(sAppOpsFile, + mLock, mHandler, mTestContext, mSwitchedOps)); + testService.readState(); + + doNothing().when(testService).upgradeRunAnyInBackgroundLocked(); + doNothing().when(testService).upgradeScheduleExactAlarmLocked(); + doNothing().when(testService).resetUseFullScreenIntentLocked(); + + testService.systemReady(); + + verify(testService, never()).upgradeRunAnyInBackgroundLocked(); + verify(testService, never()).upgradeScheduleExactAlarmLocked(); + verify(testService).resetUseFullScreenIntentLocked(); testService.writeState(); assertTrue(parser.parse());