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

Commit 51aec5dc authored by Makoto Onuki's avatar Makoto Onuki Committed by android-build-merger
Browse files

Rescan apps after restore and re-publish manifest shortcuts

am: 377b7970

Change-Id: I2da62270e106408a7fec91d7442c239457be3d04
parents c327afa0 377b7970
Loading
Loading
Loading
Loading
+24 −16
Original line number Diff line number Diff line
@@ -2601,22 +2601,32 @@ public class ShortcutService extends IShortcutService.Stub {
                                /* appStillExists = */ false);
                    }
                }

                rescanUpdatedPackagesLocked(ownerUserId, user.getLastAppScanTime(),
                        /* forceRescan=*/ false);
            }
        } finally {
            logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
        }
        verifyStates();
    }

    private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime,
            boolean forceRescan) {
        final ShortcutUser user = getUserShortcutsLocked(userId);

        final long now = injectCurrentTimeMillis();

        // Then for each installed app, publish manifest shortcuts when needed.
                forUpdatedPackages(ownerUserId, user.getLastAppScanTime(), ai -> {
                    user.rescanPackageIfNeeded(ai.packageName, /* forceRescan=*/ false);
        forUpdatedPackages(userId, lastScanTime, ai -> {
            user.attemptToRestoreIfNeededAndSave(this, ai.packageName, userId);
            user.rescanPackageIfNeeded(ai.packageName, forceRescan);
        });

        // Write the time just before the scan, because there may be apps that have just
        // been updated, and we want to catch them in the next time.
        user.setLastAppScanTime(now);
                scheduleSaveUser(ownerUserId);
            }
        } finally {
            logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
        }
        verifyStates();
        scheduleSaveUser(userId);
    }

    private void handlePackageAdded(String packageName, @UserIdInt int userId) {
@@ -3119,12 +3129,10 @@ public class ShortcutService extends IShortcutService.Stub {
            }
            mUsers.put(userId, user);

            // Then purge all the save images.
            final File bitmapPath = getUserBitmapFilePath(userId);
            final boolean success = FileUtils.deleteContents(bitmapPath);
            if (!success) {
                Slog.w(TAG, "Failed to delete " + bitmapPath);
            }
            // Rescan all packages to re-publish manifest shortcuts and do other checks.
            rescanUpdatedPackagesLocked(userId,
                    0, // lastScanTime = 0; rescan all packages.
                    /* forceRescan= */ true);

            saveUserLocked(userId);
        }
+143 −9
Original line number Diff line number Diff line
@@ -57,13 +57,11 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.Manifest.permission;
import android.app.ActivityManager;
@@ -82,6 +80,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -5153,7 +5152,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
    }


    public void testBackupAndRestore_manifestNotRestored() {
    public void testBackupAndRestore_manifestRePublished() {
        // Publish two manifest shortcuts.
        addManifestShortcutResource(
                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -5162,9 +5161,15 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));

        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertTrue(mManager.setDynamicShortcuts(list(
                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
        });

        // Pin from launcher 1.
        runWithCaller(LAUNCHER_1, USER_0, () -> {
            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1", "ms2"), HANDLE_USER_0);
            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_0);
        });

        // Update and now ms2 is gone -> disabled.
@@ -5178,9 +5183,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        // Make sure the manifest shortcuts have been published.
        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertWith(getCallerShortcuts())
                    .areAllPinned()
                    .haveIds("ms1", "ms2")
                    .selectManifest()
                    .haveIds("ms1")

                    .revertToOriginalList()
                    .selectDynamic()
                    .haveIds("s1", "s2", "s3")

                    .revertToOriginalList()
                    .selectPinned()
                    .haveIds("ms1", "ms2", "s1", "s2")

                    .revertToOriginalList()
                    .selectByIds("ms1")
                    .areAllManifest()
                    .areAllEnabled()
@@ -5191,10 +5205,130 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
                    .areAllDisabled();
        });

        // Now do the regular backup & restore test.
        // The existence of the manifest shortcuts shouldn't affect the result.
        prepareCrossProfileDataSet();
        backupAndRestore();

        // When re-installing the app, the manifest shortcut should be re-published.
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(LAUNCHER_1, USER_0));

        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertWith(getCallerVisibleShortcuts())
                    .selectPinned()
                    // ms2 was disabled, so not restored.
                    .haveIds("ms1", "s1", "s2")
                    .areAllEnabled()

                    .revertToOriginalList()
                    .selectByIds("ms1")
                    .areAllManifest()

                    .revertToOriginalList()
                    .selectByIds("s1", "s2")
                    .areAllNotDynamic()
                    ;
        });
    }

    /**
     * It's the case with preintalled apps -- when applyRestore() is called, the system
     * apps are already installed, so manifest shortcuts need to be re-published.
     */
    public void testBackupAndRestore_appAlreadyInstalledWhenRestored() {
        // Pre-backup.  Same as testBackupAndRestore_manifestRePublished().

        // Publish two manifest shortcuts.
        addManifestShortcutResource(
                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                R.xml.shortcut_2);
        updatePackageVersion(CALLING_PACKAGE_1, 1);
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));

        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertTrue(mManager.setDynamicShortcuts(list(
                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
        });

        // Pin from launcher 1.
        runWithCaller(LAUNCHER_1, USER_0, () -> {
            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_0);
        });

        // Update and now ms2 is gone -> disabled.
        addManifestShortcutResource(
                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                R.xml.shortcut_1);
        updatePackageVersion(CALLING_PACKAGE_1, 1);
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));

        // Make sure the manifest shortcuts have been published.
        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertWith(getCallerShortcuts())
                    .selectManifest()
                    .haveIds("ms1")

                    .revertToOriginalList()
                    .selectDynamic()
                    .haveIds("s1", "s2", "s3")

                    .revertToOriginalList()
                    .selectPinned()
                    .haveIds("ms1", "ms2", "s1", "s2")

                    .revertToOriginalList()
                    .selectByIds("ms1")
                    .areAllManifest()
                    .areAllEnabled()

                    .revertToOriginalList()
                    .selectByIds("ms2")
                    .areAllNotManifest()
                    .areAllDisabled();
        });

        // Backup and *without restarting the service, just call applyRestore()*.
        {
            int prevUid = mInjectedCallingUid;
            mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it.

            dumpsysOnLogcat("Before backup");

            final byte[] payload = mService.getBackupPayload(USER_0);
            if (ENABLE_DUMP) {
                final String xml = new String(payload);
                Log.v(TAG, "Backup payload:");
                for (String line : xml.split("\n")) {
                    Log.v(TAG, line);
                }
            }
            mService.applyRestore(payload, USER_0);

            dumpsysOnLogcat("After restore");

            mInjectedCallingUid = prevUid;
        }

        // The check is also the same as testBackupAndRestore_manifestRePublished().
        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertWith(getCallerVisibleShortcuts())
                    .selectPinned()
                    // ms2 was disabled, so not restored.
                    .haveIds("ms1", "s1", "s2")
                    .areAllEnabled()

                    .revertToOriginalList()
                    .selectByIds("ms1")
                    .areAllManifest()

                    .revertToOriginalList()
                    .selectByIds("s1", "s2")
                    .areAllNotDynamic()
            ;
        });
    }

    public void testSaveAndLoad_crossProfile() {