summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tiger Huang <tigerhuang@google.com> 2020-08-03 16:13:59 +0800
committer Tiger Huang <tigerhuang@google.com> 2020-08-18 20:23:59 +0800
commita15c8443354c7b049efe716e3f41258c712ea166 (patch)
treee483b89649a68c53776865213df8ceba00e7f5fd
parenta8a2aa7765895c601a33d9ed425d19b6dac39960 (diff)
Refine system bar position restoring
The previous logic restores the system bar as long as its insets source is visible. There can be a timing issue that if the user swipes to show transient bars while an immersive app just becomes the control target but the hide-bar info haven't sent to WM yet, WM will re-show the bar incorrectly. This CL uses the requested visibility and the behavior to decide if we should restore the postion and the visibility. This CL also refines and caches the arguments of showTransient. In this way, we don't have to create the array every time while invoking that method. Fix: 161247175 Test: atest InsetsPolicyTest Change-Id: Idef314dfe6625399b88b3dacb4c74c7071453497
-rw-r--r--core/java/android/view/InsetsState.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java28
-rw-r--r--services/core/java/com/android/server/wm/InsetsControlTarget.java8
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java3
7 files changed, 38 insertions, 29 deletions
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 6b0b509932a8..593b37af26ad 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -60,6 +60,8 @@ import java.util.StringJoiner;
*/
public class InsetsState implements Parcelable {
+ public static final InsetsState EMPTY = new InsetsState();
+
/**
* Internal representation of inset source types. This is different from the public API in
* {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4f6f75d924c4..c3e01af9158b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -246,6 +246,9 @@ public class DisplayPolicy {
| View.STATUS_BAR_TRANSPARENT
| View.NAVIGATION_BAR_TRANSPARENT;
+ private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR};
+ private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR};
+
private final WindowManagerService mService;
private final Context mContext;
private final Context mUiContext;
@@ -3353,8 +3356,15 @@ public class DisplayPolicy {
return;
}
+ final InsetsState requestedState = controlTarget.getRequestedInsetsState();
+ final @InsetsType int restorePositionTypes =
+ (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ ? Type.navigationBars() : 0)
+ | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
+ ? Type.statusBars() : 0);
+
if (swipeTarget == mNavigationBar
- && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
+ && (restorePositionTypes & Type.navigationBars()) != 0) {
// Don't show status bar when swiping on already visible navigation bar.
// But restore the position of navigation bar if it has been moved by the control
// target.
@@ -3362,14 +3372,13 @@ public class DisplayPolicy {
return;
}
- int insetsTypesToShow = Type.systemBars();
-
if (controlTarget.canShowTransient()) {
- insetsTypesToShow &= ~mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
- new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
- }
- if (insetsTypesToShow != 0) {
- controlTarget.showInsets(insetsTypesToShow, false);
+ // Show transient bars if they are hidden; restore position if they are visible.
+ mDisplayContent.getInsetsPolicy().showTransient(SHOW_TYPES_FOR_SWIPE);
+ controlTarget.showInsets(restorePositionTypes, false);
+ } else {
+ // Restore visibilities and positions of system bars.
+ controlTarget.showInsets(Type.statusBars() | Type.navigationBars(), false);
}
} else {
boolean sb = mStatusBarController.checkShowTransientBarLw();
@@ -3770,8 +3779,7 @@ public class DisplayPolicy {
// we're no longer on the Keyguard and the screen is ready. We can now request the bars.
mPendingPanicGestureUptime = 0;
if (!isNavBarEmpty(vis)) {
- mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
- new int[] {ITYPE_NAVIGATION_BAR}));
+ mDisplayContent.getInsetsPolicy().showTransient(SHOW_TYPES_FOR_PANIC);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 3ffc26a7a8ad..5e7ed3f80e43 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.inputmethodservice.InputMethodService;
+import android.view.InsetsState;
import android.view.WindowInsets.Type.InsetsType;
/**
@@ -38,6 +39,13 @@ interface InsetsControlTarget {
}
/**
+ * @return The requested {@link InsetsState} of this target.
+ */
+ default InsetsState getRequestedInsetsState() {
+ return InsetsState.EMPTY;
+ }
+
+ /**
* Instructs the control target to show inset sources.
*
* @param types to specify which types of insets source window should be shown.
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index b7287e718bd6..18a25033b1e6 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -42,7 +42,6 @@ import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.ViewRootImpl;
-import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowInsetsAnimationControlListener;
@@ -153,15 +152,13 @@ class InsetsPolicy {
return provider != null && provider.hasWindow() && !provider.getSource().isVisible();
}
- @InsetsType int showTransient(IntArray types) {
- @InsetsType int showingTransientTypes = 0;
+ void showTransient(@InternalInsetsType int[] types) {
boolean changed = false;
- for (int i = types.size() - 1; i >= 0; i--) {
- final int type = types.get(i);
+ for (int i = types.length - 1; i >= 0; i--) {
+ final @InternalInsetsType int type = types[i];
if (!isHidden(type)) {
continue;
}
- showingTransientTypes |= InsetsState.toPublicType(type);
if (mShowingTransientTypes.indexOf(type) != -1) {
continue;
}
@@ -189,7 +186,6 @@ class InsetsPolicy {
}
});
}
- return showingTransientTypes;
}
void hideTransient() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d9557fa6b37a..f42310d17943 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -728,7 +728,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* @return The insets state as requested by the client, i.e. the dispatched insets state
* for which the visibilities are overridden with what the client requested.
*/
- InsetsState getRequestedInsetsState() {
+ @Override
+ public InsetsState getRequestedInsetsState() {
return mRequestedInsetsState;
}
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 555906d4c910..608305c33168 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -43,7 +43,6 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import android.platform.test.annotations.Presubmit;
-import android.util.IntArray;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
@@ -242,8 +241,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
}).when(policy).startAnimation(anyBoolean(), any(), any());
policy.updateBarControlTarget(mAppWindow);
- policy.showTransient(
- IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -271,8 +269,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
policy.updateBarControlTarget(mAppWindow);
- policy.showTransient(
- IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -301,8 +298,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
policy.updateBarControlTarget(mAppWindow);
- policy.showTransient(
- IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
waitUntilWindowAnimatorIdle();
InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -340,8 +336,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
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}));
+ policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
policy.updateBarControlTarget(app2);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 085230d35c6a..59f8cc8c3412 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -346,8 +346,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
provider.getSource().setVisible(false);
- mDisplayContent.getInsetsPolicy().showTransient(
- IntArray.wrap(new int[] { ITYPE_STATUS_BAR }));
+ mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR });
assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());