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

Commit 2260ce4d authored by Adrian Roos's avatar Adrian Roos
Browse files

Fix IME flicker: move hiding the surface into the control target

Fixes a flicker that occurs during transitions between windows.

This happens for two reasons:

1.) Control is immediately transferred to the new window, and the
    previous window didn't get a chance to play the animation.

    This is addressed by adding logic to keep control on the
    exiting window for the duration of the transition - similar to
    what we do with the target for z-ordering purposes.

2.) Upon the input connection being severed, the InputMethodService
    immediately hides its window, preventing any animations whenever
    the input connection changes

    This is addressed by moving hiding of the surface into the
    controlling windows - where upon receiving control, we now
    trigger removal of the IME surface if we don't show it.

Additionally:

- Now ensures that any requests from the ImeInsetsSourceConsumer
  ensure that they come from the window that is currently served
  by IMM.

- Removes the transparancy clause from isImeTargetFromDisplayContentAndImeSame
  to match the updated IME target computation in DisplayContent in [1].

[1]: Iedd5f7407926167f4891ce9b7e9a79e22751e668

Fixes: 153145997
Fixes: 150902448
Test: atest WindowInsetsAnimationControllerTests
Test: atest DisplayContentTests InsetsSourceConsumerTest
Test: Open app with IME, press HOME button, verify IME smoothly animates away
Test: Open Messages, open a thread, open IME. Click search icon, verify IME opens in the search activity
Change-Id: I4910c2a06cc67b0470477b245fc1de54b75f10f9
parent f1f70009
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -605,9 +605,6 @@ public class InputMethodService extends AbstractInputMethodService {
            if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
                    + " ic=" + mInputConnection);
            // Unbind input is per process per display.
            // TODO(b/150902448): free-up IME surface when target is changing.
            //  e.g. DisplayContent#setInputMethodTarget()
            removeImeSurface();
            onUnbindInput();
            mInputBinding = null;
            mInputConnection = null;
+8 −4
Original line number Diff line number Diff line
@@ -119,11 +119,11 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
        // 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.getSource(getType()).isVisible()) {
        if (fromIme || mState.getSource(getType()).isVisible() && getControl() != null) {
            return ShowResult.SHOW_IMMEDIATELY;
        }

        return getImm().requestImeShow(null /* resultReceiver */)
        return getImm().requestImeShow(mController.getHost().getWindowToken())
                ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED;
    }

@@ -132,12 +132,15 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
     */
    @Override
    void notifyHidden() {
        getImm().notifyImeHidden();
        getImm().notifyImeHidden(mController.getHost().getWindowToken());
    }

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

    @Override
@@ -146,6 +149,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
        super.setControl(control, showTypes, hideTypes);
        if (control == null && !mIsRequestedVisibleAwaitingControl) {
            hide();
            removeSurface();
        }
    }

+3 −0
Original line number Diff line number Diff line
@@ -153,6 +153,9 @@ public class InsetsSourceConsumer {
                if (oldLeash == null || newLeash == null || !oldLeash.isSameSurface(newLeash)) {
                    applyHiddenToControl();
                }
                if (!requestedVisible && !mIsAnimationPending) {
                    removeSurface();
                }
            }
        }
        if (lastControl != null) {
+5 −0
Original line number Diff line number Diff line
@@ -9377,6 +9377,11 @@ public final class ViewRootImpl implements ViewParent,
        return mInputEventReceiver.getToken();
    }

    @NonNull
    public IBinder getWindowToken() {
        return mAttachInfo.mWindowToken;
    }

    /**
     * Class for managing the accessibility interaction connection
     * based on the global accessibility state.
+19 −11
Original line number Diff line number Diff line
@@ -2109,28 +2109,36 @@ public final class InputMethodManager {

    /**
     * Call showSoftInput with currently focused view.
     * @return {@code true} if IME can be shown.
     *
     * @param windowToken the window from which this request originates. If this doesn't match the
     *                    currently served view, the request is ignored and returns {@code false}.
     *
     * @return {@code true} if IME can (eventually) be shown, {@code false} otherwise.
     * @hide
     */
    public boolean requestImeShow(ResultReceiver resultReceiver) {
    public boolean requestImeShow(IBinder windowToken) {
        synchronized (mH) {
            final View servedView = getServedViewLocked();
            if (servedView == null) {
            if (servedView == null || servedView.getWindowToken() != windowToken) {
                return false;
            }
            showSoftInput(servedView, 0 /* flags */, resultReceiver);
            showSoftInput(servedView, 0 /* flags */, null /* resultReceiver */);
            return true;
        }
    }

    /**
     * Notify IME directly that it is no longer visible.
     *
     * @param windowToken the window from which this request originates. If this doesn't match the
     *                    currently served view, the request is ignored.
     * @hide
     */
    public void notifyImeHidden() {
    public void notifyImeHidden(IBinder windowToken) {
        synchronized (mH) {
            try {
                if (mCurMethod != null) {
                if (mCurMethod != null && mCurRootView != null
                        && mCurRootView.getWindowToken() == windowToken) {
                    mCurMethod.notifyImeHidden();
                }
            } catch (RemoteException re) {
@@ -2140,15 +2148,15 @@ public final class InputMethodManager {

    /**
     * Notify IME directly to remove surface as it is no longer visible.
     * @param windowToken The client window token that requests the IME to remove its surface.
     * @hide
     */
    public void removeImeSurface() {
    public void removeImeSurface(IBinder windowToken) {
        synchronized (mH) {
            try {
                if (mCurMethod != null) {
                    mCurMethod.removeImeSurface();
                }
            } catch (RemoteException re) {
                mService.removeImeSurfaceFromWindow(windowToken);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
Loading