Merge "Off-load unlocking users onto a worker thread" into nyc-mr1-dev
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c1fc7f1..b80775b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -324,10 +324,30 @@
int CHECK_LAUNCHER_ACTIVITY = 12;
int IS_ACTIVITY_ENABLED = 13;
int PACKAGE_UPDATE_CHECK = 14;
+ int ASYNC_PRELOAD_USER_DELAY = 15;
- int COUNT = PACKAGE_UPDATE_CHECK + 1;
+ 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();
@GuardedBy("mStatLock")
@@ -533,19 +553,26 @@
/** 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 @@
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 @@
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 @@
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 @@
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 1c7a138..e96e97b 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 @@
}
@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 @@
});
}
+ 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 253334e..ed4e391 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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();