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

Commit 3eb602c6 authored by Felix Stern's avatar Felix Stern Committed by Android (Google) Code Review
Browse files

Merge "Remove refactorInsetsController Flag" into main

parents bfb84880 1dad36fb
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -225,12 +225,12 @@ class IInputMethodWrapper extends IInputMethod.Stub
                return;
            case DO_SHOW_SOFT_INPUT: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
                final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2;
                if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) {
                    ImeTracker.forLogging().onProgress(
                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                    inputMethod.showSoftInputWithToken(
                            msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken);
                    inputMethod.showSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1,
                            statsToken);
                } else {
                    ImeTracker.forLogging().onFailed(
                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
@@ -240,12 +240,12 @@ class IInputMethodWrapper extends IInputMethod.Stub
            }
            case DO_HIDE_SOFT_INPUT: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
                final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg2;
                if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) {
                    ImeTracker.forLogging().onProgress(
                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                    inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2,
                            (IBinder) args.arg1, statsToken);
                    inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg1,
                            statsToken);
                } else {
                    ImeTracker.forLogging().onFailed(
                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
@@ -453,20 +453,20 @@ class IInputMethodWrapper extends IInputMethod.Stub

    @BinderThread
    @Override
    public void showSoftInput(IBinder showInputToken, @NonNull ImeTracker.Token statsToken,
    public void showSoftInput(@NonNull ImeTracker.Token statsToken,
            @InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
                flags, showInputToken, resultReceiver, statsToken));
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_SHOW_SOFT_INPUT,
                flags, resultReceiver, statsToken));
    }

    @BinderThread
    @Override
    public void hideSoftInput(IBinder hideInputToken, @NonNull ImeTracker.Token statsToken,
            int flags, ResultReceiver resultReceiver) {
    public void hideSoftInput(@NonNull ImeTracker.Token statsToken, int flags,
            ResultReceiver resultReceiver) {
        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT,
                flags, hideInputToken, resultReceiver, statsToken));
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_HIDE_SOFT_INPUT,
                flags, resultReceiver, statsToken));
    }

    @BinderThread
+14 −66
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@ 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;
@@ -649,26 +648,6 @@ public class InputMethodService extends AbstractInputMethodService {
    // committed by commitHandwritingDelegationTextIfAvailable().
    private CharSequence mHandwritingDelegationText;

    /**
     * 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
     * placeholder token to identify this window.
     * This placeholder token is only valid for a single call to
     * {@link InputMethodImpl#showSoftInput}, after which it is set null until next call.
     */
    private IBinder mCurShowInputToken;

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

    /**
     * The token tracking the current IME request.
     *
@@ -881,14 +860,12 @@ public class InputMethodService extends AbstractInputMethodService {
        @MainThread
        @Override
        public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver,
                IBinder hideInputToken, @NonNull ImeTracker.Token statsToken) {
                @NonNull ImeTracker.Token statsToken) {
            mSystemCallingHideSoftInput = true;
            mCurHideInputToken = hideInputToken;
            mCurStatsToken = statsToken;
            try {
                hideSoftInput(flags, resultReceiver);
            } finally {
                mCurHideInputToken = null;
                mSystemCallingHideSoftInput = false;
            }
        }
@@ -936,14 +913,12 @@ public class InputMethodService extends AbstractInputMethodService {
                                : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
            }
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            if (android.view.inputmethod.Flags.refactorInsetsController()) {
            // After the IME window was hidden, we can remove its surface
            scheduleImeSurfaceRemoval();
            // The hide request first finishes the animation and then proceeds to the server
            // side, finally reaching here, marking this the end state.
            ImeTracker.forLogging().onHidden(statsToken);
        }
        }

        /**
         * {@inheritDoc}
@@ -952,15 +927,12 @@ public class InputMethodService extends AbstractInputMethodService {
        @MainThread
        @Override
        public void showSoftInputWithToken(@InputMethod.ShowFlags int flags,
                ResultReceiver resultReceiver, IBinder showInputToken,
                @NonNull ImeTracker.Token statsToken) {
                ResultReceiver resultReceiver, @NonNull ImeTracker.Token statsToken) {
            mSystemCallingShowSoftInput = true;
            mCurShowInputToken = showInputToken;
            mCurStatsToken = statsToken;
            try {
                showSoftInput(flags, resultReceiver);
            } finally {
                mCurShowInputToken = null;
                mSystemCallingShowSoftInput = false;
            }
        }
@@ -3108,12 +3080,10 @@ public class InputMethodService extends AbstractInputMethodService {

        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_SHOW_WINDOW);

        if (android.view.inputmethod.Flags.refactorInsetsController()) {
        // The ImeInsetsSourceProvider need the statsToken when dispatching the control
        // (whenever the IME has drawn and its window is visible). Therefore, sending the
        // statsToken here first.
        notifyPreImeWindowVisibilityChanged(true /* visible */, statsToken);
        }

        ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", mDumper,
                null /* icProto */);
