Merge "Fix flickering when switched to the task without IME shown" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-08-02 16:59:45 +00:00
committed by Android (Google) Code Review
2 changed files with 69 additions and 10 deletions

View File

@@ -32,6 +32,10 @@ import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_B
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
@@ -211,7 +215,7 @@ class InsetsPolicy {
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
return adjustVisibilityForIme(target, state, state == originalState);
}
/**
@@ -241,16 +245,38 @@ class InsetsPolicy {
return state;
}
// Navigation bar insets is always visible to IME.
private static InsetsState adjustVisibilityForIme(InsetsState originalState,
private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
boolean copyState) {
final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
if (originalNavSource != null && !originalNavSource.isVisible()) {
final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
final InsetsSource navSource = new InsetsSource(originalNavSource);
navSource.setVisible(true);
state.addSource(navSource);
return state;
if (w.mIsImWindow) {
// Navigation bar insets is always visible to IME.
final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
if (originalNavSource != null && !originalNavSource.isVisible()) {
final InsetsState state = copyState ? new InsetsState(originalState)
: originalState;
final InsetsSource navSource = new InsetsSource(originalNavSource);
navSource.setVisible(true);
state.addSource(navSource);
return state;
}
} else if (w.mActivityRecord != null && !w.mActivityRecord.mLastImeShown) {
// During switching tasks with gestural navigation, if the IME is attached to
// one app window on that time, even the next app window is behind the IME window,
// conceptually the window should not receive the IME insets if the next window is
// not eligible IME requester and ready to show IME on top of it.
final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
if (originalImeSource != null && shouldImeAttachedToApp
&& (w.isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS)
|| !w.getRequestedVisibility(ITYPE_IME))) {
final InsetsState state = copyState ? new InsetsState(originalState)
: originalState;
final InsetsSource imeSource = new InsetsSource(originalImeSource);
imeSource.setVisible(false);
state.addSource(imeSource);
return state;
}
}
return originalState;
}

View File

@@ -53,6 +53,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
import static com.google.common.truth.Truth.assertThat;
@@ -891,6 +894,36 @@ public class WindowStateTests extends WindowTestsBase {
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@Test
public void testAdjustImeInsetsVisibilityWhenTaskSwitchIsAnimating() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
final InsetsStateController controller = mDisplayContent.getInsetsStateController();
controller.getImeSourceProvider().setWindow(mImeWindow, null, null);
// Simulate app requests IME with updating all windows Insets State when IME is above app.
mDisplayContent.setImeLayeringTarget(app);
mDisplayContent.setImeInputTarget(app);
assertTrue(mDisplayContent.shouldImeAttachedToApp());
controller.getImeSourceProvider().scheduleShowImePostLayout(app);
controller.getImeSourceProvider().getSource().setVisible(true);
controller.updateAboveInsetsState(mImeWindow, false);
// Simulate task switching animation happens when switching app to app2.
spyOn(app);
spyOn(app2);
doReturn(true).when(app).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
doReturn(true).when(app2).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
app.mActivityRecord.mLastImeShown = true;
// Verify the IME insets is visible on app, but not for app2 during task animating.
InsetsState stateApp = app.getInsetsState();
InsetsState stateApp2 = app2.getInsetsState();
assertTrue(stateApp.getSource(ITYPE_IME).isVisible());
assertFalse(stateApp2.getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {