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

Commit b37f32cf authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Let IC#reportFullscreenMode() honor IC#getHandler()

This CL fixes a regression that

  InputConnection#reportFullscreenMode()

is always called back on the main thread rather than its associated
thread.  In most of cases those two threads are the same hence there
is no semantic problem, threads are the same, but for some special
cases, e.g. when apps explicitly override

  InputConnection#getHandler(),

our thread affinity contract can be violated.

This regression was accidentally introduced in Android O time frame
while attempting to make the system more robust at Bug 28406127 [1].

Although we have never received any actual issue report from app
developers so far, this is still worth fixing.

 [1]: If23e7c7c265ab3dfb48c2fb6fdb361b17d22c594
      2bc66171

Bug: 28406127
Fix: 193588937
Test: atest CtsInputMethodTestCases:InputConnectionHandlerTest
Change-Id: Id3ac21c11d6b062bb66719109376ff642309b8ff
parent e43df490
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -843,9 +843,14 @@ public interface InputConnection {
    /**
     * Called back when the connected IME switches between fullscreen and normal modes.
     *
     * <p>Note: On {@link android.os.Build.VERSION_CODES#O} and later devices, input methods are no
     * longer allowed to directly call this method at any time. To signal this event in the target
     * application, input methods should always call
     * <p><p><strong>Editor authors:</strong> There is a bug on
     * {@link android.os.Build.VERSION_CODES#O} and later devices that this method is called back
     * on the main thread even when {@link #getHandler()} is overridden.  This bug is fixed in
     * {@link android.os.Build.VERSION_CODES#TIRAMISU}.</p>
     *
     * <p><p><strong>IME authors:</strong> On {@link android.os.Build.VERSION_CODES#O} and later
     * devices, input methods are no longer allowed to directly call this method at any time.
     * To signal this event in the target application, input methods should always call
     * {@link InputMethodService#updateFullscreenMode()} instead. This approach should work on API
     * {@link android.os.Build.VERSION_CODES#N_MR1} and prior devices.</p>
     *
+3 −3
Original line number Diff line number Diff line
@@ -950,15 +950,15 @@ public final class InputMethodManager {
                }
                case MSG_REPORT_FULLSCREEN_MODE: {
                    final boolean fullscreen = msg.arg1 != 0;
                    InputConnection ic = null;
                    RemoteInputConnectionImpl ic = null;
                    synchronized (mH) {
                        if (mFullscreenMode != fullscreen && mServedInputConnection != null) {
                            ic = mServedInputConnection.getInputConnection();
                            ic = mServedInputConnection;
                            mFullscreenMode = fullscreen;
                        }
                    }
                    if (ic != null) {
                        ic.reportFullscreenMode(fullscreen);
                        ic.dispatchReportFullscreenMode(fullscreen);
                    }
                    return;
                }
+17 −0
Original line number Diff line number Diff line
@@ -169,6 +169,23 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
        }
    }

    /**
     * Invoke {@link InputConnection#reportFullscreenMode(boolean)} or schedule it on the target
     * thread associated with {@link InputConnection#getHandler()}.
     *
     * @param enabled the parameter to be passed to
     *                {@link InputConnection#reportFullscreenMode(boolean)}.
     */
    public void dispatchReportFullscreenMode(boolean enabled) {
        dispatch(() -> {
            final InputConnection ic = getInputConnection();
            if (ic == null || !isActive()) {
                return;
            }
            ic.reportFullscreenMode(enabled);
        });
    }

    @Override
    public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
        dispatch(() -> {