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

Commit a6346907 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Rescan apps after restore and re-publish manifest shortcuts" into nyc-mr1-dev

parents 002dd297 377b7970
Loading
Loading
Loading
Loading
+24 −16
Original line number Original line Diff line number Diff line
@@ -2601,22 +2601,32 @@ public class ShortcutService extends IShortcutService.Stub {
                                /* appStillExists = */ false);
                                /* 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();
        final long now = injectCurrentTimeMillis();


        // Then for each installed app, publish manifest shortcuts when needed.
        // Then for each installed app, publish manifest shortcuts when needed.
                forUpdatedPackages(ownerUserId, user.getLastAppScanTime(), ai -> {
        forUpdatedPackages(userId, lastScanTime, ai -> {
                    user.rescanPackageIfNeeded(ai.packageName, /* forceRescan=*/ false);
            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
        // 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.
        // been updated, and we want to catch them in the next time.
        user.setLastAppScanTime(now);
        user.setLastAppScanTime(now);
                scheduleSaveUser(ownerUserId);
        scheduleSaveUser(userId);
            }
        } finally {
            logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
        }
        verifyStates();
    }
    }


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


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


            saveUserLocked(userId);
            saveUserLocked(userId);
        }
        }
+143 −9
Original line number Original line 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.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.Manifest.permission;
import android.Manifest.permission;
import android.app.ActivityManager;
import android.app.ActivityManager;
@@ -82,6 +80,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.Looper;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
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.
        // Publish two manifest shortcuts.
        addManifestShortcutResource(
        addManifestShortcutResource(
                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -5162,9 +5161,15 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        mService.mPackageMonitor.onReceive(mServiceContext,
        mService.mPackageMonitor.onReceive(mServiceContext,
                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
                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.
        // Pin from launcher 1.
        runWithCaller(LAUNCHER_1, USER_0, () -> {
        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.
        // Update and now ms2 is gone -> disabled.
@@ -5178,9 +5183,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        // Make sure the manifest shortcuts have been published.
        // Make sure the manifest shortcuts have been published.
        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
            assertWith(getCallerShortcuts())
            assertWith(getCallerShortcuts())
                    .areAllPinned()
                    .selectManifest()
                    .haveIds("ms1", "ms2")
                    .haveIds("ms1")

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

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


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


        // Now do the regular backup & restore test.
        // The existence of the manifest shortcuts shouldn't affect the result.
        prepareCrossProfileDataSet();
        backupAndRestore();
        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() {
    public void testSaveAndLoad_crossProfile() {