Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4776cdee authored by John Wu's avatar John Wu
Browse files

Update system package broadcasts for app ID changes

Whenever a package's app ID has changed, the system broadcasts should
behave as if the package is fully uninstalled and then re-installed
subsequently. Additional extras are added to indicate the app ID change
to allow components to handle this case specifically.

Test: atest SharedUserMigrationTest#testDataMigration
Bug: 179284822
Change-Id: Ie00eaed1f0a704876ea76aa0e5ae2a1b21f199df
parent d0f4400f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -11544,6 +11544,7 @@ package android.content {
    field public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
    field public static final String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME";
    field public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
    field public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";
    field public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
    field public static final String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
    field public static final String EXTRA_QUICK_VIEW_FEATURES = "android.intent.extra.QUICK_VIEW_FEATURES";
@@ -11575,6 +11576,7 @@ package android.content {
    field public static final String EXTRA_TIMEZONE = "time-zone";
    field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
    field public static final String EXTRA_UID = "android.intent.extra.UID";
    field public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";
    field public static final String EXTRA_USER = "android.intent.extra.USER";
    field public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
    field public static final int FILL_IN_ACTION = 1; // 0x1
+18 −0
Original line number Diff line number Diff line
@@ -5914,6 +5914,14 @@ public class Intent implements Parcelable, Cloneable {
     */
    public static final String EXTRA_UID = "android.intent.extra.UID";

    /**
     * Used as an optional int extra field in {@link android.content.Intent#ACTION_PACKAGE_ADDED}
     * intents to supply the previous uid the package had been assigned.
     * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
     * system app upgrade that had left sharedUserId is getting uninstalled.
     */
    public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";

    /**
     * @hide String array of package names.
     */
@@ -5945,6 +5953,16 @@ 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_REMOVED},
     * {@link android.content.Intent#ACTION_UID_REMOVED}, and
     * {@link android.content.Intent#ACTION_PACKAGE_ADDED}
     * intents to indicate that this package is changing its UID.
     * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
     * system app upgrade that had left sharedUserId is getting uninstalled.
     */
    public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";

    /**
     * Used as an int extra field in {@link android.app.AlarmManager} pending intents
     * to tell the application being invoked how many pending alarms are being
+4 −1
Original line number Diff line number Diff line
@@ -236,7 +236,9 @@ final class DeletePackageHelper {
        if (res) {
            final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
            info.sendPackageRemovedBroadcasts(killApp, removedBySystem);
            info.sendSystemPackageUpdatedBroadcasts();
            if (disabledSystemPs != null) {
                info.sendSystemPackageUpdatedBroadcasts(disabledSystemPs.getAppId());
            }
        }
        // Force a gc here.
        Runtime.getRuntime().gc();
@@ -591,6 +593,7 @@ final class DeletePackageHelper {
        if (outInfo != null) {
            // Delete the updated package
            outInfo.mIsRemovedPackageSystemUpdate = true;
            outInfo.mAppIdChanging = disabledPs.getAppId() != deletedPs.getAppId();
        }

        if (disabledPs.getVersionCode() < deletedPs.getVersionCode()
+31 −18
Original line number Diff line number Diff line
@@ -1190,6 +1190,9 @@ final class InstallPackageHelper {
                                        + " in multi-package install request.");
                        return;
                    }
                    if (result.needsNewAppId()) {
                        request.mInstallResult.mRemovedInfo.mAppIdChanging = true;
                    }
                    createdAppId.put(packageName, optimisticallyRegisterAppId(result));
                    versionInfos.put(result.mPkgSetting.getPkg().getPackageName(),
                            mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg()));
@@ -2940,6 +2943,8 @@ final class InstallPackageHelper {
        final int dataLoaderType = installArgs.mDataLoaderType;
        final boolean succeeded = res.mReturnCode == PackageManager.INSTALL_SUCCEEDED;
        final boolean update = res.mRemovedInfo != null && res.mRemovedInfo.mRemovedPackage != null;
        final int previousAppId = (res.mRemovedInfo != null && res.mRemovedInfo.mAppIdChanging)
                ? res.mRemovedInfo.mUid : Process.INVALID_UID;
        final String packageName = res.mName;
        final PackageStateInternal pkgSetting =
                succeeded ? mPm.getPackageStateInternal(packageName) : null;
@@ -3036,9 +3041,12 @@ final class InstallPackageHelper {
                        dataLoaderType);

                // Send added for users that don't see the package for the first time
                Bundle extras = new Bundle(1);
                Bundle extras = new Bundle();
                extras.putInt(Intent.EXTRA_UID, res.mUid);
                if (update) {
                if (previousAppId != Process.INVALID_UID) {
                    extras.putBoolean(Intent.EXTRA_UID_CHANGING, true);
                    extras.putInt(Intent.EXTRA_PREVIOUS_UID, previousAppId);
                } else if (update) {
                    extras.putBoolean(Intent.EXTRA_REPLACING, true);
                }
                extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
@@ -3081,6 +3089,8 @@ final class InstallPackageHelper {

                // Send replaced for users that don't see the package for the first time
                if (update) {
                    // Only send PACKAGE_REPLACED if appId has not changed
                    if (previousAppId == Process.INVALID_UID) {
                        mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                                packageName, extras, 0 /*flags*/,
                                null /*targetPackage*/, null /*finishedReceiver*/,
@@ -3090,13 +3100,16 @@ final class InstallPackageHelper {
                            mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
                                    extras, 0 /*flags*/,
                                    installerPackageName, null /*finishedReceiver*/,
                                updateUserIds, instantUserIds, null /*broadcastAllowList*/, null);
                                    updateUserIds, instantUserIds, null /*broadcastAllowList*/,
                                    null);
                        }
                        if (notifyVerifier) {
                            mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
                                    extras, 0 /*flags*/,
                                    mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
                                updateUserIds, instantUserIds, null /*broadcastAllowList*/, null);
                                    updateUserIds, instantUserIds, null /*broadcastAllowList*/,
                                    null);
                        }
                    }
                    mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
                            null /*package*/, null /*extras*/, 0 /*flags*/,
