Merge "When app is updated, save the new version code, and update shortcuts with resource based icons." into nyc-dev
This commit is contained in:
@@ -109,6 +109,27 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
return getPackageUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a shortcut is about to be published. At this point we know the publisher package
|
||||
* exists (as opposed to Launcher trying to fetch shortcuts from a non-existent package), so
|
||||
* we do some initialization for the package.
|
||||
*/
|
||||
private void onShortcutPublish(ShortcutService s) {
|
||||
// Make sure we have the version code for the app. We need the version code in
|
||||
// handlePackageUpdated().
|
||||
if (getPackageInfo().getVersionCode() < 0) {
|
||||
final int versionCode = s.getApplicationVersionCode(getPackageName(), getOwnerUserId());
|
||||
if (ShortcutService.DEBUG) {
|
||||
Slog.d(TAG, String.format("Package %s version = %d", getPackageName(),
|
||||
versionCode));
|
||||
}
|
||||
if (versionCode >= 0) {
|
||||
getPackageInfo().setVersionCode(versionCode);
|
||||
s.scheduleSaveUser(getOwnerUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreBlocked(ShortcutService s) {
|
||||
// Can't restore due to version/signature mismatch. Remove all shortcuts.
|
||||
@@ -153,6 +174,9 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
*/
|
||||
public void addDynamicShortcut(@NonNull ShortcutService s,
|
||||
@NonNull ShortcutInfo newShortcut) {
|
||||
|
||||
onShortcutPublish(s);
|
||||
|
||||
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
|
||||
|
||||
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
|
||||
@@ -387,6 +411,40 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
mApiCallCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the package is updated. If there are shortcuts with resource icons, update
|
||||
* their timestamps.
|
||||
*/
|
||||
public void handlePackageUpdated(ShortcutService s, int newVersionCode) {
|
||||
if (getPackageInfo().getVersionCode() >= newVersionCode) {
|
||||
// Version hasn't changed; nothing to do.
|
||||
return;
|
||||
}
|
||||
if (ShortcutService.DEBUG) {
|
||||
Slog.d(TAG, String.format("Package %s updated, version %d -> %d", getPackageName(),
|
||||
getPackageInfo().getVersionCode(), newVersionCode));
|
||||
}
|
||||
|
||||
getPackageInfo().setVersionCode(newVersionCode);
|
||||
|
||||
boolean changed = false;
|
||||
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
|
||||
final ShortcutInfo si = mShortcuts.valueAt(i);
|
||||
|
||||
if (si.hasIconResource()) {
|
||||
changed = true;
|
||||
si.setTimestamp(s.injectCurrentTimeMillis());
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
// This will send a notification to the launcher, and also save .
|
||||
s.packageShortcutsChanged(getPackageName(), getPackageUserId());
|
||||
} else {
|
||||
// Still save the version code.
|
||||
s.scheduleSaveUser(getPackageUserId());
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
|
||||
pw.println();
|
||||
|
||||
@@ -413,17 +471,20 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
getPackageInfo().dump(s, pw, prefix + " ");
|
||||
pw.println();
|
||||
|
||||
pw.println(" Shortcuts:");
|
||||
pw.print(prefix);
|
||||
pw.println(" Shortcuts:");
|
||||
long totalBitmapSize = 0;
|
||||
final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
|
||||
final int size = shortcuts.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final ShortcutInfo si = shortcuts.valueAt(i);
|
||||
pw.print(" ");
|
||||
pw.print(prefix);
|
||||
pw.print(" ");
|
||||
pw.println(si.toInsecureString());
|
||||
if (si.getBitmapPath() != null) {
|
||||
final long len = new File(si.getBitmapPath()).length();
|
||||
pw.print(" ");
|
||||
pw.print(prefix);
|
||||
pw.print(" ");
|
||||
pw.print("bitmap size=");
|
||||
pw.println(len);
|
||||
|
||||
|
||||
@@ -45,12 +45,14 @@ class ShortcutPackageInfo {
|
||||
private static final String TAG_SIGNATURE = "signature";
|
||||
private static final String ATTR_SIGNATURE_HASH = "hash";
|
||||
|
||||
private static final int VERSION_UNKNOWN = -1;
|
||||
|
||||
/**
|
||||
* When true, this package information was restored from the previous device, and the app hasn't
|
||||
* been installed yet.
|
||||
*/
|
||||
private boolean mIsShadow;
|
||||
private int mVersionCode;
|
||||
private int mVersionCode = VERSION_UNKNOWN;
|
||||
private ArrayList<byte[]> mSigHashes;
|
||||
|
||||
private ShortcutPackageInfo(int versionCode, ArrayList<byte[]> sigHashes, boolean isShadow) {
|
||||
@@ -60,7 +62,7 @@ class ShortcutPackageInfo {
|
||||
}
|
||||
|
||||
public static ShortcutPackageInfo newEmpty() {
|
||||
return new ShortcutPackageInfo(0, new ArrayList<>(0), /* isShadow */ false);
|
||||
return new ShortcutPackageInfo(VERSION_UNKNOWN, new ArrayList<>(0), /* isShadow */ false);
|
||||
}
|
||||
|
||||
public boolean isShadow() {
|
||||
@@ -75,6 +77,10 @@ class ShortcutPackageInfo {
|
||||
return mVersionCode;
|
||||
}
|
||||
|
||||
public void setVersionCode(int versionCode) {
|
||||
mVersionCode = versionCode;
|
||||
}
|
||||
|
||||
public boolean hasSignatures() {
|
||||
return mSigHashes.size() > 0;
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
// Preload
|
||||
getUserShortcutsLocked(userId);
|
||||
|
||||
cleanupGonePackages(userId);
|
||||
checkPackageChanges(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1158,7 +1158,11 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
* - Sends a notification to LauncherApps
|
||||
* - Write to file
|
||||
*/
|
||||
private void userPackageChanged(@NonNull String packageName, @UserIdInt int userId) {
|
||||
void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, String.format(
|
||||
"Shortcut changes: package=%s, user=%d", packageName, userId));
|
||||
}
|
||||
notifyListeners(packageName, userId);
|
||||
scheduleSaveUser(userId);
|
||||
}
|
||||
@@ -1284,7 +1288,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
ps.addDynamicShortcut(this, newShortcut);
|
||||
}
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1323,7 +1327,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
}
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1353,7 +1357,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
ps.addDynamicShortcut(this, newShortcut);
|
||||
}
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1370,7 +1374,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)));
|
||||
}
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1380,7 +1384,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
synchronized (mLock) {
|
||||
getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts(this);
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1729,7 +1733,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
launcher.pinShortcuts(
|
||||
ShortcutService.this, userId, packageName, shortcutIds);
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
packageShortcutsChanged(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1841,13 +1845,15 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a user is unlocked. Check all known packages still exist, and otherwise
|
||||
* perform cleanup.
|
||||
* Called when a user is unlocked.
|
||||
* - Check all known packages still exist, and otherwise perform cleanup.
|
||||
* - If a package still exists, check the version code. If it's been updated, may need to
|
||||
* update timestamps of its shortcuts.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void cleanupGonePackages(@UserIdInt int ownerUserId) {
|
||||
void checkPackageChanges(@UserIdInt int ownerUserId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "cleanupGonePackages() ownerUserId=" + ownerUserId);
|
||||
Slog.d(TAG, "checkPackageChanges() ownerUserId=" + ownerUserId);
|
||||
}
|
||||
final ArrayList<PackageWithUser> gonePackages = new ArrayList<>();
|
||||
|
||||
@@ -1858,10 +1864,15 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
if (spi.getPackageInfo().isShadow()) {
|
||||
return; // Don't delete shadow information.
|
||||
}
|
||||
if (isPackageInstalled(spi.getPackageName(), spi.getPackageUserId())) {
|
||||
return; // Package not gone.
|
||||
final int versionCode = getApplicationVersionCode(
|
||||
spi.getPackageName(), spi.getPackageUserId());
|
||||
if (versionCode >= 0) {
|
||||
// Package still installed, see if it's updated.
|
||||
getUserShortcutsLocked(ownerUserId).handlePackageUpdated(
|
||||
this, spi.getPackageName(), versionCode);
|
||||
} else {
|
||||
gonePackages.add(PackageWithUser.of(spi));
|
||||
}
|
||||
gonePackages.add(PackageWithUser.of(spi));
|
||||
});
|
||||
if (gonePackages.size() > 0) {
|
||||
for (int i = gonePackages.size() - 1; i >= 0; i--) {
|
||||
@@ -1890,6 +1901,12 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
synchronized (mLock) {
|
||||
forEachLoadedUserLocked(user ->
|
||||
user.attemptToRestoreIfNeededAndSave(this, packageName, userId));
|
||||
|
||||
final int versionCode = getApplicationVersionCode(packageName, userId);
|
||||
if (versionCode < 0) {
|
||||
return; // shouldn't happen
|
||||
}
|
||||
getUserShortcutsLocked(userId).handlePackageUpdated(this, packageName, versionCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,6 +1995,17 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_INSTALLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version code of the package, or -1 if the app is not installed.
|
||||
*/
|
||||
int getApplicationVersionCode(String packageName, int userId) {
|
||||
final ApplicationInfo ai = injectApplicationInfo(packageName, userId);
|
||||
if ((ai == null) || ((ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
|
||||
return -1;
|
||||
}
|
||||
return ai.versionCode;
|
||||
}
|
||||
|
||||
// === Backup & restore ===
|
||||
|
||||
boolean shouldBackupApp(String packageName, int userId) {
|
||||
@@ -2100,7 +2128,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
pw.println(mResetInterval);
|
||||
pw.print(" maxUpdatesPerInterval: ");
|
||||
pw.println(mMaxUpdatesPerInterval);
|
||||
pw.print(" maxDynamicShortcuts:");
|
||||
pw.print(" maxDynamicShortcuts: ");
|
||||
pw.println(mMaxDynamicShortcuts);
|
||||
pw.println();
|
||||
|
||||
|
||||
@@ -176,6 +176,17 @@ class ShortcutUser {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a package is updated.
|
||||
*/
|
||||
public void handlePackageUpdated(ShortcutService s, @NonNull String packageName,
|
||||
int newVersionCode) {
|
||||
if (!mPackages.containsKey(packageName)) {
|
||||
return;
|
||||
}
|
||||
getPackageShortcuts(s, packageName).handlePackageUpdated(s, newVersionCode);
|
||||
}
|
||||
|
||||
public void attemptToRestoreIfNeededAndSave(ShortcutService s, @NonNull String packageName,
|
||||
@UserIdInt int packageUserId) {
|
||||
forPackageItem(packageName, packageUserId, spi -> {
|
||||
|
||||
@@ -36,6 +36,7 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicOnly;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.findShortcut;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
|
||||
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
|
||||
@@ -644,6 +645,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED
|
||||
| ApplicationInfo.FLAG_ALLOW_BACKUP;
|
||||
pi.versionCode = version;
|
||||
pi.applicationInfo.versionCode = version;
|
||||
pi.signatures = genSignatures(signatures);
|
||||
|
||||
return pi;
|
||||
@@ -657,6 +659,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
c.accept(mInjectedPackages.get(packageName));
|
||||
}
|
||||
|
||||
private void updatePackageVersion(String packageName, int increment) {
|
||||
updatePackageInfo(packageName, pi -> {
|
||||
pi.versionCode += increment;
|
||||
pi.applicationInfo.versionCode += increment;
|
||||
});
|
||||
}
|
||||
|
||||
private void uninstallPackage(int userId, String packageName) {
|
||||
if (ENABLE_DUMP) {
|
||||
Log.i(TAG, "Unnstall package " + packageName + " / " + userId);
|
||||
@@ -3839,7 +3848,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
|
||||
// Start uninstalling.
|
||||
uninstallPackage(USER_10, LAUNCHER_1);
|
||||
mService.cleanupGonePackages(USER_10);
|
||||
mService.checkPackageChanges(USER_10);
|
||||
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
|
||||
@@ -3859,7 +3868,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
|
||||
// Uninstall.
|
||||
uninstallPackage(USER_10, CALLING_PACKAGE_1);
|
||||
mService.cleanupGonePackages(USER_10);
|
||||
mService.checkPackageChanges(USER_10);
|
||||
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
|
||||
@@ -3878,7 +3887,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
|
||||
|
||||
uninstallPackage(USER_P0, LAUNCHER_1);
|
||||
mService.cleanupGonePackages(USER_0);
|
||||
mService.checkPackageChanges(USER_0);
|
||||
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
|
||||
assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
|
||||
@@ -3896,7 +3905,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
|
||||
assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
|
||||
|
||||
mService.cleanupGonePackages(USER_P0);
|
||||
mService.checkPackageChanges(USER_P0);
|
||||
|
||||
assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
|
||||
assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
|
||||
@@ -4150,6 +4159,193 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
|
||||
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
|
||||
}
|
||||
|
||||
public void testHandlePackageUpdate() throws Throwable {
|
||||
|
||||
// Set up shortcuts and launchers.
|
||||
|
||||
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
|
||||
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
|
||||
getTestContext().getResources(), R.drawable.black_32x32));
|
||||
|
||||
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
|
||||
assertTrue(mManager.setDynamicShortcuts(list(
|
||||
makeShortcut("s1"),
|
||||
makeShortcutWithIcon("s2", res32x32),
|
||||
makeShortcutWithIcon("s3", res32x32),
|
||||
makeShortcutWithIcon("s4", bmp32x32))));
|
||||
});
|
||||
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
|
||||
assertTrue(mManager.setDynamicShortcuts(list(
|
||||
makeShortcut("s1"),
|
||||
makeShortcutWithIcon("s2", bmp32x32))));
|
||||
});
|
||||
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
|
||||
assertTrue(mManager.setDynamicShortcuts(list(
|
||||
makeShortcutWithIcon("s1", res32x32))));
|
||||
});
|
||||
|
||||
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
|
||||
assertTrue(mManager.setDynamicShortcuts(list(
|
||||
makeShortcutWithIcon("s1", res32x32),
|
||||
makeShortcutWithIcon("s2", res32x32))));
|
||||
});
|
||||
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
|
||||
assertTrue(mManager.setDynamicShortcuts(list(
|
||||
makeShortcutWithIcon("s1", bmp32x32),
|
||||
makeShortcutWithIcon("s2", bmp32x32))));
|
||||
});
|
||||
|
||||
LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
|
||||
LauncherApps.Callback c10 = mock(LauncherApps.Callback.class);
|
||||
|
||||
runWithCaller(LAUNCHER_1, USER_0, () -> {
|
||||
mLauncherApps.registerCallback(c0, new Handler(Looper.getMainLooper()));
|
||||
});
|
||||
runWithCaller(LAUNCHER_1, USER_10, () -> {
|
||||
mLauncherApps.registerCallback(c10, new Handler(Looper.getMainLooper()));
|
||||
});
|
||||
|
||||
mInjectedCurrentTimeLillis = START_TIME + 100;
|
||||
|
||||
ArgumentCaptor<List> shortcuts;
|
||||
|
||||
// First, call the event without updating the versions.
|
||||
reset(c0);
|
||||
reset(c10);
|
||||
|
||||
mService.mPackageMonitor.onReceive(getTestContext(),
|
||||
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
|
||||
mService.mPackageMonitor.onReceive(getTestContext(),
|
||||
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
|
||||
|
||||
waitOnMainThread();
|
||||
|
||||
// Version not changed, so no callback.
|
||||
verify(c0, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
verify(c10, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
|
||||
// Next, update the version info for package 1.
|
||||
reset(c0);
|
||||
reset(c10);
|
||||
updatePackageVersion(CALLING_PACKAGE_1, 1);
|
||||
|
||||
// Then send the broadcast, to only user-0.
|
||||
mService.mPackageMonitor.onReceive(getTestContext(),
|
||||
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
|
||||
|
||||
waitOnMainThread();
|
||||
|
||||
// User-0 should get the notification.
|
||||
shortcuts = ArgumentCaptor.forClass(List.class);
|
||||
verify(c0).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
shortcuts.capture(),
|
||||
eq(HANDLE_USER_0));
|
||||
|
||||
// User-10 shouldn't yet get the notification.
|
||||
verify(c10, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
assertShortcutIds(shortcuts.getValue(), "s1", "s2", "s3", "s4");
|
||||
assertEquals(START_TIME,
|
||||
findShortcut(shortcuts.getValue(), "s1").getLastChangedTimestamp());
|
||||
assertEquals(START_TIME + 100,
|
||||
findShortcut(shortcuts.getValue(), "s2").getLastChangedTimestamp());
|
||||
assertEquals(START_TIME + 100,
|
||||
findShortcut(shortcuts.getValue(), "s3").getLastChangedTimestamp());
|
||||
assertEquals(START_TIME,
|
||||
findShortcut(shortcuts.getValue(), "s4").getLastChangedTimestamp());
|
||||
|
||||
// Next, send unlock even on user-10. Now we scan packages on this user and send a
|
||||
// notification to the launcher.
|
||||
mInjectedCurrentTimeLillis = START_TIME + 200;
|
||||
|
||||
when(mMockUserManager.isUserRunning(eq(USER_10))).thenReturn(true);
|
||||
|
||||
reset(c0);
|
||||
reset(c10);
|
||||
mService.handleUnlockUser(USER_10);
|
||||
|
||||
shortcuts = ArgumentCaptor.forClass(List.class);
|
||||
verify(c0, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
|
||||
verify(c10).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
shortcuts.capture(),
|
||||
eq(HANDLE_USER_10));
|
||||
|
||||
assertShortcutIds(shortcuts.getValue(), "s1", "s2");
|
||||
assertEquals(START_TIME + 200,
|
||||
findShortcut(shortcuts.getValue(), "s1").getLastChangedTimestamp());
|
||||
assertEquals(START_TIME + 200,
|
||||
findShortcut(shortcuts.getValue(), "s2").getLastChangedTimestamp());
|
||||
|
||||
|
||||
// Do the same thing for package 2, which doesn't have resource icons.
|
||||
mInjectedCurrentTimeLillis = START_TIME + 300;
|
||||
|
||||
reset(c0);
|
||||
reset(c10);
|
||||
updatePackageVersion(CALLING_PACKAGE_2, 10);
|
||||
|
||||
// Then send the broadcast, to only user-0.
|
||||
mService.mPackageMonitor.onReceive(getTestContext(),
|
||||
genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
|
||||
mService.handleUnlockUser(USER_10);
|
||||
|
||||
waitOnMainThread();
|
||||
|
||||
verify(c0, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
|
||||
verify(c10, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_1),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
|
||||
// Do the same thing for package 3
|
||||
mInjectedCurrentTimeLillis = START_TIME + 400;
|
||||
|
||||
reset(c0);
|
||||
reset(c10);
|
||||
updatePackageVersion(CALLING_PACKAGE_3, 100);
|
||||
|
||||
// Then send the broadcast, to only user-0.
|
||||
mService.mPackageMonitor.onReceive(getTestContext(),
|
||||
genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
|
||||
mService.handleUnlockUser(USER_10);
|
||||
|
||||
waitOnMainThread();
|
||||
|
||||
shortcuts = ArgumentCaptor.forClass(List.class);
|
||||
verify(c0).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_3),
|
||||
shortcuts.capture(),
|
||||
eq(HANDLE_USER_0));
|
||||
|
||||
// User 10 doesn't have package 3, so no callback.
|
||||
verify(c10, times(0)).onShortcutsChanged(
|
||||
eq(CALLING_PACKAGE_3),
|
||||
any(List.class),
|
||||
any(UserHandle.class));
|
||||
|
||||
assertShortcutIds(shortcuts.getValue(), "s1");
|
||||
assertEquals(START_TIME + 400,
|
||||
findShortcut(shortcuts.getValue(), "s1").getLastChangedTimestamp());
|
||||
}
|
||||
|
||||
private void backupAndRestore() {
|
||||
int prevUid = mInjectedCallingUid;
|
||||
|
||||
|
||||
@@ -413,6 +413,16 @@ public class ShortcutManagerTestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static ShortcutInfo findShortcut(List<ShortcutInfo> list, String id) {
|
||||
for (ShortcutInfo si : list) {
|
||||
if (si.getId().equals(id)) {
|
||||
return si;
|
||||
}
|
||||
}
|
||||
fail("Shortcut " + id + " not found in the list");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Bitmap pfdToBitmap(ParcelFileDescriptor pfd) {
|
||||
assertNotNull(pfd);
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user