Merge "Do not scan system apps unless after OTA" into nyc-mr1-dev
This commit is contained in:
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
@@ -125,6 +126,8 @@ class ShortcutUser {
|
||||
|
||||
private long mLastAppScanTime;
|
||||
|
||||
private String mLastAppScanOsFingerprint;
|
||||
|
||||
public ShortcutUser(ShortcutService service, int userId) {
|
||||
mService = service;
|
||||
mUserId = userId;
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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 + " ";
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user