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

Commit 81a9a1ba authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Use a dedicated thread for IMMS.MyPackageMonitor

This is a follow up CL to my previous CL [1], which moved resource I/O
out of ImfLock to reduce the risk of ANRs.

Once thing that is still concerning is that

  MyPackageMonitor#onFinishPackageChangesInternal()

still gets called on a worker thread that is shared across multiple
operations in InputMethodManagerService, e.g.

 * HandwritingModeController as a UI event handler
 * event callbacks for ContentObserver
 * event forwarding used by ZeroJankProxy

Blocking above operations with resource I/O is also something we would
like to avoid. Thus this CL introduces a new worker thread dedicated
for MyPackageMonitor.

There should be no observable semantic change.

 [1]: I263cd49dd4d64b64136acc3dad469f83a862ce97
      db19711e

Bug: 340221861
Test: presubmit
Change-Id: Icc84fe9d0d3b5842b4d5ee51b12b0d3cd10a1d24
parent 9a1fb8f3
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -262,6 +262,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
    private static final String HANDLER_THREAD_NAME = "android.imms";
    private static final String PACKAGE_MONITOR_THREAD_NAME = "android.imms2";

    /**
     * When set, {@link #startInputUncheckedLocked} will return
@@ -285,6 +286,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    final Resources mRes;
    private final Handler mHandler;

    @NonNull
    private final Handler mPackageMonitorHandler;

    @MultiUserUnawareField
    @UserIdInt
    @GuardedBy("ImfLock.class")
@@ -1288,13 +1292,14 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
    }

    public InputMethodManagerService(Context context) {
        this(context, null, null);
        this(context, null, null, null);
    }

    @VisibleForTesting
    InputMethodManagerService(
            Context context,
            @Nullable ServiceThread serviceThreadForTesting,
            @Nullable ServiceThread packageMonitorThreadForTesting,
            @Nullable IntFunction<InputMethodBindingController> bindingControllerForTesting) {
        synchronized (ImfLock.class) {
            mContext = context;
@@ -1312,6 +1317,17 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                                    true /* allowIo */);
            thread.start();
            mHandler = Handler.createAsync(thread.getLooper(), this);
            {
                final ServiceThread packageMonitorThread =
                        packageMonitorThreadForTesting != null
                                ? packageMonitorThreadForTesting
                                : new ServiceThread(
                                        PACKAGE_MONITOR_THREAD_NAME,
                                        Process.THREAD_PRIORITY_FOREGROUND,
                                        true /* allowIo */);
                packageMonitorThread.start();
                mPackageMonitorHandler = Handler.createAsync(packageMonitorThread.getLooper());
            }
            SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler);
            mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
                    ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
@@ -1585,7 +1601,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                    }
                }, "Lazily initialize IMMS#mImeDrawsImeNavBarRes");

                mMyPackageMonitor.register(mContext, UserHandle.ALL, mHandler);
                mMyPackageMonitor.register(mContext, UserHandle.ALL, mPackageMonitorHandler);
                mSettingsObserver.registerContentObserverLocked(currentUserId);

                final IntentFilter broadcastFilterForAllUsers = new IntentFilter();
+14 −4
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ public class InputMethodManagerServiceTestBase {
    protected IInputMethodInvoker mMockInputMethodInvoker;
    protected InputMethodManagerService mInputMethodManagerService;
    protected ServiceThread mServiceThread;
    protected ServiceThread mPackageMonitorThread;
    protected boolean mIsLargeScreen;
    private InputManagerGlobal.TestSession mInputManagerGlobalSession;

@@ -222,11 +223,16 @@ public class InputMethodManagerServiceTestBase {

        mServiceThread =
                new ServiceThread(
                        "TestServiceThread",
                        Process.THREAD_PRIORITY_FOREGROUND, /* allowIo */
                        false);
                        "immstest1",
                        Process.THREAD_PRIORITY_FOREGROUND,
                        true /* allowIo */);
        mPackageMonitorThread =
                new ServiceThread(
                        "immstest2",
                        Process.THREAD_PRIORITY_FOREGROUND,
                        true /* allowIo */);
        mInputMethodManagerService = new InputMethodManagerService(mContext, mServiceThread,
                unusedUserId -> mMockInputMethodBindingController);
                mPackageMonitorThread, unusedUserId -> mMockInputMethodBindingController);
        spyOn(mInputMethodManagerService);

        // Start a InputMethodManagerService.Lifecycle to publish and manage the lifecycle of
@@ -259,6 +265,10 @@ public class InputMethodManagerServiceTestBase {
            mInputMethodManagerService.mInputMethodDeviceConfigs.destroy();
        }

        if (mPackageMonitorThread != null) {
            mPackageMonitorThread.quitSafely();
        }

        if (mServiceThread != null) {
            mServiceThread.quitSafely();
        }