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

Commit 057b9150 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Zero jank IMMS 2/N" into main

parents 30fc8e6e be605eca
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ final class IInputMethodManagerGlobalInvoker {

    @Nullable
    private static volatile IImeTracker sTrackerServiceCache = null;
    private static int sCurStartInputSeq = 0;

    /**
     * @return {@code true} if {@link IInputMethodManager} is available.
@@ -327,6 +328,7 @@ final class IInputMethodManagerGlobalInvoker {
        }
    }

    // TODO(b/293640003): Remove method once Flags.useZeroJankProxy() is enabled.
    @AnyThread
    @NonNull
    @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
@@ -353,6 +355,41 @@ final class IInputMethodManagerGlobalInvoker {
        }
    }

    /**
     * Returns a sequence number for startInput.
     */
    @AnyThread
    @NonNull
    @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
    static int startInputOrWindowGainedFocusAsync(@StartInputReason int startInputReason,
            @NonNull IInputMethodClient client, @Nullable IBinder windowToken,
            @StartInputFlags int startInputFlags,
            @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode,
            @WindowManager.LayoutParams.Flags int windowFlags, @Nullable EditorInfo editorInfo,
            @Nullable IRemoteInputConnection remoteInputConnection,
            @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
            int unverifiedTargetSdkVersion, @UserIdInt int userId,
            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
        final IInputMethodManager service = getService();
        if (service == null) {
            return -1;
        }
        try {
            service.startInputOrWindowGainedFocusAsync(startInputReason, client, windowToken,
                    startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
                    remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
                    imeDispatcher, advanceAngGetStartInputSequenceNumber());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return sCurStartInputSeq;
    }

    private static int advanceAngGetStartInputSequenceNumber() {
        return ++sCurStartInputSeq;
    }


    @AnyThread
    static void showInputMethodPickerFromClient(@NonNull IInputMethodClient client,
            int auxiliarySubtypeMode) {
+125 −8
Original line number Diff line number Diff line
@@ -320,6 +320,22 @@ public final class InputMethodManager {
        }
    };

    /**
     * A runnable that reports {@link InputConnection} opened event for calls to
     * {@link IInputMethodManagerGlobalInvoker#startInputOrWindowGainedFocusAsync}.
     */
    private abstract static class ReportInputConnectionOpenedRunner implements Runnable {
        /**
         * Sequence number to track startInput requests to
         * {@link IInputMethodManagerGlobalInvoker#startInputOrWindowGainedFocusAsync}
         */
        int mSequenceNum;
        ReportInputConnectionOpenedRunner(int sequenceNum) {
            this.mSequenceNum = sequenceNum;
        }
    }
    private ReportInputConnectionOpenedRunner mReportInputConnectionOpenedRunner;

    /**
     * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
     * or indirectly relied on {@link #sInstance} via reflection or something like that.
@@ -691,6 +707,7 @@ public final class InputMethodManager {
    private static final int MSG_UNBIND_ACCESSIBILITY_SERVICE = 12;
    private static final int MSG_SET_INTERACTIVE = 13;
    private static final int MSG_ON_SHOW_REQUESTED = 31;
    private static final int MSG_START_INPUT_RESULT = 40;

    /**
     * Calling this will invalidate Local stylus handwriting availability Cache which
@@ -1071,6 +1088,60 @@ public final class InputMethodManager {
                    startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
                    return;
                }

                case MSG_START_INPUT_RESULT: {
                    final InputBindResult res = (InputBindResult) msg.obj;
                    final int startInputSeq = msg.arg1;
                    if (res == null) {
                        // IMMS logs .wtf already.
                        return;
                    }
                    if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
                    synchronized (mH) {
                        if (res.id != null) {
                            updateInputChannelLocked(res.channel);
                            mCurMethod = res.method; // for @UnsupportedAppUsage
                            mCurBindState = new BindState(res);
                            mAccessibilityInputMethodSession.clear();
                            if (res.accessibilitySessions != null) {
                                for (int i = 0; i < res.accessibilitySessions.size(); i++) {
                                    IAccessibilityInputMethodSessionInvoker wrapper =
                                            IAccessibilityInputMethodSessionInvoker.createOrNull(
                                                    res.accessibilitySessions.valueAt(i));
                                    if (wrapper != null) {
                                        mAccessibilityInputMethodSession.append(
                                                res.accessibilitySessions.keyAt(i), wrapper);
                                    }
                                }
                            }
                            mCurId = res.id; // for @UnsupportedAppUsage
                        } else if (res.channel != null && res.channel != mCurChannel) {
                            res.channel.dispose();
                        }
                        switch (res.result) {
                            case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
                                mRestartOnNextWindowFocus = true;
                                mServedView = null;
                                break;
                        }
                        if (mCompletions != null) {
                            if (isImeSessionAvailableLocked()) {
                                mCurBindState.mImeSession.displayCompletions(mCompletions);
                            }
                        }

                        if (res != null
                                && res.method != null
                                && mServedView != null
                                && mReportInputConnectionOpenedRunner != null
                                && mReportInputConnectionOpenedRunner.mSequenceNum
                                        == startInputSeq) {
                            mReportInputConnectionOpenedRunner.run();
                        }
                        mReportInputConnectionOpenedRunner = null;
                    }
                    return;
                }
                case MSG_UNBIND: {
                    final int sequence = msg.arg1;
                    @UnbindReason
@@ -1321,6 +1392,12 @@ public final class InputMethodManager {
            mH.obtainMessage(MSG_BIND, res).sendToTarget();
        }

        @Override
        public void onStartInputResult(InputBindResult res, int startInputSeq) {
            mH.obtainMessage(MSG_START_INPUT_RESULT, startInputSeq, -1 /* unused */, res)
                    .sendToTarget();
        }

        @Override
        public void onBindAccessibilityService(InputBindResult res, int id) {
            mH.obtainMessage(MSG_BIND_ACCESSIBILITY_SERVICE, id, 0, res).sendToTarget();
@@ -2010,6 +2087,7 @@ public final class InputMethodManager {
            mServedConnecting = false;
            clearConnectionLocked();
        }
        mReportInputConnectionOpenedRunner = null;
        // Clear the back callbacks held by the ime dispatcher to avoid memory leaks.
        mImeDispatcher.clear();
    }
