Merge "Rescan apps after restore and re-publish manifest shortcuts" into nyc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a63469076e
@@ -2601,17 +2601,9 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
/* appStillExists = */ false);
|
||||
}
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
// 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);
|
||||
rescanUpdatedPackagesLocked(ownerUserId, user.getLastAppScanTime(),
|
||||
/* forceRescan=*/ false);
|
||||
}
|
||||
} finally {
|
||||
logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
|
||||
@@ -2619,6 +2611,24 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
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(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(userId);
|
||||
}
|
||||
|
||||
private void handlePackageAdded(String packageName, @UserIdInt int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, 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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user