summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jorim Jaggi <jjaggi@google.com> 2020-03-24 22:28:38 +0100
committer Jorim Jaggi <jjaggi@google.com> 2020-03-27 20:11:31 +0100
commit49b9f6c67c777898f4f956a433a11292174e37b9 (patch)
treea8686e84fd9ba3a5eb1995e7258257fe4d904563
parentac30aafd29174c2d17cb39b646920b9d7f6e65ed (diff)
Fix flickers when changing control
- Do not reset system bar visibility when changing control target - Do not apply hide transaction when gaining control, because that may result in a single-frame flicker because it will conflict with the animation - Check requestedVisible instead of InsetsState.isVisible in DecorView to avoid drawing the bar backgrounds transiently - Abort transient mode when focused win changes. Bug: 150195782 Bug: 152014877 Change-Id: I8bc9cdc89ce7364984ade8146e12a706ad5e8edb
-rw-r--r--core/java/android/view/InsetsController.java5
-rw-r--r--core/java/android/view/InsetsSourceConsumer.java12
-rw-r--r--core/java/android/view/PendingInsetsController.java8
-rw-r--r--core/java/android/view/WindowInsetsController.java8
-rw-r--r--core/java/com/android/internal/policy/DecorView.java23
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java37
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java86
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java3
10 files changed, 144 insertions, 50 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 40a460dfece0..ae115f631424 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -456,6 +456,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
return mState;
}
+ @Override
+ public boolean isRequestedVisible(int type) {
+ return getSourceConsumer(type).isRequestedVisible();
+ }
+
public InsetsState getLastDispatchedState() {
return mLastDispachedState;
}
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index f36621c0a49e..360195df6625 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -112,12 +112,12 @@ public class InsetsSourceConsumer {
hideTypes[0] |= toPublicType(getType());
}
} else {
- // We are gaining control, but don't need to run an animation.
- // However make sure that the leash visibility is still up to date.
- if (applyLocalVisibilityOverride()) {
- mController.notifyVisibilityChanged();
- }
- applyHiddenToControl();
+ // We are gaining control, but don't need to run an animation.
+ // However make sure that the leash visibility is still up to date.
+ if (applyLocalVisibilityOverride()) {
+ mController.notifyVisibilityChanged();
+ applyHiddenToControl();
+ }
}
}
if (lastControl != null) {
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index a106b2c4726d..0283ada0dd40 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -108,6 +108,14 @@ public class PendingInsetsController implements WindowInsetsController {
}
@Override
+ public boolean isRequestedVisible(int type) {
+
+ // Method is only used once real insets controller is attached, so no need to traverse
+ // requests here.
+ return InsetsState.getDefaultVisibility(type);
+ }
+
+ @Override
public void addOnControllableInsetsChangedListener(
OnControllableInsetsChangedListener listener) {
if (mReplayedInsetsController != null) {
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 439223cf568b..3d348efc7f0f 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.graphics.Insets;
import android.inputmethodservice.InputMethodService;
import android.os.CancellationSignal;
+import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.animation.Interpolator;
@@ -226,6 +227,13 @@ public interface WindowInsetsController {
InsetsState getState();
/**
+ * @return Whether the specified insets source is currently requested to be visible by the
+ * application.
+ * @hide
+ */
+ boolean isRequestedVisible(@InternalInsetsType int type);
+
+ /**
* Adds a {@link OnControllableInsetsChangedListener} to the window insets controller.
*
* @param listener The listener to add.
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index d2508f3616e4..71cf5cad316e 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -120,6 +120,7 @@ import com.android.internal.widget.DecorCaptionView;
import com.android.internal.widget.FloatingToolbar;
import java.util.List;
+import java.util.function.Function;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -1101,7 +1102,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
final WindowInsetsController controller = getWindowInsetsController();
- final InsetsState state = controller != null ? controller.getState() : null;
// IME is an exceptional floating window that requires color view.
final boolean isImeWindow =
@@ -1151,7 +1151,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
0 /* sideInset */, animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds, state);
+ mForceWindowDrawsBarBackgrounds, controller);
boolean oldDrawLegacy = mDrawLegacyNavigationBarBackground;
mDrawLegacyNavigationBarBackground = mNavigationColorViewState.visible
&& (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
@@ -1172,7 +1172,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
calculateStatusBarColor(), 0, mLastTopInset,
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds, state);
+ mForceWindowDrawsBarBackgrounds, controller);
if (mHasCaption) {
final int captionColor = calculateStatusBarColor();
@@ -1193,7 +1193,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION to indicate whether the app wants to handle it by
// themselves.
boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
- || !(state == null || state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+ || !(controller == null || controller.isRequestedVisible(ITYPE_NAVIGATION_BAR));
boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds
&& (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
@@ -1214,7 +1214,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// fullscreen, as othrewise we can expect the app to handle it.
boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
|| (attrs.flags & FLAG_FULLSCREEN) != 0
- || !(state == null || state.getSource(ITYPE_STATUS_BAR).isVisible());
+ || !(controller == null || controller.isRequestedVisible(ITYPE_STATUS_BAR));
boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
@@ -1354,10 +1354,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
*/
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin,
- boolean animate, boolean force, InsetsState insetsState) {
+ boolean animate, boolean force, WindowInsetsController controller) {
state.present = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
? state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force)
- : state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
+ : state.attributes.isPresent(
+ controller.isRequestedVisible(state.attributes.insetsType),
+ mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
mWindow.getAttributes().flags, force);
boolean showView = show && !isResizing() && !mHasCaption && size > 0;
@@ -2624,8 +2626,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|| force);
}
- public boolean isPresent(InsetsState state, int windowFlags, boolean force) {
- return (state == null || state.getSource(insetsType).isVisible())
+ public boolean isPresent(boolean requestedVisible, int windowFlags, boolean force) {
+ return requestedVisible
&& ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || force);
}
@@ -2642,7 +2644,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
public boolean isVisible(InsetsState state, int color, int windowFlags, boolean force) {
- final boolean present = isPresent(state, windowFlags, force);
+ final boolean present = isPresent(state.getSource(insetsType).isVisible(), windowFlags,
+ force);
return isVisible(present, color, windowFlags, force);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index fda70d14db2b..b2f5988719cf 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -77,6 +77,9 @@ class InsetsPolicy {
/** Updates the target which can control system bars. */
void updateBarControlTarget(@Nullable WindowState focusedWin) {
+ if (mFocusedWin != focusedWin){
+ abortTransient();
+ }
mFocusedWin = focusedWin;
mStateController.onBarControlTargetChanged(getStatusControlTarget(focusedWin),
getFakeStatusControlTarget(focusedWin),
@@ -123,11 +126,13 @@ class InsetsPolicy {
mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
mShowingTransientTypes.toArray());
updateBarControlTarget(mFocusedWin);
+ InsetsState state = new InsetsState(mStateController.getRawInsetsState());
startAnimation(true /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mStateController.notifyInsetsChanged();
}
- });
+ }, state);
+ mStateController.onInsetsModified(mDummyControlTarget, state);
}
}
@@ -135,13 +140,15 @@ class InsetsPolicy {
if (mShowingTransientTypes.size() == 0) {
return;
}
+ InsetsState state = new InsetsState(mStateController.getRawInsetsState());
startAnimation(false /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mShowingTransientTypes.clear();
mStateController.notifyInsetsChanged();
updateBarControlTarget(mFocusedWin);
}
- });
+ }, state);
+ mStateController.onInsetsModified(mDummyControlTarget, state);
}
boolean isTransient(@InternalInsetsType int type) {
@@ -152,14 +159,22 @@ class InsetsPolicy {
* @see InsetsStateController#getInsetsForDispatch
*/
InsetsState getInsetsForDispatch(WindowState target) {
- InsetsState state = mStateController.getInsetsForDispatch(target);
+ InsetsState originalState = mStateController.getInsetsForDispatch(target);
+ InsetsState state = originalState;
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ state = new InsetsState(state);
state.setSourceVisible(mShowingTransientTypes.get(i), false);
}
if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) {
+ if (state == originalState) {
+ state = new InsetsState(state);
+ }
state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState());
}
if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) {
+ if (state == originalState) {
+ state = new InsetsState(state);
+ }
state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState());
}
return state;
@@ -206,6 +221,13 @@ class InsetsPolicy {
}
}
+ private void abortTransient() {
+ mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
+ mShowingTransientTypes.toArray());
+ mShowingTransientTypes.clear();
+ updateBarControlTarget(mFocusedWin);
+ }
+
private @Nullable InsetsControlTarget getFakeStatusControlTarget(
@Nullable WindowState focused) {
return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null;
@@ -286,19 +308,20 @@ class InsetsPolicy {
}
@VisibleForTesting
- void startAnimation(boolean show, Runnable callback) {
+ void startAnimation(boolean show, Runnable callback, InsetsState state) {
int typesReady = 0;
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
final IntArray showingTransientTypes = mShowingTransientTypes;
for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
- InsetsSourceProvider provider =
- mStateController.getSourceProvider(showingTransientTypes.get(i));
+ int type = showingTransientTypes.get(i);
+ InsetsSourceProvider provider = mStateController.getSourceProvider(type);
InsetsSourceControl control = provider.getControl(mDummyControlTarget);
if (control == null || control.getLeash() == null) {
continue;
}
- typesReady |= InsetsState.toPublicType(showingTransientTypes.get(i));
+ typesReady |= InsetsState.toPublicType(type);
controls.put(control.getType(), new InsetsSourceControl(control));
+ state.setSourceVisible(type, show);
}
controlAnimationUnchecked(typesReady, controls, show, callback);
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index ada6d4710967..cb0d8536fe72 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -259,10 +259,13 @@ class InsetsSourceProvider {
if (target == null) {
// Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
mWin.cancelAnimation();
+ setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
return;
}
mAdapter = new ControlAdapter();
- setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
+ if (getSource().getType() == ITYPE_IME) {
+ setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
+ }
final Transaction t = mDisplayContent.getPendingTransaction();
mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */,
ANIMATION_TYPE_INSETS_CONTROL, null /* animationFinishedCallback */);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c4d700c9aca3..47b8208ad527 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3968,7 +3968,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
pw.println(prefix + "isOnScreen=" + isOnScreen());
pw.println(prefix + "isVisible=" + isVisible());
- pw.println(prefix + "mEmbeddedDisplayContents=" + mEmbeddedDisplayContents);
+ if (!mEmbeddedDisplayContents.isEmpty()) {
+ pw.println(prefix + "mEmbeddedDisplayContents=" + mEmbeddedDisplayContents);
+ }
+ if (dumpAll) {
+ pw.println(prefix + "mRequestedInsetsState: " + mRequestedInsetsState);
+ }
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 5e30477e1e3f..b21ea796396c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
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 android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -29,13 +30,18 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
import android.util.IntArray;
@@ -164,45 +170,51 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+
+ doAnswer(invocation -> {
+ ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_STATUS_BAR, true);
+ ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_NAVIGATION_BAR, true);
+ return null;
+ }).when(policy).startAnimation(anyBoolean(), any(), any());
+
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
final InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both fake controls.
assertEquals(2, controls.length);
for (int i = controls.length - 1; i >= 0; i--) {
assertNull(controls[i].getLeash());
}
+
+ assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_STATUS_BAR).isVisible());
+ assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_NAVIGATION_BAR).isVisible());
}
@Test
public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() {
- // Adding app window before setting source visibility is to prevent the visibility from
- // being cleared by InsetsSourceProvider.updateVisibility.
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
-
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
final InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get the fake control of the status bar, and must get the real control of the
// navigation bar.
@@ -219,19 +231,18 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both fake controls.
assertEquals(2, controls.length);
@@ -239,12 +250,12 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertNull(controls[i].getLeash());
}
- final InsetsState state = policy.getInsetsForDispatch(app);
+ final InsetsState state = policy.getInsetsForDispatch(mAppWindow);
state.setSourceVisible(ITYPE_STATUS_BAR, true);
state.setSourceVisible(ITYPE_NAVIGATION_BAR, true);
- policy.onInsetsModified(app, state);
+ policy.onInsetsModified(mAppWindow, state);
- controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both real controls.
assertEquals(2, controls.length);
@@ -253,6 +264,33 @@ public class InsetsPolicyTest extends WindowTestsBase {
}
}
+ @Test
+ public void testShowTransientBars_abortsWhenControlTargetChanges() {
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+ final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
+
+ final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(app);
+ policy.showTransient(
+ IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ final InsetsSourceControl[] controls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ policy.updateBarControlTarget(app2);
+ assertFalse(policy.isTransient(ITYPE_STATUS_BAR));
+ assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+ }
+
+ private WindowState addNonFocusableWindow(int type, String name) {
+ WindowState win = addWindow(type, name);
+ win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ return win;
+ }
+
private WindowState addWindow(int type, String name) {
final WindowState win = createWindow(null, type, name);
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 2164de9ea191..67d4016dbd73 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -41,6 +41,7 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -87,7 +88,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
0 /* systemUiVisibility */, false /* isTranslucent */);
mSurface = new TaskSnapshotSurface(mWm, new Window(), new SurfaceControl(), snapshot, "Test",
createTaskDescription(Color.WHITE, Color.RED, Color.BLUE), sysuiVis, windowFlags, 0,
- taskBounds, ORIENTATION_PORTRAIT, null /* insetsState */);
+ taskBounds, ORIENTATION_PORTRAIT, new InsetsState());
}
private static TaskDescription createTaskDescription(int background, int statusBar,