Off-load unlocking users onto a worker thread

Bug 29645168

(cherry picked from commit 3107ff7845)

Change-Id: I3f8e768f6afeb6386a08ba9ac48e0e206395da2b
This commit is contained in:
Makoto Onuki
2016-08-19 11:39:29 -07:00
parent eab8a12845
commit 085a05cd86
3 changed files with 70 additions and 36 deletions

View File

@@ -324,10 +324,30 @@ public class ShortcutService extends IShortcutService.Stub {
int CHECK_LAUNCHER_ACTIVITY = 12; int CHECK_LAUNCHER_ACTIVITY = 12;
int IS_ACTIVITY_ENABLED = 13; int IS_ACTIVITY_ENABLED = 13;
int PACKAGE_UPDATE_CHECK = 14; 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(); final Object mStatLock = new Object();
@GuardedBy("mStatLock") @GuardedBy("mStatLock")
@@ -533,19 +553,26 @@ public class ShortcutService extends IShortcutService.Stub {
/** lifecycle event */ /** lifecycle event */
void handleUnlockUser(int userId) { void handleUnlockUser(int userId) {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "handleUnlockUser: user=" + userId); Slog.d(TAG, "handleUnlockUser: user=" + userId);
} }
synchronized (mLock) { synchronized (mLock) {
mUnlockedUsers.put(userId, true); 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 */ /** lifecycle event */
@@ -1110,6 +1137,9 @@ public class ShortcutService extends IShortcutService.Stub {
userPackages = new ShortcutUser(this, userId); userPackages = new ShortcutUser(this, userId);
} }
mUsers.put(userId, userPackages); mUsers.put(userId, userPackages);
// Also when a user's data is first accessed, scan all packages.
checkPackageChanges(userId);
} }
return userPackages; return userPackages;
} }
@@ -1468,6 +1498,10 @@ public class ShortcutService extends IShortcutService.Stub {
mHandler.post(r); mHandler.post(r);
} }
void injectRunOnNewThread(Runnable r) {
new Thread(r).start();
}
/** /**
* @throws IllegalArgumentException if {@code numShortcuts} is bigger than * @throws IllegalArgumentException if {@code numShortcuts} is bigger than
* {@link #getMaxActivityShortcuts()}. * {@link #getMaxActivityShortcuts()}.
@@ -3218,23 +3252,9 @@ public class ShortcutService extends IShortcutService.Stub {
pw.println(" Stats:"); pw.println(" Stats:");
synchronized (mStatLock) { synchronized (mStatLock) {
final String p = " "; for (int i = 0; i < Stats.COUNT; i++) {
dumpStatLS(pw, p, Stats.GET_DEFAULT_HOME, "getHomeActivities()"); dumpStatLS(pw, " ", i);
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");
} }
pw.println(); pw.println();
@@ -3277,12 +3297,12 @@ public class ShortcutService extends IShortcutService.Stub {
return tobj.format("%Y-%m-%d %H:%M:%S"); 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); pw.print(prefix);
final int count = mCountStats[statId]; final int count = mCountStats[statId];
final long dur = mDurationStats[statId]; final long dur = mDurationStats[statId];
pw.println(String.format("%s: count=%d, total=%dms, avg=%.1fms", 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))); (count == 0 ? 0 : ((double) dur) / count)));
} }

View File

@@ -389,6 +389,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
runOnHandler(r); runOnHandler(r);
} }
@Override
void injectRunOnNewThread(Runnable r) {
runOnHandler(r);
}
@Override @Override
void injectEnforceCallingPermission(String permission, String message) { void injectEnforceCallingPermission(String permission, String message) {
if (!mCallerPermissions.contains(permission)) { if (!mCallerPermissions.contains(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) { protected void uninstallPackage(int userId, String packageName) {
if (ENABLE_DUMP) { if (ENABLE_DUMP) {
Log.v(TAG, "Unnstall package " + packageName + " / " + userId); Log.v(TAG, "Unnstall package " + packageName + " / " + userId);

View File

@@ -3945,11 +3945,11 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mInjectedPackages.remove(CALLING_PACKAGE_1); mInjectedPackages.remove(CALLING_PACKAGE_1);
mInjectedPackages.remove(CALLING_PACKAGE_3); mInjectedPackages.remove(CALLING_PACKAGE_3);
mService.handleUnlockUser(USER_0); mService.checkPackageChanges(USER_0);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "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)); assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "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)); assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, 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)); assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "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); updatePackageVersion(CALLING_PACKAGE_1, 1);
// Then send the broadcast, to only user-0. // Then send the broadcast, to only user-0.
mService.mPackageMonitor.onReceive(getTestContext(), mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0)); genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
waitOnMainThread(); waitOnMainThread();
@@ -4186,10 +4186,13 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mInjectedCurrentTimeMillis = START_TIME + 200; mInjectedCurrentTimeMillis = START_TIME + 200;
mRunningUsers.put(USER_10, true); mRunningUsers.put(USER_10, true);
mUnlockedUsers.put(USER_10, true);
reset(c0); reset(c0);
reset(c10); reset(c10);
setPackageLastUpdateTime(CALLING_PACKAGE_1, mInjectedCurrentTimeMillis);
mService.handleUnlockUser(USER_10); mService.handleUnlockUser(USER_10);
mService.checkPackageChanges(USER_10);
waitOnMainThread(); waitOnMainThread();
@@ -4221,7 +4224,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Then send the broadcast, to only user-0. // Then send the broadcast, to only user-0.
mService.mPackageMonitor.onReceive(getTestContext(), mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0)); genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
mService.handleUnlockUser(USER_10); mService.checkPackageChanges(USER_10);
waitOnMainThread(); waitOnMainThread();
@@ -4243,9 +4246,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_3, 100); updatePackageVersion(CALLING_PACKAGE_3, 100);
// Then send the broadcast, to only user-0. // Then send the broadcast, to only user-0.
mService.mPackageMonitor.onReceive(getTestContext(), mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0)); genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
mService.handleUnlockUser(USER_10); mService.checkPackageChanges(USER_10);
waitOnMainThread(); waitOnMainThread();