Loading services/core/java/com/android/server/pm/ShortcutPackage.java +6 −0 Original line number Diff line number Diff line Loading @@ -667,6 +667,12 @@ class ShortcutPackage extends ShortcutPackageItem { // - version code hasn't change // - lastUpdateTime hasn't change // - all target activities are still enabled. // Note, system apps timestamps do *not* change after OTAs. (But they do // after an adb sync or a local flash.) // This means if a system app's version code doesn't change on an OTA, // we don't notice it's updated. But that's fine since their version code *should* // really change on OTAs. if ((getPackageInfo().getVersionCode() == pi.versionCode) && (getPackageInfo().getLastUpdateTime() == pi.lastUpdateTime) && areAllActivitiesStillEnabled()) { Loading services/core/java/com/android/server/pm/ShortcutService.java +16 −3 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.graphics.RectF; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; Loading Loading @@ -2659,10 +2660,14 @@ public class ShortcutService extends IShortcutService.Stub { boolean forceRescan) { final ShortcutUser user = getUserShortcutsLocked(userId); // Note after each OTA, we'll need to rescan all system apps, as their lastUpdateTime // is not reliable. final long now = injectCurrentTimeMillis(); final boolean afterOta = !injectBuildFingerprint().equals(user.getLastAppScanOsFingerprint()); // Then for each installed app, publish manifest shortcuts when needed. forUpdatedPackages(userId, lastScanTime, ai -> { forUpdatedPackages(userId, lastScanTime, afterOta, ai -> { user.attemptToRestoreIfNeededAndSave(this, ai.packageName, userId); user.rescanPackageIfNeeded(ai.packageName, forceRescan); }); Loading @@ -2670,6 +2675,7 @@ public class ShortcutService extends IShortcutService.Stub { // 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); user.setLastAppScanOsFingerprint(injectBuildFingerprint()); scheduleSaveUser(userId); } Loading Loading @@ -2908,7 +2914,7 @@ public class ShortcutService extends IShortcutService.Stub { return parceledList.getList(); } private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, boolean afterOta, Consumer<ApplicationInfo> callback) { if (DEBUG) { Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime); Loading @@ -2920,7 +2926,8 @@ public class ShortcutService extends IShortcutService.Stub { // If the package has been updated since the last scan time, then scan it. // Also if it's a system app with no update, lastUpdateTime is not reliable, so // just scan it. if (pi.lastUpdateTime >= lastScanTime || isPureSystemApp(pi.applicationInfo)) { if (pi.lastUpdateTime >= lastScanTime || (afterOta && isPureSystemApp(pi.applicationInfo))) { if (DEBUG) { Slog.d(TAG, "Found updated package " + pi.packageName); } Loading Loading @@ -3598,6 +3605,12 @@ public class ShortcutService extends IShortcutService.Stub { Binder.restoreCallingIdentity(token); } // Injection point. @VisibleForTesting String injectBuildFingerprint() { return Build.FINGERPRINT; } final void wtf(String message) { wtf(message, /* exception= */ null); } Loading services/core/java/com/android/server/pm/ShortcutUser.java +17 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ class ShortcutUser { // Suffix "2" was added to force rescan all packages after the next OTA. private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time2"; private static final String ATTR_LAST_APP_SCAN_OS_FINGERPRINT = "last-app-scan-fp"; private static final String KEY_USER_ID = "userId"; private static final String KEY_LAUNCHERS = "launchers"; private static final String KEY_PACKAGES = "packages"; Loading Loading @@ -125,6 +126,8 @@ class ShortcutUser { private long mLastAppScanTime; private String mLastAppScanOsFingerprint; public ShortcutUser(ShortcutService service, int userId) { mService = service; mUserId = userId; Loading @@ -142,6 +145,14 @@ class ShortcutUser { mLastAppScanTime = lastAppScanTime; } public String getLastAppScanOsFingerprint() { return mLastAppScanOsFingerprint; } public void setLastAppScanOsFingerprint(String lastAppScanOsFingerprint) { mLastAppScanOsFingerprint = lastAppScanOsFingerprint; } // We don't expose this directly to non-test code because only ShortcutUser should add to/ // remove from it. @VisibleForTesting Loading Loading @@ -318,6 +329,8 @@ class ShortcutUser { ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales); ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME, mLastAppScanTime); ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_OS_FINGERPRINT, mLastAppScanOsFingerprint); ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher); Loading Loading @@ -364,7 +377,8 @@ class ShortcutUser { ATTR_LAST_APP_SCAN_TIME); final long currentTime = s.injectCurrentTimeMillis(); ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0; ret.mLastAppScanOsFingerprint = ShortcutService.parseStringAttribute(parser, ATTR_LAST_APP_SCAN_OS_FINGERPRINT); final int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT Loading Loading @@ -457,6 +471,8 @@ class ShortcutUser { pw.print(mLastAppScanTime); pw.print("] "); pw.print(ShortcutService.formatTime(mLastAppScanTime)); pw.print(" Last app scan FP: "); pw.print(mLastAppScanOsFingerprint); pw.println(); prefix += prefix + " "; Loading services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +12 −0 Original line number Diff line number Diff line Loading @@ -406,6 +406,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { return mSafeMode; } @Override String injectBuildFingerprint() { return mInjectedBuildFingerprint; } @Override void wtf(String message, Throwable th) { // During tests, WTF is fatal. Loading Loading @@ -528,6 +533,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected Map<String, PackageInfo> mInjectedPackages; protected Set<PackageWithUser> mUninstalledPackages; protected Set<String> mSystemPackages; protected PackageManager mMockPackageManager; protected PackageManagerInternal mMockPackageManagerInternal; Loading Loading @@ -628,6 +634,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback"; protected static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999; protected String mInjectedBuildFingerprint = "build1"; static { QUERY_ALL.setQueryFlags( ShortcutQuery.FLAG_GET_ALL_KINDS); Loading Loading @@ -677,6 +685,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); mUninstalledPackages = new HashSet<>(); mSystemPackages = new HashSet<>(); mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); Loading Loading @@ -963,6 +972,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) { ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; } if (mSystemPackages.contains(packageName)) { ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; } if (getSignatures) { ret.signatures = pi.signatures; Loading services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +122 −0 Original line number Diff line number Diff line Loading @@ -4347,6 +4347,128 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { }); } public void testHandlePackageUpdate_systemAppUpdate() { // Package1 is a system app. Package 2 is not a system app, so it's not scanned // in this test at all. mSystemPackages.add(CALLING_PACKAGE_1); // Initial state: no shortcuts. mService.checkPackageChanges(USER_0); assertEquals(mInjectedCurrentTimeMillis, mService.getUserShortcutsLocked(USER_0).getLastAppScanTime()); assertEquals(mInjectedBuildFingerprint, mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint()); // They have no shortcuts. runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update the packages -- now they have 1 manifest shortcut. // But checkPackageChanges() don't notice it, since their version code / timestamp haven't // changed. addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), R.xml.shortcut_1); addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()), R.xml.shortcut_1); mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update the build finger print. All system apps will be scanned now. mInjectedBuildFingerprint = "update1"; mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update manifest shortcuts. mInjectedBuildFingerprint = "update2"; addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), R.xml.shortcut_2); addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()), R.xml.shortcut_2); mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); // Fingerprint hasn't changed, so CALLING_PACKAGE_1 wasn't scanned. runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Update the fingerprint, but CALLING_PACKAGE_1's version code hasn't changed, so // still not scanned. mInjectedBuildFingerprint = "update2"; mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Now update the version code, so CALLING_PACKAGE_1 is scanned again. mInjectedBuildFingerprint = "update3"; mInjectedCurrentTimeMillis += 1000; updatePackageVersion(CALLING_PACKAGE_1, 1); mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1", "ms2"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Make sure getLastAppScanTime / getLastAppScanOsFingerprint are persisted. initService(); assertEquals(mInjectedCurrentTimeMillis, mService.getUserShortcutsLocked(USER_0).getLastAppScanTime()); assertEquals(mInjectedBuildFingerprint, mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint()); } public void testHandlePackageChanged() { final ComponentName ACTIVITY1 = new ComponentName(CALLING_PACKAGE_1, "act1"); final ComponentName ACTIVITY2 = new ComponentName(CALLING_PACKAGE_1, "act2"); Loading Loading
services/core/java/com/android/server/pm/ShortcutPackage.java +6 −0 Original line number Diff line number Diff line Loading @@ -667,6 +667,12 @@ class ShortcutPackage extends ShortcutPackageItem { // - version code hasn't change // - lastUpdateTime hasn't change // - all target activities are still enabled. // Note, system apps timestamps do *not* change after OTAs. (But they do // after an adb sync or a local flash.) // This means if a system app's version code doesn't change on an OTA, // we don't notice it's updated. But that's fine since their version code *should* // really change on OTAs. if ((getPackageInfo().getVersionCode() == pi.versionCode) && (getPackageInfo().getLastUpdateTime() == pi.lastUpdateTime) && areAllActivitiesStillEnabled()) { Loading
services/core/java/com/android/server/pm/ShortcutService.java +16 −3 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.graphics.RectF; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; Loading Loading @@ -2659,10 +2660,14 @@ public class ShortcutService extends IShortcutService.Stub { boolean forceRescan) { final ShortcutUser user = getUserShortcutsLocked(userId); // Note after each OTA, we'll need to rescan all system apps, as their lastUpdateTime // is not reliable. final long now = injectCurrentTimeMillis(); final boolean afterOta = !injectBuildFingerprint().equals(user.getLastAppScanOsFingerprint()); // Then for each installed app, publish manifest shortcuts when needed. forUpdatedPackages(userId, lastScanTime, ai -> { forUpdatedPackages(userId, lastScanTime, afterOta, ai -> { user.attemptToRestoreIfNeededAndSave(this, ai.packageName, userId); user.rescanPackageIfNeeded(ai.packageName, forceRescan); }); Loading @@ -2670,6 +2675,7 @@ public class ShortcutService extends IShortcutService.Stub { // 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); user.setLastAppScanOsFingerprint(injectBuildFingerprint()); scheduleSaveUser(userId); } Loading Loading @@ -2908,7 +2914,7 @@ public class ShortcutService extends IShortcutService.Stub { return parceledList.getList(); } private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, boolean afterOta, Consumer<ApplicationInfo> callback) { if (DEBUG) { Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime); Loading @@ -2920,7 +2926,8 @@ public class ShortcutService extends IShortcutService.Stub { // If the package has been updated since the last scan time, then scan it. // Also if it's a system app with no update, lastUpdateTime is not reliable, so // just scan it. if (pi.lastUpdateTime >= lastScanTime || isPureSystemApp(pi.applicationInfo)) { if (pi.lastUpdateTime >= lastScanTime || (afterOta && isPureSystemApp(pi.applicationInfo))) { if (DEBUG) { Slog.d(TAG, "Found updated package " + pi.packageName); } Loading Loading @@ -3598,6 +3605,12 @@ public class ShortcutService extends IShortcutService.Stub { Binder.restoreCallingIdentity(token); } // Injection point. @VisibleForTesting String injectBuildFingerprint() { return Build.FINGERPRINT; } final void wtf(String message) { wtf(message, /* exception= */ null); } Loading
services/core/java/com/android/server/pm/ShortcutUser.java +17 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ class ShortcutUser { // Suffix "2" was added to force rescan all packages after the next OTA. private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time2"; private static final String ATTR_LAST_APP_SCAN_OS_FINGERPRINT = "last-app-scan-fp"; private static final String KEY_USER_ID = "userId"; private static final String KEY_LAUNCHERS = "launchers"; private static final String KEY_PACKAGES = "packages"; Loading Loading @@ -125,6 +126,8 @@ class ShortcutUser { private long mLastAppScanTime; private String mLastAppScanOsFingerprint; public ShortcutUser(ShortcutService service, int userId) { mService = service; mUserId = userId; Loading @@ -142,6 +145,14 @@ class ShortcutUser { mLastAppScanTime = lastAppScanTime; } public String getLastAppScanOsFingerprint() { return mLastAppScanOsFingerprint; } public void setLastAppScanOsFingerprint(String lastAppScanOsFingerprint) { mLastAppScanOsFingerprint = lastAppScanOsFingerprint; } // We don't expose this directly to non-test code because only ShortcutUser should add to/ // remove from it. @VisibleForTesting Loading Loading @@ -318,6 +329,8 @@ class ShortcutUser { ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales); ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME, mLastAppScanTime); ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_OS_FINGERPRINT, mLastAppScanOsFingerprint); ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher); Loading Loading @@ -364,7 +377,8 @@ class ShortcutUser { ATTR_LAST_APP_SCAN_TIME); final long currentTime = s.injectCurrentTimeMillis(); ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0; ret.mLastAppScanOsFingerprint = ShortcutService.parseStringAttribute(parser, ATTR_LAST_APP_SCAN_OS_FINGERPRINT); final int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT Loading Loading @@ -457,6 +471,8 @@ class ShortcutUser { pw.print(mLastAppScanTime); pw.print("] "); pw.print(ShortcutService.formatTime(mLastAppScanTime)); pw.print(" Last app scan FP: "); pw.print(mLastAppScanOsFingerprint); pw.println(); prefix += prefix + " "; Loading
services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +12 −0 Original line number Diff line number Diff line Loading @@ -406,6 +406,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { return mSafeMode; } @Override String injectBuildFingerprint() { return mInjectedBuildFingerprint; } @Override void wtf(String message, Throwable th) { // During tests, WTF is fatal. Loading Loading @@ -528,6 +533,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected Map<String, PackageInfo> mInjectedPackages; protected Set<PackageWithUser> mUninstalledPackages; protected Set<String> mSystemPackages; protected PackageManager mMockPackageManager; protected PackageManagerInternal mMockPackageManagerInternal; Loading Loading @@ -628,6 +634,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback"; protected static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999; protected String mInjectedBuildFingerprint = "build1"; static { QUERY_ALL.setQueryFlags( ShortcutQuery.FLAG_GET_ALL_KINDS); Loading Loading @@ -677,6 +685,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP); mUninstalledPackages = new HashSet<>(); mSystemPackages = new HashSet<>(); mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); Loading Loading @@ -963,6 +972,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) { ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; } if (mSystemPackages.contains(packageName)) { ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; } if (getSignatures) { ret.signatures = pi.signatures; Loading
services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +122 −0 Original line number Diff line number Diff line Loading @@ -4347,6 +4347,128 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { }); } public void testHandlePackageUpdate_systemAppUpdate() { // Package1 is a system app. Package 2 is not a system app, so it's not scanned // in this test at all. mSystemPackages.add(CALLING_PACKAGE_1); // Initial state: no shortcuts. mService.checkPackageChanges(USER_0); assertEquals(mInjectedCurrentTimeMillis, mService.getUserShortcutsLocked(USER_0).getLastAppScanTime()); assertEquals(mInjectedBuildFingerprint, mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint()); // They have no shortcuts. runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update the packages -- now they have 1 manifest shortcut. // But checkPackageChanges() don't notice it, since their version code / timestamp haven't // changed. addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), R.xml.shortcut_1); addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()), R.xml.shortcut_1); mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update the build finger print. All system apps will be scanned now. mInjectedBuildFingerprint = "update1"; mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Next. // Update manifest shortcuts. mInjectedBuildFingerprint = "update2"; addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), R.xml.shortcut_2); addManifestShortcutResource( new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()), R.xml.shortcut_2); mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); // Fingerprint hasn't changed, so CALLING_PACKAGE_1 wasn't scanned. runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Update the fingerprint, but CALLING_PACKAGE_1's version code hasn't changed, so // still not scanned. mInjectedBuildFingerprint = "update2"; mInjectedCurrentTimeMillis += 1000; mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Now update the version code, so CALLING_PACKAGE_1 is scanned again. mInjectedBuildFingerprint = "update3"; mInjectedCurrentTimeMillis += 1000; updatePackageVersion(CALLING_PACKAGE_1, 1); mService.checkPackageChanges(USER_0); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1", "ms2"); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertWith(getCallerShortcuts()) .isEmpty(); }); // Make sure getLastAppScanTime / getLastAppScanOsFingerprint are persisted. initService(); assertEquals(mInjectedCurrentTimeMillis, mService.getUserShortcutsLocked(USER_0).getLastAppScanTime()); assertEquals(mInjectedBuildFingerprint, mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint()); } public void testHandlePackageChanged() { final ComponentName ACTIVITY1 = new ComponentName(CALLING_PACKAGE_1, "act1"); final ComponentName ACTIVITY2 = new ComponentName(CALLING_PACKAGE_1, "act2"); Loading