diff options
11 files changed, 89 insertions, 50 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 0e5a5157c090..6ab4a3d9dde3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -11094,6 +11094,7 @@ package android.content { field public static final String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE"; field @Deprecated public static final String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE"; field public static final String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS"; + field public static final String EXTRA_ARCHIVAL = "android.intent.extra.ARCHIVAL"; field public static final String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT"; field public static final String EXTRA_ASSIST_INPUT_DEVICE_ID = "android.intent.extra.ASSIST_INPUT_DEVICE_ID"; field public static final String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD"; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index fe7d1e6fb232..f156878f5694 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -6270,6 +6270,14 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING"; /** + * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_ADDED} and + * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} intents to indicate that + * the package is being archived. Either by removing the existing APK, or by installing + * a package without an APK. + */ + public static final String EXTRA_ARCHIVAL = "android.intent.extra.ARCHIVAL"; + + /** * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} * intents to indicate that this is a system update uninstall. * @hide diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java index 02052808dd18..9a69d77c61f0 100644 --- a/services/core/java/com/android/server/pm/BroadcastHelper.java +++ b/services/core/java/com/android/server/pm/BroadcastHelper.java @@ -19,7 +19,6 @@ package com.android.server.pm; import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED; - import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.PACKAGE_SCHEME; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; @@ -323,14 +322,17 @@ public final class BroadcastHelper { } } - public void sendPackageAddedForNewUsers(String packageName, - @AppIdInt int appId, int[] userIds, int[] instantUserIds, - int dataLoaderType, SparseArray<int[]> broadcastAllowlist) { + public void sendPackageAddedForNewUsers(String packageName, @AppIdInt int appId, int[] userIds, + int[] instantUserIds, boolean isArchived, int dataLoaderType, + SparseArray<int[]> broadcastAllowlist) { Bundle extras = new Bundle(1); // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast final int uid = UserHandle.getUid( (ArrayUtils.isEmpty(userIds) ? instantUserIds[0] : userIds[0]), appId); extras.putInt(Intent.EXTRA_UID, uid); + if (isArchived) { + extras.putBoolean(Intent.EXTRA_ARCHIVAL, true); + } extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType); sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 967998a790ac..4d3bf4007e92 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -24,7 +24,6 @@ import static android.content.pm.PackageManager.DELETE_KEEP_DATA; import static android.content.pm.PackageManager.DELETE_SUCCEEDED; import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES; import static android.content.pm.PackageManager.PERMISSION_GRANTED; - import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION; import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; @@ -120,13 +119,14 @@ final class DeletePackageHelper { */ public int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags, boolean removedBySystem) { + final boolean isArchived = false; // TODO(b/278553670) Pass true during archival. + final PackageRemovedInfo info = new PackageRemovedInfo(mPm); final boolean res; final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0 ? UserHandle.USER_ALL : userId; - final PackageSetting uninstalledPs; final PackageSetting disabledSystemPs; final AndroidPackage pkg; @@ -250,7 +250,7 @@ final class DeletePackageHelper { if (res) { final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0; - info.sendPackageRemovedBroadcasts(killApp, removedBySystem); + info.sendPackageRemovedBroadcasts(killApp, removedBySystem, isArchived); info.sendSystemPackageUpdatedBroadcasts(); PackageMetrics.onUninstallSucceeded(info, deleteFlags, removeUser); } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 2712fa782c27..d668146b04d4 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -729,8 +729,10 @@ final class InstallPackageHelper { mAppDataHelper.prepareAppDataAfterInstallLIF(pkgSetting.getPkg()); } } + // TODO(b/278553670) Store archive state for the user. + boolean isArchived = (pkgSetting.getPkg() == null); mPm.sendPackageAddedForUser(mPm.snapshotComputer(), packageName, pkgSetting, userId, - DataLoaderType.NONE); + isArchived, DataLoaderType.NONE); synchronized (mPm.mLock) { mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId }); } @@ -1713,7 +1715,6 @@ final class InstallPackageHelper { installedUsers = ps.queryInstalledUsers(allUsers, true); uninstalledUsers = ps.queryInstalledUsers(allUsers, false); - // don't allow an upgrade from full to ephemeral if (isInstantApp) { if (request.getUserId() == UserHandle.USER_ALL) { @@ -2798,6 +2799,7 @@ final class InstallPackageHelper { final int dataLoaderType = request.getDataLoaderType(); final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED; final boolean update = request.isUpdate(); + final boolean archived = request.isArchived(); final String packageName = request.getName(); final PackageStateInternal pkgSetting = succeeded ? mPm.snapshotComputer().getPackageStateInternal(packageName) : null; @@ -2837,7 +2839,7 @@ final class InstallPackageHelper { false /* mediaStatus */, true /* replacing */, pkgNames, uids); } request.getRemovedInfo().sendPackageRemovedBroadcasts( - killApp, false /*removedBySystem*/); + killApp, false /*removedBySystem*/, false /*isArchived*/); } final String installerPackageName = @@ -2896,6 +2898,9 @@ final class InstallPackageHelper { if (update) { extras.putBoolean(Intent.EXTRA_REPLACING, true); } + if (archived) { + extras.putBoolean(Intent.EXTRA_ARCHIVAL, true); + } extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType); // If a package is a static shared library, then only the installer of the package @@ -2919,7 +2924,7 @@ final class InstallPackageHelper { boolean isSystem = request.isInstallSystem(); mPm.sendPackageAddedForNewUsers(mPm.snapshotComputer(), packageName, isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId, - firstUserIds, firstInstantUserIds, dataLoaderType); + firstUserIds, firstInstantUserIds, archived, dataLoaderType); // Send PACKAGE_ADDED broadcast for users that don't see // the package for the first time @@ -3034,12 +3039,14 @@ final class InstallPackageHelper { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + request.getPkg() + " is external"); } - final String[] pkgNames = new String[]{packageName}; - final int[] uids = new int[]{request.getPkg().getUid()}; - mBroadcastHelper.sendResourcesChangedBroadcast(mPm::snapshotComputer, - true /* mediaStatus */, true /* replacing */, pkgNames, uids); - mPm.notifyResourcesChanged(true /* mediaStatus */, true /* replacing */, - pkgNames, uids); + if (!archived) { + final String[] pkgNames = new String[]{packageName}; + final int[] uids = new int[]{request.getPkg().getUid()}; + mBroadcastHelper.sendResourcesChangedBroadcast(mPm::snapshotComputer, + true /* mediaStatus */, true /* replacing */, pkgNames, uids); + mPm.notifyResourcesChanged(true /* mediaStatus */, true /* replacing */, + pkgNames, uids); + } } } else if (!ArrayUtils.isEmpty(request.getLibraryConsumers())) { // if static shared lib // No need to kill consumers if it's installation of new version static shared lib. @@ -3092,19 +3099,34 @@ final class InstallPackageHelper { VMRuntime.getRuntime().requestConcurrentGC(); } - final Computer snapshot = mPm.snapshotComputer(); - // Notify DexManager that the package was installed for new users. - // The updated users should already be indexed and the package code paths - // should not change. - // Don't notify the manager for ephemeral apps as they are not expected to - // survive long enough to benefit of background optimizations. - for (int userId : firstUserIds) { - PackageInfo info = snapshot.getPackageInfo(packageName, /*flags*/ 0, userId); - // There's a race currently where some install events may interleave with an - // uninstall. This can lead to package info being null (b/36642664). - if (info != null) { - mDexManager.notifyPackageInstalled(info, userId); + if (!archived) { + final Computer snapshot = mPm.snapshotComputer(); + // Notify DexManager that the package was installed for new users. + // The updated users should already be indexed and the package code paths + // should not change. + // Don't notify the manager for ephemeral apps as they are not expected to + // survive long enough to benefit of background optimizations. + for (int userId : firstUserIds) { + PackageInfo info = snapshot.getPackageInfo(packageName, /*flags*/ 0, userId); + // There's a race currently where some install events may interleave with an + // uninstall. This can lead to package info being null (b/36642664). + if (info != null) { + mDexManager.notifyPackageInstalled(info, userId); + } } + } else { + // Now send PACKAGE_REMOVED + EXTRA_REPLACING broadcast. + final PackageRemovedInfo info = new PackageRemovedInfo(mPm); + info.mRemovedPackage = packageName; + info.mInstallerPackageName = request.getInstallerPackageName(); + info.mRemovedUsers = firstUserIds; + info.mBroadcastUsers = firstUserIds; + info.mRemovedAppId = request.getAppId(); + info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode(); + info.mRemovedForAllUsers = true; + + info.sendPackageRemovedBroadcasts(false /*killApp*/, + false /*removedBySystem*/, true /*isArchived*/); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0c2f1ca54f73..7290791826dc 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3044,7 +3044,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService } void sendPackageAddedForUser(@NonNull Computer snapshot, String packageName, - @NonNull PackageStateInternal packageState, int userId, int dataLoaderType) { + @NonNull PackageStateInternal packageState, int userId, boolean isArchived, + int dataLoaderType) { final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId); final boolean isSystem = packageState.isSystem(); final boolean isInstantApp = userState.isInstantApp(); @@ -3052,7 +3053,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY; sendPackageAddedForNewUsers(snapshot, packageName, isSystem /*sendBootCompleted*/, false /*startReceiver*/, packageState.getAppId(), userIds, instantUserIds, - dataLoaderType); + isArchived, dataLoaderType); // Send a session commit broadcast final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo(); @@ -3064,17 +3065,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, boolean sendBootCompleted, boolean includeStopped, @AppIdInt int appId, int[] userIds, - int[] instantUserIds, int dataLoaderType) { + int[] instantUserIds, boolean isArchived, int dataLoaderType) { if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) { return; } SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(snapshot, snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID), userIds, snapshot.getPackageStates()); - mHandler.post(() -> mBroadcastHelper.sendPackageAddedForNewUsers( - packageName, appId, userIds, instantUserIds, dataLoaderType, broadcastAllowList)); + mHandler.post( + () -> mBroadcastHelper.sendPackageAddedForNewUsers(packageName, appId, userIds, + instantUserIds, isArchived, dataLoaderType, broadcastAllowList)); mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(packageName, appId, userIds, - instantUserIds, dataLoaderType, broadcastAllowList); + instantUserIds, isArchived, dataLoaderType, broadcastAllowList); if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) { mHandler.post(() -> { for (int userId : userIds) { @@ -3095,7 +3097,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService info.mBroadcastUsers = new int[] {userId}; info.mUid = UserHandle.getUid(userId, packageState.getAppId()); info.mRemovedPackageVersionCode = packageState.getVersionCode(); - info.sendPackageRemovedBroadcasts(true /*killApp*/, false /*removedBySystem*/); + info.sendPackageRemovedBroadcasts(true /*killApp*/, false /*removedBySystem*/, + false /*isArchived*/); } boolean isUserRestricted(int userId, String restrictionKey) { @@ -5772,7 +5775,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService sendApplicationHiddenForUser(packageName, newPackageState, userId); } else { sendPackageAddedForUser(newSnapshot, packageName, newPackageState, userId, - DataLoaderType.NONE); + false /* isArchived */, DataLoaderType.NONE); } scheduleWritePackageRestrictions(userId); diff --git a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java index a7715025d024..bb3bf5360edc 100644 --- a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java +++ b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java @@ -100,12 +100,15 @@ class PackageMonitorCallbackHelper { public void notifyPackageAddedForNewUsers(String packageName, @AppIdInt int appId, @NonNull int[] userIds, @NonNull int[] instantUserIds, - int dataLoaderType, SparseArray<int[]> broadcastAllowList) { + boolean isArchived, int dataLoaderType, SparseArray<int[]> broadcastAllowList) { Bundle extras = new Bundle(2); // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast final int uid = UserHandle.getUid( (ArrayUtils.isEmpty(userIds) ? instantUserIds[0] : userIds[0]), appId); extras.putInt(Intent.EXTRA_UID, uid); + if (isArchived) { + extras.putBoolean(Intent.EXTRA_ARCHIVAL, true); + } extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType); notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED, packageName, extras , userIds /* userIds */, instantUserIds, broadcastAllowList); diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java index 5f4452884fc9..9f02542a31e4 100644 --- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java +++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java @@ -18,7 +18,6 @@ package com.android.server.pm; import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; - import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.annotation.NonNull; @@ -63,8 +62,9 @@ final class PackageRemovedInfo { mPackageSender = packageSender; } - void sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem) { - sendPackageRemovedBroadcastInternal(killApp, removedBySystem); + void sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem, + boolean isArchived) { + sendPackageRemovedBroadcastInternal(killApp, removedBySystem, isArchived); } void sendSystemPackageUpdatedBroadcasts() { @@ -111,7 +111,8 @@ final class PackageRemovedInfo { return bOptions; } - private void sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem) { + private void sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem, + boolean isArchived) { Bundle extras = new Bundle(); final int removedUid = mRemovedAppId >= 0 ? mRemovedAppId : mUid; extras.putInt(Intent.EXTRA_UID, removedUid); @@ -120,9 +121,12 @@ final class PackageRemovedInfo { extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp); extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem); final boolean isReplace = mIsUpdate || mIsRemovedPackageSystemUpdate; - if (isReplace) { + if (isReplace || isArchived) { extras.putBoolean(Intent.EXTRA_REPLACING, true); } + if (isArchived) { + extras.putBoolean(Intent.EXTRA_ARCHIVAL, true); + } extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, mRemovedForAllUsers); // Send PACKAGE_REMOVED broadcast to the respective installer. diff --git a/services/core/java/com/android/server/pm/PackageSender.java b/services/core/java/com/android/server/pm/PackageSender.java index 656d5962e1a9..82e1d5f389c5 100644 --- a/services/core/java/com/android/server/pm/PackageSender.java +++ b/services/core/java/com/android/server/pm/PackageSender.java @@ -33,7 +33,7 @@ interface PackageSender { @Nullable SparseArray<int[]> broadcastAllowList, @Nullable Bundle bOptions); void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, boolean sendBootCompleted, boolean includeStopped, int appId, int[] userIds, - int[] instantUserIds, int dataLoaderType); + int[] instantUserIds, boolean isArchived, int dataLoaderType); void notifyPackageAdded(String packageName, int uid); void notifyPackageChanged(String packageName, int uid); void notifyPackageRemoved(String packageName, int uid); diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java index bea654305a9f..4a2bf75b4d2c 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java @@ -17,12 +17,9 @@ package com.android.server.pm; import static com.android.compatibility.common.util.ShellUtils.runShellCommand; - import static com.google.common.truth.Truth.assertWithMessage; - import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; - import static java.lang.reflect.Modifier.isFinal; import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isStatic; @@ -99,7 +96,7 @@ public class PackageManagerServiceTest { public void sendPackageAddedForNewUsers(@NonNull Computer snapshot, String packageName, boolean sendBootComplete, boolean includeStopped, int appId, - int[] userIds, int[] instantUserIds, int dataLoaderType) { + int[] userIds, int[] instantUserIds, boolean isArchived, int dataLoaderType) { } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java index f20633342759..c5db5db41787 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java @@ -17,7 +17,6 @@ package com.android.server.pm; import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.after; import static org.mockito.Mockito.reset; @@ -183,7 +182,7 @@ public class PackageMonitorCallbackHelperTest { mPackageMonitorCallbackHelper.registerPackageMonitorCallback(callback, 0 /* userId */, Binder.getCallingUid()); mPackageMonitorCallbackHelper.notifyPackageAddedForNewUsers(FAKE_PACKAGE_NAME, - FAKE_PACKAGE_UID, new int[]{0} /* userIds */, new int[0], + FAKE_PACKAGE_UID, new int[]{0} /* userIds */, new int[0], false /* isArchived */, PackageInstaller.DATA_LOADER_TYPE_STREAMING, null /* broadcastAllowList */); ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); |