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

Commit 8fb9afd6 authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Fix ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest flaky

As CL[1] that ImeVisibilityStateComputer leverages
onImeInputTargetVisibilityChanged callback to check whether the current
IME input target has been covered and became invisible by non-IME focusable
layering target. If so then ImeVisibilityStateComputer will hide the IME
to address the IME persists on top of layering target but the input target
was invisible case.

But there is an edge case that the starting window could possible shown
and cover the IME input target befor it drawn during animating (e.g.
quick-switching app tasks by recents animation) then leads to IME may
hidden by CL[1]'s case.

Luckly the above scenario has caught by
ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest, to fix this
flaky case, add the windowType in onImeTargetOverlayVisibilityChanged
to give more context for ImeVisibilityStateComputer and ignore the starting
window case, since it since it's ok to cover the IME input target window
in temporary without affecting the IME visibility.

[1]: Ia71b975898efb19439c3a1b1a9a2bdcf21b78650

Fix: 278698977
Test: atest
FlickerTest:ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest
--rerun-until-failure 10
Test: atest ImeVisibilityStateComputerTest

Change-Id: I3a950423f73f0a97432589d0a90ac8fd1c84f05e
parent 95741003
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVI
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;

import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
@@ -195,19 +196,25 @@ public final class ImeVisibilityStateComputer {
        mWindowManagerInternal.setInputMethodTargetChangeListener(new ImeTargetChangeListener() {
            @Override
            public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken,
                    boolean visible, boolean removed) {
                mCurVisibleImeLayeringOverlay = (visible && !removed) ? overlayWindowToken : null;
                    @WindowManager.LayoutParams.WindowType int windowType, boolean visible,
                    boolean removed) {
                mCurVisibleImeLayeringOverlay =
                        // Ignoring the starting window since it's ok to cover the IME target
                        // window in temporary without affecting the IME visibility.
                        (visible && !removed && windowType != TYPE_APPLICATION_STARTING)
                                ? overlayWindowToken : null;
            }

            @Override
            public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
                    boolean visibleRequested, boolean removed) {
                mCurVisibleImeInputTarget = (visibleRequested && !removed) ? imeInputTarget : null;
                if (mCurVisibleImeInputTarget == null && mCurVisibleImeLayeringOverlay != null) {
                if (mCurVisibleImeInputTarget == imeInputTarget && (!visibleRequested || removed)
                        && mCurVisibleImeLayeringOverlay != null) {
                    mService.onApplyImeVisibilityFromComputer(imeInputTarget,
                            new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
                                    SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE));
                }
                mCurVisibleImeInputTarget = (visibleRequested && !removed) ? imeInputTarget : null;
            }
        });
    }
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;

import android.annotation.NonNull;
import android.os.IBinder;
import android.view.WindowManager;

/**
 * Callback the IME targeting window visibility change state for
@@ -32,11 +33,13 @@ public interface ImeTargetChangeListener {
     * has changed its window visibility.
     *
     * @param overlayWindowToken the window token of the overlay window.
     * @param windowType         the window type of the overlay window.
     * @param visible            the visibility of the overlay window, {@code true} means visible
     *                           and {@code false} otherwise.
     * @param removed            Whether the IME target overlay window has being removed.
     */
    default void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken,
            @WindowManager.LayoutParams.WindowType int windowType,
            boolean visible, boolean removed) {
    }

+8 −5
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@ import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
import android.view.TaskTransitionSpec;
import android.view.View;
import android.view.ViewDebug;
import android.view.WindowContentFrameStats;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
@@ -1811,7 +1812,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (imMayMove) {
                displayContent.computeImeTarget(true /* updateImeTarget */);
                if (win.isImeOverlayLayeringTarget()) {
                    dispatchImeTargetOverlayVisibilityChanged(client.asBinder(),
                    dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
                            win.isVisibleRequestedOrAdding(), false /* removed */);
                }
            }
@@ -2521,7 +2522,7 @@ public class WindowManagerService extends IWindowManager.Stub

            final boolean winVisibleChanged = win.isVisible() != wasVisible;
            if (win.isImeOverlayLayeringTarget() && winVisibleChanged) {
                dispatchImeTargetOverlayVisibilityChanged(client.asBinder(),
                dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
                        win.isVisible(), false /* removed */);
            }
            // Notify listeners about IME input target window visibility change.
@@ -3355,15 +3356,17 @@ public class WindowManagerService extends IWindowManager.Stub
        });
    }

    void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token, boolean visible,
    void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token,
            @WindowManager.LayoutParams.WindowType int windowType, boolean visible,
            boolean removed) {
        if (mImeTargetChangeListener != null) {
            if (DEBUG_INPUT_METHOD) {
                Slog.d(TAG, "onImeTargetOverlayVisibilityChanged, win=" + mWindowMap.get(token)
                        + "visible=" + visible + ", removed=" + removed);
                        + ", type=" + ViewDebug.intToString(WindowManager.LayoutParams.class,
                        "type", windowType) + "visible=" + visible + ", removed=" + removed);
            }
            mH.post(() -> mImeTargetChangeListener.onImeTargetOverlayVisibilityChanged(token,
                    visible, removed));
                    windowType, visible, removed));
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -2349,7 +2349,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        super.removeImmediately();

        if (isImeOverlayLayeringTarget()) {
            mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(),
            mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(), mAttrs.type,
                    false /* visible */, true /* removed */);
        }
        final DisplayContent dc = getDisplayContent();
+6 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
@@ -241,8 +242,12 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
        final IBinder testImeTargetOverlay = new Binder();
        final IBinder testImeInputTarget = new Binder();

        // Simulate a test IME input target was visible.
        mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, true, false);

        // Simulate a test IME layering target overlay fully occluded the IME input target.
        mListener.onImeTargetOverlayVisibilityChanged(testImeTargetOverlay, true, false);
        mListener.onImeTargetOverlayVisibilityChanged(testImeTargetOverlay,
                TYPE_APPLICATION_OVERLAY, true, false);
        mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, false, false);
        final ArgumentCaptor<IBinder> targetCaptor = ArgumentCaptor.forClass(IBinder.class);
        final ArgumentCaptor<ImeVisibilityResult> resultCaptor = ArgumentCaptor.forClass(
Loading