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

This commit is contained in:
TreeHugger Robot
2016-08-09 23:22:40 +00:00
committed by Android (Google) Code Review
2 changed files with 167 additions and 25 deletions

View File

@@ -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);
}

View File

@@ -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() {