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

Commit bb0e2f75 authored by Tarandeep Singh's avatar Tarandeep Singh
Browse files

Pipe windowToken of window requesting IME

It takes time from when IME is requested to the time when IME is ready
to be shown. When its ready to be shown, we need to make sure that
window that requested IME is still the IME target in DisplayContent. The
only realistic way of knowing originating window is passing windowToken
from IMM API.

Bug: 111084606
Test: CtsInputMethodTestCases

Change-Id: Ia49e23dd077d264a58d28a7b8acffde54b7db187
parent 1dc6ec5b
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -221,7 +221,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
                inputMethod.revokeSession((InputMethodSession)msg.obj);
                return;
            case DO_SHOW_SOFT_INPUT:
                inputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj);
                SomeArgs args = (SomeArgs)msg.obj;
                inputMethod.showSoftInputWithToken(
                        msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1);
                return;
            case DO_HIDE_SOFT_INPUT:
                inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
@@ -230,10 +232,11 @@ class IInputMethodWrapper extends IInputMethod.Stub
                inputMethod.changeInputMethodSubtype((InputMethodSubtype)msg.obj);
                return;
            case DO_CREATE_INLINE_SUGGESTIONS_REQUEST:
                SomeArgs args = (SomeArgs) msg.obj;
                args = (SomeArgs) msg.obj;
                inputMethod.onCreateInlineSuggestionsRequest((ComponentName) args.arg1,
                        (AutofillId) args.arg2, (IInlineSuggestionsRequestCallback) args.arg3);
                return;

        }
        Log.w(TAG, "Unhandled message code: " + msg.what);
    }
@@ -371,9 +374,9 @@ class IInputMethodWrapper extends IInputMethod.Stub

    @BinderThread
    @Override
    public void showSoftInput(int flags, ResultReceiver resultReceiver) {
        mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_SHOW_SOFT_INPUT,
                flags, resultReceiver));
    public void showSoftInput(IBinder showInputToken, int flags, ResultReceiver resultReceiver) {
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_SHOW_SOFT_INPUT,
                flags, showInputToken, resultReceiver));
    }

    @BinderThread
+47 −1
Original line number Diff line number Diff line
@@ -46,11 +46,13 @@ import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.Region;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
@@ -450,6 +452,16 @@ public class InputMethodService extends AbstractInputMethodService {
    @Nullable
    private InlineSuggestionsRequestInfo mInlineSuggestionsRequestInfo = null;

    /**
     * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
     * The original app window token is passed from client app window.
     * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique dummy
     * token to identify this window.
     * This dummy token is only valid for a single call to {@link InputMethodImpl#showSoftInput},
     * after which it is set null until next call.
     */
    private IBinder mCurShowInputToken;

    private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);

    final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
@@ -491,6 +503,9 @@ public class InputMethodService extends AbstractInputMethodService {
     * all of the standard behavior for an input method.
     */
    public class InputMethodImpl extends AbstractInputMethodImpl {

        private boolean mSystemCallingShowSoftInput;

        /**
         * {@inheritDoc}
         * @hide
@@ -657,6 +672,21 @@ public class InputMethodService extends AbstractInputMethodService {
            }
        }

        /**
         * {@inheritDoc}
         * @hide
         */
        @MainThread
        @Override
        public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
                IBinder showInputToken) {
            mSystemCallingShowSoftInput = true;
            mCurShowInputToken = showInputToken;
            showSoftInput(flags, resultReceiver);
            mCurShowInputToken = null;
            mSystemCallingShowSoftInput = false;
        }

        /**
         * {@inheritDoc}
         */
@@ -664,6 +694,13 @@ public class InputMethodService extends AbstractInputMethodService {
        @Override
        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
            if (DEBUG) Log.v(TAG, "showSoftInput()");
            // TODO(b/148086656): Disallow IME developers from calling InputMethodImpl methods.
            if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
                    && !mSystemCallingShowSoftInput) {
                Log.e(TAG," IME shouldn't call showSoftInput on itself."
                        + " Use requestShowSelf(int) itself");
                return;
            }
            final boolean wasVisible = mIsPreRendered
                    ? mDecorViewVisible && mWindowVisible : isInputViewShown();
            if (dispatchOnShowInputRequested(flags, false)) {
@@ -698,6 +735,15 @@ public class InputMethodService extends AbstractInputMethodService {
        public void changeInputMethodSubtype(InputMethodSubtype subtype) {
            dispatchOnCurrentInputMethodSubtypeChanged(subtype);
        }

        /**
         * {@inheritDoc}
         * @hide
         */
        @Override
        public void setCurrentShowInputToken(IBinder showInputToken) {
            mCurShowInputToken = showInputToken;
        }
    }

    // TODO(b/137800469): Add detailed docs explaining the inline suggestions process.
@@ -2181,7 +2227,7 @@ public class InputMethodService extends AbstractInputMethodService {
        if (!isVisibilityAppliedUsingInsetsConsumer()) {
            return;
        }
        mPrivOps.applyImeVisibility(setVisible);
        mPrivOps.applyImeVisibility(mCurShowInputToken, setVisible);
    }

    private boolean isVisibilityAppliedUsingInsetsConsumer() {
+34 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Log;
import android.view.View;
import android.view.autofill.AutofillId;

import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
@@ -299,6 +300,29 @@ public interface InputMethod {
     */
    public static final int SHOW_FORCED = 0x00002;

    /**
     * Request that any soft input part of the input method be shown to the user.
     *
     * @param flags Provides additional information about the show request.
     * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
     * @param resultReceiver The client requesting the show may wish to
     * be told the impact of their request, which should be supplied here.
     * The result code should be
     * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
     * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
     * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
     * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
     * @param showInputToken an opaque {@link android.os.Binder} token to identify which API call
     *        of {@link InputMethodManager#showSoftInput(View, int)} is associated with
     *        this callback.
     * @hide
     */
    @MainThread
    default public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
            IBinder showInputToken) {
        showSoftInput(flags, resultReceiver);
    }

    /**
     * Request that any soft input part of the input method be shown to the user.
     * 
@@ -336,4 +360,12 @@ public interface InputMethod {
     */
    @MainThread
    public void changeInputMethodSubtype(InputMethodSubtype subtype);

    /**
     * Update token of the client window requesting {@link #showSoftInput(int, ResultReceiver)}
     * @param showInputToken dummy app window token for window requesting
     *        {@link InputMethodManager#showSoftInput(View, int)}
     * @hide
     */
    public void setCurrentShowInputToken(IBinder showInputToken);
}
+4 −2
Original line number Diff line number Diff line
@@ -1617,7 +1617,8 @@ public final class InputMethodManager {
            }

            try {
                return mService.showSoftInput(mClient, flags, resultReceiver);
                return mService.showSoftInput(
                        mClient, view.getWindowToken(), flags, resultReceiver);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -1639,7 +1640,8 @@ public final class InputMethodManager {
            Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
                    + "soon. If you are using android.support.v7.widget.SearchView, please update "
                    + "to version 26.0 or newer version.");
            mService.showSoftInput(mClient, flags, resultReceiver);
            mService.showSoftInput(
                    mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -41,5 +41,5 @@ interface IInputMethodPrivilegedOperations {
    boolean shouldOfferSwitchingToNextInputMethod();
    void notifyUserAction();
    void reportPreRendered(in EditorInfo info);
    void applyImeVisibility(boolean setVisible);
    void applyImeVisibility(IBinder showInputToken, boolean setVisible);
}
Loading