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

Commit 2aed6844 authored by Taran Singh's avatar Taran Singh Committed by Adrian Roos
Browse files

InputMethodManager: invoke ResultReceiver when returning true

After the introduction of the ZeroJankProxy [1], we unconditionally
return true from showSoftInput and hideSoftInput, indicating that we
accepted the request.

If the request then later fails, we need to report that to the result
receiver, since some apps and tests currently assume that the result
receiver will be invoked when they receive a true from the corresponding
call.

[1]: I37fd585eeccab7c3b18fb509b3607c56d800c306

Bug: 327751155
Bug: 293640003
Test: blaze test third_party/java_src/android_app/bugle/tests/instrumentation/javatests/com/google/android/apps/messaging/arigato/ui/conversation/rcs:RcsSendMultipleTest_generic_phone_master_x86_64_fullboot_en-US

Change-Id: Ie2f262128eb32db5a7922373fdfaebd2945ea36a
parent 5878e860
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -1248,7 +1248,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
            mService.publishLocalService();
            IInputMethodManager.Stub service;
            if (Flags.useZeroJankProxy()) {
                service = new ZeroJankProxy(mService.mHandler::post, mService);
                service =
                        new ZeroJankProxy(
                                mService.mHandler::post,
                                mService,
                                () -> {
                                    synchronized (ImfLock.class) {
                                        return mService.isInputShown();
                                    }
                                });
            } else {
                service = mService;
            }
+32 −6
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.util.ExceptionUtils;
import android.util.Slog;
import android.view.WindowManager;
import android.view.inputmethod.CursorAnchorInfo;
@@ -77,6 +76,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.BooleanSupplier;

/**
 * A proxy that processes all {@link IInputMethodManager} calls asynchronously.
@@ -86,10 +86,12 @@ public class ZeroJankProxy extends IInputMethodManager.Stub {

    private final IInputMethodManager mInner;
    private final Executor mExecutor;
    private final BooleanSupplier mIsInputShown;

    ZeroJankProxy(Executor executor, IInputMethodManager inner) {
    ZeroJankProxy(Executor executor, IInputMethodManager inner, BooleanSupplier isInputShown) {
        mInner = inner;
        mExecutor = executor;
        mIsInputShown = isInputShown;
    }

    private void offload(ThrowingRunnable r) {
@@ -163,8 +165,19 @@ public class ZeroJankProxy extends IInputMethodManager.Stub {
            int lastClickTooType, ResultReceiver resultReceiver,
            @SoftInputShowHideReason int reason)
            throws RemoteException {
        offload(() -> mInner.showSoftInput(client, windowToken, statsToken, flags, lastClickTooType,
                resultReceiver, reason));
        offload(
                () -> {
                    if (!mInner.showSoftInput(
                            client,
                            windowToken,
                            statsToken,
                            flags,
                            lastClickTooType,
                            resultReceiver,
                            reason)) {
                        sendResultReceiverFailure(resultReceiver);
                    }
                });
        return true;
    }

@@ -173,11 +186,24 @@ public class ZeroJankProxy extends IInputMethodManager.Stub {
            @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason)
            throws RemoteException {
        offload(() -> mInner.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver,
                reason));
        offload(
                () -> {
                    if (!mInner.hideSoftInput(
                            client, windowToken, statsToken, flags, resultReceiver, reason)) {
                        sendResultReceiverFailure(resultReceiver);
                    }
                });
        return true;
    }

    private void sendResultReceiverFailure(ResultReceiver resultReceiver) {
        resultReceiver.send(
                mIsInputShown.getAsBoolean()
                        ? InputMethodManager.RESULT_UNCHANGED_SHOWN
                        : InputMethodManager.RESULT_UNCHANGED_HIDDEN,
                null);
    }

    @Override
    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
    public void hideSoftInputFromServerForTest() throws RemoteException {