Merge "Off-load unlocking users onto a worker thread"
This commit is contained in:
committed by
Android (Google) Code Review
commit
18d5ee3351
@@ -324,10 +324,30 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
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 @@ 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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -389,6 +389,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
|
||||
runOnHandler(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
void injectRunOnNewThread(Runnable r) {
|
||||
runOnHandler(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
void injectEnforceCallingPermission(String permission, String message) {
|
||||
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) {
|
||||
if (ENABLE_DUMP) {
|
||||
Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -156,11 +156,10 @@ public class ShortcutManagerTestUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<String> runCommand(Instrumentation instrumentation, String command) {
|
||||
private static List<String> runCommand(Instrumentation instrumentation, String command) {
|
||||
return runCommand(instrumentation, command, null);
|
||||
}
|
||||
|
||||
public static List<String> runCommand(Instrumentation instrumentation, String command,
|
||||
private static List<String> runCommand(Instrumentation instrumentation, String command,
|
||||
Predicate<List<String>> resultAsserter) {
|
||||
Log.d(TAG, "Running command: " + command);
|
||||
final List<String> result;
|
||||
@@ -176,11 +175,11 @@ public class ShortcutManagerTestUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void runCommandForNoOutput(Instrumentation instrumentation, String command) {
|
||||
private static void runCommandForNoOutput(Instrumentation instrumentation, String command) {
|
||||
runCommand(instrumentation, command, result -> result.size() == 0);
|
||||
}
|
||||
|
||||
public static List<String> runShortcutCommand(Instrumentation instrumentation, String command,
|
||||
private static List<String> runShortcutCommand(Instrumentation instrumentation, String command,
|
||||
Predicate<List<String>> resultAsserter) {
|
||||
return runCommand(instrumentation, "cmd shortcut " + command, resultAsserter);
|
||||
}
|
||||
@@ -205,8 +204,7 @@ public class ShortcutManagerTestUtils {
|
||||
}
|
||||
|
||||
public static void setDefaultLauncher(Instrumentation instrumentation, String component) {
|
||||
runCommand(instrumentation, "cmd package set-home-activity --user "
|
||||
+ instrumentation.getContext().getUserId() + " " + component,
|
||||
runCommand(instrumentation, "cmd package set-home-activity " + component,
|
||||
result -> result.contains("Success"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user