diff options
3 files changed, 72 insertions, 38 deletions
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index c1fc7f114c67..b80775b690e2 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -324,9 +324,29 @@ public class ShortcutService extends IShortcutService.Stub { int CHECK_LAUNCHER_ACTIVITY = 12; int IS_ACTIVITY_ENABLED = 13; int PACKAGE_UPDATE_CHECK = 14; - - int COUNT = PACKAGE_UPDATE_CHECK + 1; - } + int ASYNC_PRELOAD_USER_DELAY = 15; + + int COUNT = ASYNC_PRELOAD_USER_DELAY + 1; + } + + private static final String[] STAT_LABELS = { + "getHomeActivities()", + "Launcher permission check", + "getPackageInfo()", + "getPackageInfo(SIG)", + "getApplicationInfo", + "cleanupDanglingBitmaps", + "getActivity+metadata", + "getInstalledPackages", + "checkPackageChanges", + "getApplicationResources", + "resourceNameLookup", + "getLauncherActivity", + "checkLauncherActivity", + "isActivityEnabled", + "packageUpdateCheck", + "asyncPreloadUserDelay" + }; final Object mStatLock = new Object(); @@ -533,19 +553,26 @@ public class ShortcutService extends IShortcutService.Stub { /** lifecycle event */ void handleUnlockUser(int userId) { if (DEBUG) { - Slog.d(TAG, "handleUnlockUser: user=" + userId); + Slog.d(TAG, "handleUnlockUser: user=" + userId); } synchronized (mLock) { mUnlockedUsers.put(userId, true); - - // Preload the user's shortcuts. - // Also see if the locale has changed. - // Note as of nyc, the locale is per-user, so the locale shouldn't change - // when the user is locked. However due to b/30119489 it still happens. - getUserShortcutsLocked(userId).detectLocaleChange(); - - checkPackageChanges(userId); } + + // Preload the user data. + // Note, we don't use mHandler here but instead just start a new thread. + // This is because mHandler (which uses com.android.internal.os.BackgroundThread) is very + // busy at this point and this could take hundreds of milliseconds, which would be too + // late since the launcher would already have started. + // So we just create a new thread. This code runs rarely, so we don't use a thread pool + // or anything. + final long start = injectElapsedRealtime(); + injectRunOnNewThread(() -> { + synchronized (mLock) { + logDurationStat(Stats.ASYNC_PRELOAD_USER_DELAY, start); + getUserShortcutsLocked(userId); + } + }); } /** lifecycle event */ @@ -1110,6 +1137,9 @@ public class ShortcutService extends IShortcutService.Stub { userPackages = new ShortcutUser(this, userId); } mUsers.put(userId, userPackages); + + // Also when a user's data is first accessed, scan all packages. + checkPackageChanges(userId); } return userPackages; } @@ -1468,6 +1498,10 @@ public class ShortcutService extends IShortcutService.Stub { mHandler.post(r); } + void injectRunOnNewThread(Runnable r) { + new Thread(r).start(); + } + /** * @throws IllegalArgumentException if {@code numShortcuts} is bigger than * {@link #getMaxActivityShortcuts()}. @@ -3218,23 +3252,9 @@ public class ShortcutService extends IShortcutService.Stub { pw.println(" Stats:"); synchronized (mStatLock) { - final String p = " "; - dumpStatLS(pw, p, Stats.GET_DEFAULT_HOME, "getHomeActivities()"); - dumpStatLS(pw, p, Stats.LAUNCHER_PERMISSION_CHECK, "Launcher permission check"); - - dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO, "getPackageInfo()"); - dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO_WITH_SIG, "getPackageInfo(SIG)"); - dumpStatLS(pw, p, Stats.GET_APPLICATION_INFO, "getApplicationInfo"); - dumpStatLS(pw, p, Stats.CLEANUP_DANGLING_BITMAPS, "cleanupDanglingBitmaps"); - dumpStatLS(pw, p, Stats.GET_ACTIVITY_WITH_METADATA, "getActivity+metadata"); - dumpStatLS(pw, p, Stats.GET_INSTALLED_PACKAGES, "getInstalledPackages"); - dumpStatLS(pw, p, Stats.CHECK_PACKAGE_CHANGES, "checkPackageChanges"); - dumpStatLS(pw, p, Stats.GET_APPLICATION_RESOURCES, "getApplicationResources"); - dumpStatLS(pw, p, Stats.RESOURCE_NAME_LOOKUP, "resourceNameLookup"); - dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity"); - dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity"); - dumpStatLS(pw, p, Stats.IS_ACTIVITY_ENABLED, "isActivityEnabled"); - dumpStatLS(pw, p, Stats.PACKAGE_UPDATE_CHECK, "packageUpdateCheck"); + for (int i = 0; i < Stats.COUNT; i++) { + dumpStatLS(pw, " ", i); + } } pw.println(); @@ -3277,12 +3297,12 @@ public class ShortcutService extends IShortcutService.Stub { return tobj.format("%Y-%m-%d %H:%M:%S"); } - private void dumpStatLS(PrintWriter pw, String prefix, int statId, String label) { + private void dumpStatLS(PrintWriter pw, String prefix, int statId) { pw.print(prefix); final int count = mCountStats[statId]; final long dur = mDurationStats[statId]; pw.println(String.format("%s: count=%d, total=%dms, avg=%.1fms", - label, count, dur, + STAT_LABELS[statId], count, dur, (count == 0 ? 0 : ((double) dur) / count))); } 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 1c7a138468cf..e96e97bcaa02 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -390,6 +390,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } @Override + void injectRunOnNewThread(Runnable r) { + runOnHandler(r); + } + + @Override void injectEnforceCallingPermission(String permission, String message) { if (!mCallerPermissions.contains(permission)) { throw new SecurityException("Missing permission: " + permission); @@ -921,6 +926,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { }); } + protected void setPackageLastUpdateTime(String packageName, long value) { + updatePackageInfo(packageName, pi -> { + pi.lastUpdateTime = value; + }); + } + protected void uninstallPackage(int userId, String packageName) { if (ENABLE_DUMP) { Log.v(TAG, "Unnstall package " + packageName + " / " + userId); diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 253334eec9cf..ed4e391a6273 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -3945,11 +3945,11 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { mInjectedPackages.remove(CALLING_PACKAGE_1); mInjectedPackages.remove(CALLING_PACKAGE_3); - mService.handleUnlockUser(USER_0); + mService.checkPackageChanges(USER_0); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); - assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); + assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0)); // --------------- assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10)); @@ -3961,7 +3961,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10)); assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10)); - mService.handleUnlockUser(USER_10); + mService.checkPackageChanges(USER_10); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0)); @@ -4154,7 +4154,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { updatePackageVersion(CALLING_PACKAGE_1, 1); // Then send the broadcast, to only user-0. - mService.mPackageMonitor.onReceive(getTestContext(), + mService.mPackageMonitor.onReceive(getTestContext(), genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0)); waitOnMainThread(); @@ -4186,10 +4186,13 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { mInjectedCurrentTimeMillis = START_TIME + 200; mRunningUsers.put(USER_10, true); + mUnlockedUsers.put(USER_10, true); reset(c0); reset(c10); + setPackageLastUpdateTime(CALLING_PACKAGE_1, mInjectedCurrentTimeMillis); mService.handleUnlockUser(USER_10); + mService.checkPackageChanges(USER_10); waitOnMainThread(); @@ -4221,7 +4224,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { // Then send the broadcast, to only user-0. mService.mPackageMonitor.onReceive(getTestContext(), genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0)); - mService.handleUnlockUser(USER_10); + mService.checkPackageChanges(USER_10); waitOnMainThread(); @@ -4243,9 +4246,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { updatePackageVersion(CALLING_PACKAGE_3, 100); // Then send the broadcast, to only user-0. - mService.mPackageMonitor.onReceive(getTestContext(), + mService.mPackageMonitor.onReceive(getTestContext(), genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0)); - mService.handleUnlockUser(USER_10); + mService.checkPackageChanges(USER_10); waitOnMainThread(); |