diff options
5 files changed, 88 insertions, 36 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 846349d8be77..48286d4d156f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2738,6 +2738,22 @@ public class Intent implements Parcelable, Cloneable { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED"; + /** + * Broadcast Action: One of the suspend conditions have been modified for the packages. + * <p>Includes the following extras: + * <ul> + * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been modified + * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been modified + * </ul> + * + * <p class="note">This is a protected intent that can only be sent + * by the system. It is only sent to registered receivers. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGES_SUSPENSION_CHANGED = + "android.intent.action.PACKAGES_SUSPENSION_CHANGED"; /** * Broadcast Action: Distracting packages have been changed. diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java index 84354d90b5f3..ec224e50eb8d 100644 --- a/core/java/com/android/internal/app/SuspendedAppActivity.java +++ b/core/java/com/android/internal/app/SuspendedAppActivity.java @@ -72,17 +72,19 @@ public class SuspendedAppActivity extends AlertActivity private Resources mSuspendingAppResources; private SuspendDialogInfo mSuppliedDialogInfo; private Bundle mOptions; - private BroadcastReceiver mUnsuspendReceiver = new BroadcastReceiver() { + private BroadcastReceiver mSuspendModifiedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(intent.getAction())) { - final String[] unsuspended = intent.getStringArrayExtra( + if (Intent.ACTION_PACKAGES_SUSPENSION_CHANGED.equals(intent.getAction())) { + // Suspension conditions were modified, dismiss any related visible dialogs. + final String[] modified = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_PACKAGE_LIST); - if (ArrayUtils.contains(unsuspended, mSuspendedPackage)) { + if (ArrayUtils.contains(modified, mSuspendedPackage)) { if (!isFinishing()) { - Slog.w(TAG, "Package " + mSuspendedPackage - + " got unsuspended while the dialog was visible. Finishing."); + Slog.w(TAG, "Package " + mSuspendedPackage + " has modified" + + " suspension conditions while dialog was visible. Finishing."); SuspendedAppActivity.this.finish(); + // TODO (b/198201994): reload the suspend dialog to show most relevant info } } } @@ -245,15 +247,16 @@ public class SuspendedAppActivity extends AlertActivity setupAlert(); - final IntentFilter unsuspendFilter = new IntentFilter(Intent.ACTION_PACKAGES_UNSUSPENDED); - registerReceiverAsUser(mUnsuspendReceiver, UserHandle.of(mUserId), unsuspendFilter, null, - null); + final IntentFilter suspendModifiedFilter = + new IntentFilter(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED); + registerReceiverAsUser(mSuspendModifiedReceiver, UserHandle.of(mUserId), + suspendModifiedFilter, null, null); } @Override protected void onDestroy() { super.onDestroy(); - unregisterReceiver(mUnsuspendReceiver); + unregisterReceiver(mSuspendModifiedReceiver); } private void requestDismissKeyguardIfNeeded(CharSequence dismissMessage) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 94306ce1e501..f1bff6fbc087 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15818,8 +15818,7 @@ public class PackageManagerService extends IPackageManager.Stub } @VisibleForTesting(visibility = Visibility.PRIVATE) - void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId, - boolean suspended) { + void sendPackagesSuspendedForUser(String intent, String[] pkgList, int[] uidList, int userId) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); @@ -15860,11 +15859,8 @@ public class PackageManagerService extends IPackageManager.Stub extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); - sendPackageBroadcast( - suspended ? Intent.ACTION_PACKAGES_SUSPENDED - : Intent.ACTION_PACKAGES_UNSUSPENDED, - null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, - userIds, null, allowList, null); + sendPackageBroadcast(intent, null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, + null, userIds, null, allowList, null); } } @@ -16178,6 +16174,8 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> changedPackagesList = new ArrayList<>(packageNames.length); final IntArray changedUids = new IntArray(packageNames.length); + final List<String> modifiedPackagesList = new ArrayList<>(packageNames.length); + final IntArray modifiedUids = new IntArray(packageNames.length); final List<String> unactionedPackages = new ArrayList<>(packageNames.length); final boolean[] canSuspend = suspended ? canSuspendPackageForUserInternal(packageNames, userId) : null; @@ -16205,13 +16203,14 @@ public class PackageManagerService extends IPackageManager.Stub unactionedPackages.add(packageName); continue; } - boolean packageUnsuspended; + final boolean packageUnsuspended; + final boolean packageModified; synchronized (mLock) { if (suspended) { - pkgSetting.addOrUpdateSuspension(callingPackage, dialogInfo, appExtras, - launcherExtras, userId); + packageModified = pkgSetting.addOrUpdateSuspension(callingPackage, + dialogInfo, appExtras, launcherExtras, userId); } else { - pkgSetting.removeSuspension(callingPackage, userId); + packageModified = pkgSetting.removeSuspension(callingPackage, userId); } packageUnsuspended = !suspended && !pkgSetting.getSuspended(userId); } @@ -16219,18 +16218,29 @@ public class PackageManagerService extends IPackageManager.Stub changedPackagesList.add(packageName); changedUids.add(UserHandle.getUid(userId, pkgSetting.appId)); } + if (packageModified) { + modifiedPackagesList.add(packageName); + modifiedUids.add(UserHandle.getUid(userId, pkgSetting.appId)); + } } if (!changedPackagesList.isEmpty()) { - final String[] changedPackages = changedPackagesList.toArray( - new String[changedPackagesList.size()]); - sendPackagesSuspendedForUser(changedPackages, changedUids.toArray(), userId, suspended); + final String[] changedPackages = changedPackagesList.toArray(new String[0]); + sendPackagesSuspendedForUser( + suspended ? Intent.ACTION_PACKAGES_SUSPENDED + : Intent.ACTION_PACKAGES_UNSUSPENDED, + changedPackages, changedUids.toArray(), userId); sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, userId); synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } - return unactionedPackages.toArray(new String[unactionedPackages.size()]); + // Send the suspension changed broadcast to ensure suspension state is not stale. + if (!modifiedPackagesList.isEmpty()) { + sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, + modifiedPackagesList.toArray(new String[0]), modifiedUids.toArray(), userId); + } + return unactionedPackages.toArray(new String[0]); } @Override @@ -16359,7 +16369,8 @@ public class PackageManagerService extends IPackageManager.Stub final String[] packageArray = unsuspendedPackages.toArray( new String[unsuspendedPackages.size()]); sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId); - sendPackagesSuspendedForUser(packageArray, unsuspendedUids.toArray(), userId, false); + sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_UNSUSPENDED, + packageArray, unsuspendedUids.toArray(), userId); } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 717f3d57ec38..d9c4d316f948 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -455,7 +455,7 @@ public abstract class PackageSettingBase extends SettingBase { return state.suspendParams != null && state.suspendParams.containsKey(suspendingPackage); } - void addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo, + boolean addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) { final PackageUserState existingUserState = modifyUserState(userId); final PackageUserState.SuspendParams newSuspendParams = @@ -464,21 +464,27 @@ public abstract class PackageSettingBase extends SettingBase { if (existingUserState.suspendParams == null) { existingUserState.suspendParams = new ArrayMap<>(); } - existingUserState.suspendParams.put(suspendingPackage, newSuspendParams); + final PackageUserState.SuspendParams oldSuspendParams = + existingUserState.suspendParams.put(suspendingPackage, newSuspendParams); existingUserState.suspended = true; onChanged(); + return !Objects.equals(oldSuspendParams, newSuspendParams); } - void removeSuspension(String suspendingPackage, int userId) { + boolean removeSuspension(String suspendingPackage, int userId) { + boolean wasModified = false; final PackageUserState existingUserState = modifyUserState(userId); if (existingUserState.suspendParams != null) { - existingUserState.suspendParams.remove(suspendingPackage); + if (existingUserState.suspendParams.remove(suspendingPackage) != null) { + wasModified = true; + } if (existingUserState.suspendParams.size() == 0) { existingUserState.suspendParams = null; } } existingUserState.suspended = (existingUserState.suspendParams != null); onChanged(); + return wasModified; } void removeSuspension(Predicate<String> suspendingPackagePredicate, int userId) { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt index 7a6110bdbda3..f17fa625d007 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt @@ -79,8 +79,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10003)) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), any(), nullable()) @@ -97,8 +97,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10007)) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms, times(2)).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), any(), nullable()) @@ -118,8 +118,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, null) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms, times(2)).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) @@ -133,6 +133,22 @@ class SuspendPackagesBroadcastTest { } } + @Test + @Throws(Exception::class) + fun sendPackagesSuspendModifiedForUser() { + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) + verify(pms).sendPackageBroadcast( + eq(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED), nullable(), bundleCaptor.capture(), + anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) + + var modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST) + var modifiedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST) + assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2) + assertThat(modifiedUids).asList().containsExactly( + packageSetting1.appId, packageSetting2.appId) + } + private fun allowList(vararg uids: Int) = SparseArray<IntArray>().apply { this.put(TEST_USER_ID, uids) } |