@@ -3080,6 +3158,18 @@ public final class InputMethodManager {
            final int targetUserId = editorInfo.targetInputMethodUser != null
                    ? editorInfo.targetInputMethodUser.getIdentifier() : UserHandle.myUserId();
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMM.startInputOrWindowGainedFocus");

            int startInputSeq = -1;
            if (Flags.useZeroJankProxy()) {
                // async result delivered via MSG_START_INPUT_RESULT.
                startInputSeq = IInputMethodManagerGlobalInvoker.startInputOrWindowGainedFocusAsync(
                        startInputReason, mClient, windowGainingFocus, startInputFlags,
                        softInputMode, windowFlags, editorInfo, servedInputConnection,
                        servedInputConnection == null ? null
                                : servedInputConnection.asIRemoteAccessibilityInputConnection(),
                        view.getContext().getApplicationInfo().targetSdkVersion, targetUserId,
                        mImeDispatcher);
            } else {
                res = IInputMethodManagerGlobalInvoker.startInputOrWindowGainedFocus(
                        startInputReason, mClient, windowGainingFocus, startInputFlags,
                        softInputMode, windowFlags, editorInfo, servedInputConnection,
@@ -3087,7 +3177,33 @@ public final class InputMethodManager {
                                : servedInputConnection.asIRemoteAccessibilityInputConnection(),
                        view.getContext().getApplicationInfo().targetSdkVersion, targetUserId,
                        mImeDispatcher);
            }
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            if (Flags.useZeroJankProxy()) {
                // Create a runnable for delayed notification to the app that the InputConnection is
                // initialized and ready for use.
                if (ic != null) {
                    final int seqId = startInputSeq;
                    mReportInputConnectionOpenedRunner =
                            new ReportInputConnectionOpenedRunner(startInputSeq) {
                                @Override
                                public void run() {
                                    if (DEBUG) {
                                        Log.v(TAG, "Calling View.onInputConnectionOpened: view= "
                                                + view
                                                + ", ic=" + ic + ", editorInfo=" + editorInfo
                                                + ", handler="
                                                + icHandler + ", startInputSeq=" + seqId);
                                    }
                                    reportInputConnectionOpened(ic, editorInfo, icHandler, view);
                                }
                            };
                } else {
                    mReportInputConnectionOpenedRunner = null;
                }
                return true;
            }

            if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
            if (res == null) {
                Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
@@ -3118,6 +3234,7 @@ public final class InputMethodManager {
            } else if (res.channel != null && res.channel != mCurChannel) {
                res.channel.dispose();
            }

            switch (res.result) {
                case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
                    mRestartOnNextWindowFocus = true;
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.internal.inputmethod.InputBindResult;
 */
oneway interface IInputMethodClient {
    void onBindMethod(in InputBindResult res);
    void onStartInputResult(in InputBindResult res, int startInputSeq);
    void onBindAccessibilityService(in InputBindResult res, int id);
    void onUnbindMethod(int sequence, int unbindReason);
    void onUnbindAccessibilityService(int sequence, int id);
+1 −0
Original line number Diff line number Diff line
@@ -271,6 +271,7 @@ public final class InputBindResult implements Parcelable {
    public String toString() {
        return "InputBindResult{result=" + getResultString() + " method=" + method + " id=" + id
                + " sequence=" + sequence
                + " result=" + result
                + " isInputMethodSuppressingSpellChecker=" + isInputMethodSuppressingSpellChecker
                + "}";
    }
+18 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ interface IInputMethodManager {
    boolean hideSoftInput(in IInputMethodClient client, @nullable IBinder windowToken,
            in @nullable ImeTracker.Token statsToken, int flags,
            in @nullable ResultReceiver resultReceiver, int reason);

    // TODO(b/293640003): Remove method once Flags.useZeroJankProxy() is enabled.
    // If windowToken is null, this just does startInput().  Otherwise this reports that a window
    // has gained focus, and if 'editorInfo' is non-null then also does startInput.
    // @NonNull
@@ -85,6 +87,21 @@ interface IInputMethodManager {
            int unverifiedTargetSdkVersion, int userId,
            in ImeOnBackInvokedDispatcher imeDispatcher);

    // If windowToken is null, this just does startInput().  Otherwise this reports that a window
    // has gained focus, and if 'editorInfo' is non-null then also does startInput.
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
            + "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
    void startInputOrWindowGainedFocusAsync(
            /* @StartInputReason */ int startInputReason,
            in IInputMethodClient client, in @nullable IBinder windowToken,
            /* @StartInputFlags */ int startInputFlags,
            /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
            /* @android.view.WindowManager.LayoutParams.Flags */ int windowFlags,
            in @nullable EditorInfo editorInfo, in @nullable IRemoteInputConnection inputConnection,
            in @nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
            int unverifiedTargetSdkVersion, int userId,
            in ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq);

    void showInputMethodPickerFromClient(in IInputMethodClient client,
            int auxiliarySubtypeMode);

@@ -156,6 +173,7 @@ interface IInputMethodManager {
                in String delegatePackageName,
                in String delegatorPackageName);

    // TODO(b/293640003): introduce a new API method to provide async way to return boolean.
    /** Accepts and starts a stylus handwriting session for the delegate view **/
    boolean acceptStylusHandwritingDelegation(in IInputMethodClient client, in int userId,
            in String delegatePackageName, in String delegatorPackageName, int flags);
Loading