From 6dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Wed, 1 Jun 2016 13:55:54 -0700 Subject: [PATCH] ShortcutManager: Optimize package scanning SM needs to check all packages when a user is unlocked in case any apps have been upgraded while the user was not running, in which case it'll publish the manifest shortcuts. Currently it actually scans all apps' manifests. This CL optimizes it by remembering the last scan time (for each user) and checks only the packages that have been updated since then. Bug 29069154 Change-Id: Id10b6be8915fe7c1e26daccde7951ddbd01ea452 --- .../com/android/server/pm/ShortcutService.java | 38 +++++++++++++++------- .../java/com/android/server/pm/ShortcutUser.java | 22 +++++++++++++ .../android/server/pm/BaseShortcutManagerTest.java | 25 ++++++++++++-- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 78352319e156..356515442386 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -113,6 +113,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import java.util.function.Predicate; @@ -316,7 +317,7 @@ public class ShortcutService extends IShortcutService.Stub { int LAUNCHER_PERMISSION_CHECK = 4; int CLEANUP_DANGLING_BITMAPS = 5; int GET_ACTIVITIES_WITH_METADATA = 6; - int GET_INSTALLED_APPLICATIONS = 7; + int GET_INSTALLED_PACKAGES = 7; int CHECK_PACKAGE_CHANGES = 8; int COUNT = CHECK_PACKAGE_CHANGES + 1; @@ -2282,11 +2283,17 @@ public class ShortcutService extends IShortcutService.Stub { cleanUpPackageLocked(pu.packageName, ownerUserId, pu.userId); } } + final long now = injectCurrentTimeMillis(); // Then for each installed app, publish manifest shortcuts when needed. - forInstalledApplications(ownerUserId, ai -> { + forUpdatedPackages(ownerUserId, user.getLastAppScanTime(), ai -> { user.handlePackageAddedOrUpdated(ai.packageName); }); + + // 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); } } finally { logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start); @@ -2424,12 +2431,12 @@ public class ShortcutService extends IShortcutService.Stub { @Nullable @VisibleForTesting - List injectInstalledApplications(@UserIdInt int userId) { + List injectInstalledPackages(@UserIdInt int userId) { final long start = injectElapsedRealtime(); final long token = injectClearCallingIdentity(); try { - final ParceledListSlice parceledList = - mIPackageManager.getInstalledApplications(PACKAGE_MATCH_FLAGS, userId); + final ParceledListSlice parceledList = + mIPackageManager.getInstalledPackages(PACKAGE_MATCH_FLAGS, userId); if (parceledList == null) { return Collections.emptyList(); } @@ -2441,18 +2448,25 @@ public class ShortcutService extends IShortcutService.Stub { } finally { injectRestoreCallingIdentity(token); - logDurationStat(Stats.GET_INSTALLED_APPLICATIONS, start); + logDurationStat(Stats.GET_INSTALLED_PACKAGES, start); } } - private void forInstalledApplications(@UserIdInt int userId, + private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, Consumer callback) { - final List list = injectInstalledApplications(userId); + if (DEBUG) { + Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime); + } + final List list = injectInstalledPackages(userId); for (int i = list.size() - 1; i >= 0; i--) { - final ApplicationInfo ai = list.get(i); + final PackageInfo pi = list.get(i); - if ((ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { - callback.accept(ai); + if (((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0) + && (pi.lastUpdateTime >= lastScanTime)) { + if (DEBUG) { + Slog.d(TAG, "Found updated package " + pi.packageName); + } + callback.accept(pi.applicationInfo); } } } @@ -2612,7 +2626,7 @@ public class ShortcutService extends IShortcutService.Stub { dumpStatLS(pw, p, Stats.GET_APPLICATION_INFO, "getApplicationInfo"); dumpStatLS(pw, p, Stats.CLEANUP_DANGLING_BITMAPS, "cleanupDanglingBitmaps"); dumpStatLS(pw, p, Stats.GET_ACTIVITIES_WITH_METADATA, "getActivities+metadata"); - dumpStatLS(pw, p, Stats.GET_INSTALLED_APPLICATIONS, "getInstalledApplications"); + dumpStatLS(pw, p, Stats.GET_INSTALLED_PACKAGES, "getInstalledPackages"); dumpStatLS(pw, p, Stats.CHECK_PACKAGE_CHANGES, "checkPackageChanges"); } diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java index 840c3df97cc3..f8ee3251055b 100644 --- a/services/core/java/com/android/server/pm/ShortcutUser.java +++ b/services/core/java/com/android/server/pm/ShortcutUser.java @@ -52,6 +52,7 @@ class ShortcutUser { private static final String ATTR_VALUE = "value"; private static final String ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER = "locale-seq-no"; + private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time"; static final class PackageWithUser { final int userId; @@ -107,6 +108,8 @@ class ShortcutUser { private long mKnownLocaleChangeSequenceNumber; + private long mLastAppScanTime; + public ShortcutUser(ShortcutService service, int userId) { mService = service; mUserId = userId; @@ -116,6 +119,14 @@ class ShortcutUser { return mUserId; } + public long getLastAppScanTime() { + return mLastAppScanTime; + } + + public void setLastAppScanTime(long lastAppScanTime) { + mLastAppScanTime = lastAppScanTime; + } + // We don't expose this directly to non-test code because only ShortcutUser should add to/ // remove from it. @VisibleForTesting @@ -258,6 +269,8 @@ class ShortcutUser { ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER, mKnownLocaleChangeSequenceNumber); + ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME, + mLastAppScanTime); ShortcutService.writeTagValue(out, TAG_LAUNCHER, mDefaultLauncherComponent); @@ -299,6 +312,13 @@ class ShortcutUser { ret.mKnownLocaleChangeSequenceNumber = ShortcutService.parseLongAttribute(parser, ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER); + // If lastAppScanTime is in the future, that means the clock went backwards. + // Just scan all apps again. + final long lastAppScanTime = ShortcutService.parseLongAttribute(parser, + ATTR_LAST_APP_SCAN_TIME); + final long currentTime = s.injectCurrentTimeMillis(); + ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0; + final int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT @@ -361,6 +381,8 @@ class ShortcutUser { pw.print(mUserId); pw.print(" Known locale seq#: "); pw.print(mKnownLocaleChangeSequenceNumber); + pw.print(" Last app scan: "); + pw.print(mLastAppScanTime); pw.println(); prefix += prefix + " "; diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index ed53b7782e46..d33047b68757 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -302,8 +302,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } @Override - List injectInstalledApplications(@UserIdInt int userId) { - return getInstalledApplications(userId); + List injectInstalledPackages(@UserIdInt int userId) { + return getInstalledPackages(userId); } @Override @@ -793,6 +793,27 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { return ret; } + private void addPackageInfo(PackageInfo pi, List list) { + if (pi != null) { + list.add(pi); + } + } + + private List getInstalledPackages(int userId) { + final ArrayList ret = new ArrayList<>(); + + addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret); + addPackageInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret); + + return ret; + } + protected void addManifestShortcutResource(ComponentName activity, int resId) { final String packageName = activity.getPackageName(); LinkedHashMap map = mActivityMetadataResId.get(packageName); -- 2.11.0