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

Commit ebef2371 authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Automerger Merge Worker
Browse files

Merge "Fix IME jumpcut when playing user IME animation after IME restarted"...

Merge "Fix IME jumpcut when playing user IME animation after IME restarted" into tm-qpr-dev am: 469cbe90

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19600919



Change-Id: I6a80cf882660267d6a131ebb016a09e09c34297a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 008316a2 469cbe90
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -176,7 +176,9 @@ public class InsetsSourceConsumer {

                // If we have a new leash, make sure visibility is up-to-date, even though we
                // didn't want to run an animation above.
                if (mController.getAnimationType(control.getType()) == ANIMATION_TYPE_NONE) {
                    applyRequestedVisibilityToControl();
                }

                // Remove the surface that owned by last control when it lost.
                if (!requestedVisible && lastControl == null) {
+43 −4
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package android.view;

import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_USER;
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.statusBars;

import static junit.framework.Assert.assertEquals;
@@ -28,6 +30,7 @@ import static junit.framework.TestCase.assertTrue;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -75,6 +78,7 @@ public class InsetsSourceConsumerTest {
    private boolean mRemoveSurfaceCalled = false;
    private InsetsController mController;
    private InsetsState mState;
    private ViewRootImpl mViewRoot;

    @Before
    public void setup() {
@@ -86,10 +90,9 @@ public class InsetsSourceConsumerTest {
        instrumentation.runOnMainSync(() -> {
            final Context context = instrumentation.getTargetContext();
            // cannot mock ViewRootImpl since it's final.
            final ViewRootImpl viewRootImpl = new ViewRootImpl(context,
                    context.getDisplayNoVerify());
            mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify());
            try {
                viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
                mViewRoot.setView(new TextView(context), new LayoutParams(), null);
            } catch (BadTokenException e) {
                // activity isn't running, lets ignore BadTokenException.
            }
@@ -97,7 +100,7 @@ public class InsetsSourceConsumerTest {
            mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR));
            mState.addSource(mSpyInsetsSource);

            mController = new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl));
            mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot));
            mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mState,
                    () -> mMockTransaction, mController) {
                @Override
@@ -207,4 +210,40 @@ public class InsetsSourceConsumerTest {
        });

    }

    @Test
    public void testWontUpdateImeLeashVisibility_whenAnimation() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            InsetsState state = new InsetsState();
            ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot);
            InsetsController insetsController = new InsetsController(host, (controller, type) -> {
                if (type == ITYPE_IME) {
                    return new InsetsSourceConsumer(ITYPE_IME, state,
                            () -> mMockTransaction, controller) {
                        @Override
                        public int requestShow(boolean fromController) {
                            return SHOW_IMMEDIATELY;
                        }
                    };
                }
                return new InsetsSourceConsumer(type, controller.getState(), Transaction::new,
                        controller);
            }, host.getHandler());
            InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(ITYPE_IME);

            // Initial IME insets source control with its leash.
            imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash,
                    false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
            reset(mMockTransaction);

            // Verify when the app requests controlling show IME animation, the IME leash
            // visibility won't be updated when the consumer received the same leash in setControl.
            insetsController.controlWindowInsetsAnimation(ime(), 0L,
                    null /* interpolator */, null /* cancellationSignal */, null /* listener */);
            assertTrue(insetsController.getAnimationType(ITYPE_IME) == ANIMATION_TYPE_USER);
            imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash,
                    true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
            verify(mMockTransaction, never()).show(mLeash);
        });
    }
}
+11 −4
Original line number Diff line number Diff line
@@ -4388,13 +4388,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     */
    @VisibleForTesting
    InsetsControlTarget computeImeControlTarget() {
        if (mImeInputTarget == null) {
            // A special case that if there is no IME input target while the IME is being killed,
            // in case seeing unexpected IME surface visibility change when delivering the IME leash
            // to the remote insets target during the IME restarting, but the focus window is not in
            // multi-windowing mode, return null target until the next input target updated.
            return null;
        }

        final WindowState imeInputTarget = mImeInputTarget.getWindowState();
        if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null
                || (mImeInputTarget != null
                        && getImeHostOrFallback(mImeInputTarget.getWindowState())
                               == mRemoteInsetsControlTarget)) {
                || getImeHostOrFallback(imeInputTarget) == mRemoteInsetsControlTarget) {
            return mRemoteInsetsControlTarget;
        } else {
            return mImeInputTarget != null ? mImeInputTarget.getWindowState() : null;
            return imeInputTarget;
        }
    }

+9 −1
Original line number Diff line number Diff line
@@ -1251,7 +1251,15 @@ public class DisplayContentTests extends WindowTestsBase {
    public void testComputeImeControlTarget() throws Exception {
        final DisplayContent dc = createNewDisplay();
        dc.setRemoteInsetsController(createDisplayWindowInsetsController());
        dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
        dc.mCurrentFocus = createWindow(null, TYPE_BASE_APPLICATION, "app");

        // Expect returning null IME control target when the focus window has not yet been the
        // IME input target (e.g. IME is restarting) in fullscreen windowing mode.
        dc.setImeInputTarget(null);
        assertFalse(dc.mCurrentFocus.inMultiWindowMode());
        assertNull(dc.computeImeControlTarget());

        dc.setImeInputTarget(dc.mCurrentFocus);
        dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState());
        assertEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget());
    }