@@ -3132,9 +3102,6 @@ public class InputMethodService extends AbstractInputMethodService {
        if (DEBUG) Log.v(TAG, "showWindow: draw decorView!");
        mWindow.show();
        mDecorViewWasVisible = true;
        if (!android.view.inputmethod.Flags.refactorInsetsController()) {
            applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */, statsToken);
        }
        cancelImeSurfaceRemoval();
        mInShowWindow = false;
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -3266,21 +3233,6 @@ public class InputMethodService extends AbstractInputMethodService {
        if (doShowInput) startExtractingText(false);
    }

    /**
     * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}.
     *
     * @param setVisible {@code true} to make it visible, false to hide it.
     * @param statsToken the token tracking the current IME request.
     */
    private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible,
            @NonNull ImeTracker.Token statsToken) {
        ImeTracing.getInstance().triggerServiceDump(
                "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper,
                null /* icProto */);
        mPrivOps.applyImeVisibilityAsync(setVisible
                ? mCurShowInputToken : mCurHideInputToken, setVisible, statsToken);
    }

    /**
     * Notifies the ImeInsetsSourceProvider before the IME visibility changes.
     *
@@ -3336,13 +3288,9 @@ public class InputMethodService extends AbstractInputMethodService {
        ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper,
                null /* icProto */);
        setImeWindowVisibility(0 /* vis */);
        if (android.view.inputmethod.Flags.refactorInsetsController()) {
        // The ImeInsetsSourceProvider need the statsToken when dispatching the control. We
        // send the token here, so that another request in the provider can be cancelled.
        notifyPreImeWindowVisibilityChanged(false /* visible */, statsToken);
        } else {
            applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */, statsToken);
        }
        mWindowVisible = false;
        finishViews(false /* finishingInput */);
        if (mDecorViewVisible) {
+4 −7
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ import android.util.Log;
import android.view.animation.BackGestureInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
@@ -151,13 +150,11 @@ public class ImeBackAnimationController implements OnBackAnimationCallback {
        } else {
            startPostCommitAnim(/*hideIme*/ true);
        }
        if (Flags.refactorInsetsController()) {
        // Unregister all IME back callbacks so that back events are sent to the next callback
        // even while the hide animation is playing
        mInsetsController.getHost().getInputMethodManager().getImeOnBackInvokedDispatcher()
                .preliminaryClear();
    }
    }

    private void setPreCommitProgress(float progress) {
        if (isHideAnimationInProgress()) return;
+1 −3
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.annotation.NonNull;
import android.annotation.UiThread;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.inputmethod.Flags;
import android.view.inputmethod.InputMethodManager;

import com.android.internal.inputmethod.InputMethodDebug;
@@ -151,8 +150,7 @@ public final class ImeFocusController {
        if (!mHasImeFocus || isInLocalFocusMode(windowAttribute)) {
            return InputMethodManager.DISPATCH_NOT_HANDLED;
        }
        if (Flags.refactorInsetsController() && event instanceof KeyEvent keyEvent
                && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        if (event instanceof KeyEvent keyEvent && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            final var insetsController = mViewRootImpl.getInsetsController();
            if (insetsController.getAnimationType(WindowInsets.Type.ime())
                    == InsetsController.ANIMATION_TYPE_HIDE
+0 −291
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.view;

import static android.os.Trace.TRACE_TAG_VIEW;
import static android.view.ImeInsetsSourceConsumerProto.HAS_PENDING_REQUEST;
import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER;
import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.Trace;
import android.util.proto.ProtoOutputStream;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputMethodManager;

import com.android.internal.inputmethod.ImeTracing;
import com.android.internal.inputmethod.SoftInputShowHideReason;

/**
 * Controls the visibility and animations of IME window insets source.
 * @hide
 */
public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {

    /**
     * Tracks whether are requested to show during the hide animation or requested to hide during
     * the show animation. If this is true, we should not remove the surface.
     */
    private boolean mHasPendingRequest;

    /**
     * Tracks whether we have an outstanding request from the IME to show, but weren't able to
     * execute it because we didn't have control yet, or we didn't have a leash on the control yet.
     */
    private boolean mIsRequestedVisibleAwaitingLeash;

    public ImeInsetsSourceConsumer(int id, InsetsState state, InsetsController controller) {
        super(id, WindowInsets.Type.ime(), state, controller);
    }

    @Override
    public boolean onAnimationStateChanged(boolean running) {
        if (Flags.refactorInsetsController()) {
            return super.onAnimationStateChanged(running);
        } else {
            if (!running) {
                ImeTracing.getInstance().triggerClientDump(
                        "ImeInsetsSourceConsumer#onAnimationFinished",
                        mController.getHost().getInputMethodManager(), null /* icProto */);
            }
            boolean insetsChanged = false;
            if (!running && isShowRequested() && mAnimationState == ANIMATION_STATE_HIDE) {
                // A user controlled hide animation may have ended in the shown state (e.g.
                // cancelled predictive back animation) -> Insets need to be reset to shown.
                insetsChanged |= applyLocalVisibilityOverride();
            }
            insetsChanged |= super.onAnimationStateChanged(running);
            if (running && !isShowRequested()
                    && mController.isPredictiveBackImeHideAnimInProgress()) {
                // IME predictive back animation switched from pre-commit to post-commit.
                insetsChanged |= applyLocalVisibilityOverride();
            }
            if (!isShowRequested()) {
                mIsRequestedVisibleAwaitingLeash = false;
                if (!running && !mHasPendingRequest) {
                    final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
                            ImeTracker.ORIGIN_CLIENT,
                            SoftInputShowHideReason.HIDE_SOFT_INPUT_ON_ANIMATION_STATE_CHANGED,
                            mController.getHost().isHandlingPointerEvent() /* fromUser */);
                    notifyHidden(statsToken);
                    removeSurface();
                }
            }
            // This method is called
            // (1) after the animation starts.
            // (2) after the animation ends (including the case of cancel).
            // (3) if the IME is not controllable (running == false in this case).
            // We should reset mHasPendingRequest in all cases.
            mHasPendingRequest = false;
            return insetsChanged;
        }
    }

    @Override
    public void onWindowFocusGained(boolean hasViewFocus) {
        super.onWindowFocusGained(hasViewFocus);
        if (!Flags.refactorInsetsController()) {
            getImm().registerImeConsumer(this);
            if ((mController.getRequestedVisibleTypes() & getType()) != 0 && !hasLeash()) {
                mIsRequestedVisibleAwaitingLeash = true;
            }
        }
    }

    @Override
    public void onWindowFocusLost() {
        super.onWindowFocusLost();
        if (!Flags.refactorInsetsController()) {
            getImm().unregisterImeConsumer(this);
            mIsRequestedVisibleAwaitingLeash = false;
        }
    }

    @Override
    public boolean applyLocalVisibilityOverride() {
        if (!Flags.refactorInsetsController()) {
            ImeTracing.getInstance().triggerClientDump(
                    "ImeInsetsSourceConsumer#applyLocalVisibilityOverride",
                    mController.getHost().getInputMethodManager(), null /* icProto */);
        }
        return super.applyLocalVisibilityOverride();
    }

    /**
     * Request {@link InputMethodManager} to show the IME.
     * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}.
     */
    @Override
    @ShowResult
    public int requestShow(boolean fromIme, @Nullable ImeTracker.Token statsToken) {
        if (!Flags.refactorInsetsController()) {
            if (fromIme) {
                ImeTracing.getInstance().triggerClientDump(
                        "ImeInsetsSourceConsumer#requestShow",
                        mController.getHost().getInputMethodManager(), null /* icProto */);
            }
            onShowRequested();

            // TODO: ResultReceiver for IME.
            // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
            ImeTracker.forLogging().onProgress(statsToken,
                    ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW);

            if (!hasLeash()) {
                // If control or leash is null, schedule to show IME when both available.
                mIsRequestedVisibleAwaitingLeash = true;
            }
            // If we had a request before to show from IME (tracked with mImeRequestedShow),
            // reaching this code here means that we now got control, so we can start the
            // animation immediately. If client window is trying to control IME and IME is
            // already visible, it is immediate.
            if (fromIme || (mState.isSourceOrDefaultVisible(getId(), getType())
                    && hasLeash())) {
                return ShowResult.SHOW_IMMEDIATELY;
            }

            return getImm().requestImeShow(mController.getHost().getWindowToken(), statsToken)
                    ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED;
        } else {
            return ShowResult.IME_SHOW_FAILED;
        }
    }

    void requestHide(boolean fromIme, @Nullable ImeTracker.Token statsToken) {
        if (!Flags.refactorInsetsController()) {
            if (!fromIme) {
                // Create a new token to track the hide request when we have control and leash,
                // as we use the passed in token for the insets animation already.
                final var notifyStatsToken = hasLeash()
                        ? ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
                            ImeTracker.ORIGIN_CLIENT,
                            SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL,
                            mController.getHost().isHandlingPointerEvent() /* fromUser */)
                        : statsToken;
                // The insets might be controlled by a remote target. Let the server know we are
                // requested to hide.
                notifyHidden(notifyStatsToken);
            }
            if (mAnimationState == ANIMATION_STATE_SHOW) {
                mHasPendingRequest = true;
            }
        }
    }

    /**
     * Notify {@link com.android.server.inputmethod.InputMethodManagerService} that
     * IME insets are hidden.
     *
     * @param statsToken the token tracking the current IME request or {@code null} otherwise.
     */
    private void notifyHidden(@NonNull ImeTracker.Token statsToken) {
        if (!Flags.refactorInsetsController()) {
            ImeTracker.forLogging().onProgress(statsToken,
                    ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);

            getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken);
            mIsRequestedVisibleAwaitingLeash = false;
            Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
        }
    }

    @Override
    public void removeSurface() {
        if (Flags.refactorInsetsController()) {
            super.removeSurface();
        } else {
            final IBinder window = mController.getHost().getWindowToken();
            if (window != null) {
                getImm().removeImeSurface(window);
            }
        }
    }

    @Override
    public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes,
            int[] hideTypes, int[] cancelTypes, int[] transientTypes) {
        if (Flags.refactorInsetsController()) {
            return super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes);
        } else {
            ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl",
                    mController.getHost().getInputMethodManager(), null /* icProto */);
            if (!super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes)) {
                return false;
            }
            if (control == null && !mIsRequestedVisibleAwaitingLeash) {
                mController.setRequestedVisibleTypes(0 /* visibleTypes */, getType());
                removeSurface();
            }
            final boolean hasLeash = control != null && control.getLeash() != null;
            if (hasLeash) {
                mIsRequestedVisibleAwaitingLeash = false;
            }
            return true;
        }
    }

    @Override
    protected boolean isRequestedVisibleAwaitingControl() {
        return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingLeash;
    }

    /**
     * Checks whether the consumer has an insets source control with a leash.
     */
    private boolean hasLeash() {
        final var control = getControl();
        return control != null && control.getLeash() != null;
    }

    @Override
    public void onPerceptible(boolean perceptible) {
        super.onPerceptible(perceptible);
        if (!Flags.refactorInsetsController()) {
            final IBinder window = mController.getHost().getWindowToken();
            if (window != null) {
                getImm().reportPerceptible(window, perceptible);
            }
        }
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        super.dumpDebug(proto, INSETS_SOURCE_CONSUMER);
        proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingLeash);
        proto.write(HAS_PENDING_REQUEST, mHasPendingRequest);
        proto.end(token);
    }

    /**
     * Called when {@link #requestShow(boolean, ImeTracker.Token)} or
     * {@link InputMethodManager#showSoftInput(View, int)} is called.
     */
    public void onShowRequested() {
        if (mAnimationState == ANIMATION_STATE_HIDE
                || mController.isPredictiveBackImeHideAnimInProgress()) {
            mHasPendingRequest = true;
        }
    }

    private InputMethodManager getImm() {
        return mController.getHost().getInputMethodManager();
    }
}
Loading