OSDN Git Service

ShortcutManager: Optimize package scanning
authorMakoto Onuki <omakoto@google.com>
Wed, 1 Jun 2016 20:55:54 +0000 (13:55 -0700)
committerMakoto Onuki <omakoto@google.com>
Tue, 7 Jun 2016 17:32:19 +0000 (10:32 -0700)
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

services/core/java/com/android/server/pm/ShortcutService.java
services/core/java/com/android/server/pm/ShortcutUser.java
services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java

index 7835231..3565154 100644 (file)
@@ -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<ApplicationInfo> injectInstalledApplications(@UserIdInt int userId) {
+    List<PackageInfo> injectInstalledPackages(@UserIdInt int userId) {
         final long start = injectElapsedRealtime();
         final long token = injectClearCallingIdentity();
         try {
-            final ParceledListSlice<ApplicationInfo> parceledList =
-                    mIPackageManager.getInstalledApplications(PACKAGE_MATCH_FLAGS, userId);
+            final ParceledListSlice<PackageInfo> 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<ApplicationInfo> callback) {
-        final List<ApplicationInfo> list = injectInstalledApplications(userId);
+        if (DEBUG) {
+            Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime);
+        }
+        final List<PackageInfo> 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");
             }
 
index 840c3df..f8ee325 100644 (file)
@@ -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 + "  ";
index ed53b77..d33047b 100644 (file)
@@ -302,8 +302,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
         }
 
         @Override
-        List<ApplicationInfo> injectInstalledApplications(@UserIdInt int userId) {
-            return getInstalledApplications(userId);
+        List<PackageInfo> 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<PackageInfo> list) {
+        if (pi != null) {
+            list.add(pi);
+        }
+    }
+
+    private List<PackageInfo> getInstalledPackages(int userId) {
+        final ArrayList<PackageInfo> 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<ComponentName, Integer> map = mActivityMetadataResId.get(packageName);