+35 −19
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ final class PackageRemovedInfo {
    boolean mDataRemoved;
    boolean mRemovedForAllUsers;
    boolean mIsStaticSharedLib;
    boolean mAppIdChanging = false;
    // a two dimensional array mapping userId to the set of appIds that can receive notice
    // of package changes
    SparseArray<int[]> mBroadcastAllowList;
@@ -64,34 +65,44 @@ final class PackageRemovedInfo {
        sendPackageRemovedBroadcastInternal(killApp, removedBySystem);
    }

    void sendSystemPackageUpdatedBroadcasts() {
    void sendSystemPackageUpdatedBroadcasts(int newAppId) {
        if (mIsRemovedPackageSystemUpdate) {
            sendSystemPackageUpdatedBroadcastsInternal();
            sendSystemPackageUpdatedBroadcastsInternal(newAppId);
        }
    }

    private void sendSystemPackageUpdatedBroadcastsInternal() {
    private void sendSystemPackageUpdatedBroadcastsInternal(int newAppId) {
        Bundle extras = new Bundle(2);
        extras.putInt(Intent.EXTRA_UID, mRemovedAppId >= 0 ? mRemovedAppId : mUid);
        extras.putInt(Intent.EXTRA_UID, newAppId);
        // When appId changes, do not set the replacing extra
        if (mAppIdChanging) {
            extras.putBoolean(Intent.EXTRA_UID_CHANGING, true);
            extras.putInt(Intent.EXTRA_PREVIOUS_UID, mRemovedAppId >= 0 ? mRemovedAppId : mUid);
        } else {
            extras.putBoolean(Intent.EXTRA_REPLACING, true);
        }
        mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, mRemovedPackage, extras,
                0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
        mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, mRemovedPackage,
                extras, 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
        mPackageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
                mRemovedPackage, null, null, null, null /* broadcastAllowList */,
                getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle());
        if (mInstallerPackageName != null) {
            mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                    mRemovedPackage, extras, 0 /*flags*/,
                    mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
                    null);
        }
        if (!mAppIdChanging) {
            mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, mRemovedPackage,
                    extras, 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
            if (mInstallerPackageName != null) {
                mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                        mRemovedPackage, extras, 0 /*flags*/,
                        mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
                        null);
            }
        }
        mPackageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
                mRemovedPackage, null, null, null, null /* broadcastAllowList */,
                getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle());
    }

    private static @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
            @PowerExemptionManager.ReasonCode int reasonCode) {
@@ -115,15 +126,20 @@ final class PackageRemovedInfo {
        if (mIsStaticSharedLib) {
            return;
        }
        Bundle extras = new Bundle(2);
        Bundle extras = new Bundle();
        final int removedUid = mRemovedAppId >= 0  ? mRemovedAppId : mUid;
        extras.putInt(Intent.EXTRA_UID, removedUid);
        extras.putBoolean(Intent.EXTRA_DATA_REMOVED, mDataRemoved);
        extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
        extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
        if (mIsUpdate || mIsRemovedPackageSystemUpdate) {

        // When appId changes, do not set the replacing extra
        if (mAppIdChanging) {
            extras.putBoolean(Intent.EXTRA_UID_CHANGING, true);
        } else if (mIsUpdate || mIsRemovedPackageSystemUpdate) {
            extras.putBoolean(Intent.EXTRA_REPLACING, true);
        }

        extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, mRemovedForAllUsers);
        if (mRemovedPackage != null) {
            mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
@@ -146,9 +162,9 @@ final class PackageRemovedInfo {
            }
        }
        if (mRemovedAppId >= 0) {
            // If a system app's updates are uninstalled the UID is not actually removed. Some
            // services need to know the package name affected.
            if (extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
            // If the package is not actually removed, some services need to know the
            // package name affected.
            if (mAppIdChanging || mIsUpdate || mIsRemovedPackageSystemUpdate) {
                extras.putString(Intent.EXTRA_PACKAGE_NAME, mRemovedPackage);
            }