Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3107ff78 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Off-load unlocking users onto a worker thread

Bug 29645168

Change-Id: I50dce4f9227b2f30470ddd5799d8e2cdb90d4d79
parent c8c44e73
Loading
Loading
Loading
Loading
+51 −31
Original line number Diff line number Diff line
@@ -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();

@@ -537,15 +557,22 @@ public class ShortcutService extends IShortcutService.Stub {
        }
        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)));
    }

+11 −0
Original line number Diff line number Diff line
@@ -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);
+10 −7
Original line number Diff line number Diff line
@@ -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));
@@ -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();

@@ -4245,7 +4248,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        // Then send the broadcast, to only user-0.
        mService.mPackageMonitor.onReceive(getTestContext(),
                genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
        mService.handleUnlockUser(USER_10);
        mService.checkPackageChanges(USER_10);

        waitOnMainThread();

+5 −7
Original line number Diff line number Diff line
@@ -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"));
    }