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

Commit 737c7915 authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Fix WIC#hide(ime()) no-op after WIC#show(ime()) in Activity#onCreate

In InsetsController#hide, ensure to request hide IME with calling
ImeInsetsSurceConsumer#requestHide, in case the pending visible
request will triggger show after setControl.

Also, we modified PendingControlRequest to be able to remove from the
show insets type when it has being requested invisible by
InsetsController#hide(type), if the removed type contains the IME then
we handle the pending show control request for other types since it
is no longer needed to wait the IME ready to show.

Also, make sure set mIsRequestedVisibleAwaitingControl as false when
ImeInsetsSourceConsumer#notifyHidden to avoid the above pending visible
request happens.

Bug: 248456059
Test: atest CtsInputMethodTestCases
Test: atest InputMethodStressTest:ImeOpenCloseStressTest
Change-Id: Id3aebca3348888826bc5d3c6694e94cddb80b4d4
parent 0b6a4209
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
                ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);

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

+47 −14
Original line number Diff line number Diff line
@@ -552,7 +552,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            this.useInsetsAnimationThread = useInsetsAnimationThread;
        }

        final @InsetsType int types;
        @InsetsType int types;
        final WindowInsetsAnimationControlListener listener;
        final long durationMs;
        final Interpolator interpolator;
@@ -1006,19 +1006,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        }
        // Handle pending request ready in case there was one set.
        if (fromIme && mPendingImeControlRequest != null) {
            PendingControlRequest pendingRequest = mPendingImeControlRequest;
            mPendingImeControlRequest = null;
            mHandler.removeCallbacks(mPendingControlTimeout);

            // We are about to playing the default animation. Passing a null frame indicates the
            // controlled types should be animated regardless of the frame.
            controlAnimationUnchecked(
                    pendingRequest.types, pendingRequest.cancellationSignal,
                    pendingRequest.listener, null /* frame */,
                    true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
                    pendingRequest.animationType,
                    pendingRequest.layoutInsetsDuringAnimation,
                    pendingRequest.useInsetsAnimationThread, statsToken);
            handlePendingControlRequest(statsToken);
            return;
        }

@@ -1061,6 +1049,27 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        applyAnimation(typesReady, true /* show */, fromIme, statsToken);
    }

    /**
     * Handle the {@link #mPendingImeControlRequest} when
     * - The IME insets is ready to show.
     * - The IME insets has being requested invisible.
     */
    private void handlePendingControlRequest(@Nullable ImeTracker.Token statsToken) {
        PendingControlRequest pendingRequest = mPendingImeControlRequest;
        mPendingImeControlRequest = null;
        mHandler.removeCallbacks(mPendingControlTimeout);

        // We are about to playing the default animation. Passing a null frame indicates the
        // controlled types should be animated regardless of the frame.
        controlAnimationUnchecked(
                pendingRequest.types, pendingRequest.cancellationSignal,
                pendingRequest.listener, null /* frame */,
                true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
                pendingRequest.animationType,
                pendingRequest.layoutInsetsDuringAnimation,
                pendingRequest.useInsetsAnimationThread, statsToken);
    }

    @Override
    public void hide(@InsetsType int types) {
        ImeTracker.Token statsToken = null;
@@ -1084,6 +1093,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
        }
        int typesReady = 0;
        boolean hasImeRequestedHidden = false;
        final boolean hadPendingImeControlRequest = mPendingImeControlRequest != null;
        for (int type = FIRST; type <= LAST; type = type << 1) {
            if ((types & type) == 0) {
                continue;
@@ -1091,6 +1102,22 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            @AnimationType final int animationType = getAnimationType(type);
            final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0;
            final boolean isImeAnimation = type == ime();
            if (mPendingImeControlRequest != null && !requestedVisible) {
                // Remove the hide insets type from the pending show request.
                mPendingImeControlRequest.types &= ~type;
                if (mPendingImeControlRequest.types == 0) {
                    abortPendingImeControlRequest();
                }
            }
            if (isImeAnimation && !requestedVisible && animationType == ANIMATION_TYPE_NONE) {
                hasImeRequestedHidden = true;
                // Ensure to request hide IME in case there is any pending requested visible
                // being applied from setControl when receiving the insets control.
                if (hadPendingImeControlRequest
                        || getImeSourceConsumer().isRequestedVisibleAwaitingControl()) {
                    getImeSourceConsumer().requestHide(fromIme, statsToken);
                }
            }
            if (!requestedVisible && animationType == ANIMATION_TYPE_NONE
                    || animationType == ANIMATION_TYPE_HIDE) {
                // no-op: already hidden or animating out (because window visibility is
@@ -1106,6 +1133,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            }
            typesReady |= type;
        }
        if (hasImeRequestedHidden && mPendingImeControlRequest != null) {
            // Handle the pending show request for other insets types since the IME insets has being
            // requested hidden.
            handlePendingControlRequest(statsToken);
            getImeSourceConsumer().removeSurface();
        }
        applyAnimation(typesReady, false /* show */, fromIme, statsToken);
    }