summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tiger Huang <tigerhuang@google.com> 2020-02-05 17:10:03 +0800
committer Tiger Huang <tigerhuang@google.com> 2020-02-07 18:19:21 +0800
commita1663403045248f94e88fb6d9558dc589d86114e (patch)
treecc18c772dd4e1e1be720ab49833ed6745549c54e
parentbe5015b00aee39ff6956701942dca2383bdff13c (diff)
Refine logic about controlling transient bars
- Use copied InsetsSourceControl to prevent the leash from being released while the control gets revoked while playing transient bar animations. - Start the animation after mAnimationControl gets assigned to prevent NullPointerException. - Let SystemUI to change the bar mode to transient mode before WM plays the transient bar animation. - Remove a redundunt call to the super method. - Fix InsetsPolicyTest - Fix InsetsStateControllerTest - Fix misc things Bug: 118118435 Test: Manually swipe to show transient bars many times. Test: atest InsetsSourceProviderTest InsetsStateControllerTest InsetsPolicyTest WindowStateTests CommandQueueTest RegisterStatusBarResultTest InsetsFlagsTest LightBarControllerTest RegisterStatusBarResultTest ViewRootImplTest DisplayPolicyInsetsTests DisplayPolicyTests TaskSnapshotSurfaceTest InsetsAnimationControlImplTest Change-Id: I7d445b7dc6f47a64048937cd439bdd5ffa7fa3a3
-rw-r--r--core/java/android/view/InsetsSource.java2
-rw-r--r--core/java/android/view/WindowInsetsController.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java40
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java16
6 files changed, 64 insertions, 42 deletions
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index d4961eab7473..6caa4fed6409 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -198,7 +198,7 @@ public class InsetsSource implements Parcelable {
return "InsetsSource: {"
+ "mType=" + InsetsState.typeToString(mType)
+ ", mFrame=" + mFrame.toShortString()
- + ", mVisible" + mVisible
+ + ", mVisible=" + mVisible
+ "}";
}
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index f501de91b3b7..ea8e73885980 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -16,8 +16,6 @@
package android.view;
-import static android.view.WindowInsets.Type.ime;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -148,7 +146,7 @@ public interface WindowInsetsController {
* @param types The {@link InsetsType}s the application has requested to control.
* @param durationMillis Duration of animation in
* {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or -1 if the
- * animation doesn't have a predetermined duration.T his value will be
+ * animation doesn't have a predetermined duration. This value will be
* passed to {@link InsetsAnimation#getDurationMillis()}
* @param interpolator The interpolator used for this animation, or {@code null} if this
* animation doesn't follow an interpolation curve. This value will be
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index d0179adadbd7..51b9916159fe 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -44,6 +44,7 @@ import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimationCallback;
import android.view.WindowInsetsAnimationControlListener;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.DisplayThread;
/**
@@ -107,11 +108,11 @@ class InsetsPolicy {
changed = true;
}
if (changed) {
- startAnimation(mShowingTransientTypes, true, () -> {
+ mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
+ mShowingTransientTypes.toArray());
+ updateBarControlTarget(mFocusedWin);
+ startAnimation(true /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
- mPolicy.getStatusBarManagerInternal().showTransient(
- mDisplayContent.getDisplayId(),
- mShowingTransientTypes.toArray());
mStateController.notifyInsetsChanged();
}
});
@@ -122,7 +123,7 @@ class InsetsPolicy {
if (mShowingTransientTypes.size() == 0) {
return;
}
- startAnimation(mShowingTransientTypes, false, () -> {
+ startAnimation(false /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mShowingTransientTypes.clear();
mStateController.notifyInsetsChanged();
@@ -268,18 +269,20 @@ class InsetsPolicy {
return isDockedStackVisible || isFreeformStackVisible || isResizing;
}
- private void startAnimation(IntArray internalTypes, boolean show, Runnable callback) {
+ @VisibleForTesting
+ void startAnimation(boolean show, Runnable callback) {
int typesReady = 0;
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
- updateBarControlTarget(mFocusedWin);
- for (int i = internalTypes.size() - 1; i >= 0; i--) {
+ final IntArray showingTransientTypes = mShowingTransientTypes;
+ for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
InsetsSourceProvider provider =
- mStateController.getSourceProvider(internalTypes.get(i));
- if (provider == null) continue;
- InsetsSourceControl control = provider.getControl(provider.getControlTarget());
- if (control == null || control.getLeash() == null) continue;
- typesReady |= InsetsState.toPublicType(internalTypes.get(i));
- controls.put(control.getType(), control);
+ mStateController.getSourceProvider(showingTransientTypes.get(i));
+ InsetsSourceControl control = provider.getControl(mTransientControlTarget);
+ if (control == null || control.getLeash() == null) {
+ continue;
+ }
+ typesReady |= InsetsState.toPublicType(showingTransientTypes.get(i));
+ controls.put(control.getType(), new InsetsSourceControl(control));
}
controlAnimationUnchecked(typesReady, controls, show, callback);
}
@@ -335,7 +338,6 @@ class InsetsPolicy {
private InsetsPolicyAnimationControlListener mListener;
InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) {
- super();
mListener = listener;
}
@@ -353,9 +355,11 @@ class InsetsPolicy {
InsetsController.INTERPOLATOR, true,
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
+ SurfaceAnimationThread.getHandler().post(
+ () -> mListener.onReady(mAnimationControl, typesReady));
}
- /** Called on SurfaceAnimationThread lock without global WM lock held. */
+ /** Called on SurfaceAnimationThread without global WM lock held. */
@Override
public void scheduleApplyChangeInsets() {
InsetsState state = getState();
@@ -384,7 +388,7 @@ class InsetsPolicy {
return overrideState;
}
- /** Called on SurfaceAnimationThread lock without global WM lock held. */
+ /** Called on SurfaceAnimationThread without global WM lock held. */
@Override
public void applySurfaceParams(
final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
@@ -396,14 +400,12 @@ class InsetsPolicy {
t.apply();
}
- /** Called on SurfaceAnimationThread lock without global WM lock held. */
@Override
public void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
WindowInsetsAnimationCallback.InsetsAnimation animation,
WindowInsetsAnimationCallback.AnimationBounds bounds,
int layoutDuringAnimation) {
- SurfaceAnimationThread.getHandler().post(() -> listener.onReady(controller, types));
}
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index caaa4305406c..2d7d3f18c101 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -89,6 +90,12 @@ class InsetsStateController {
if (type == ITYPE_NAVIGATION_BAR) {
state.removeSource(ITYPE_IME);
state.removeSource(ITYPE_STATUS_BAR);
+ state.removeSource(ITYPE_CAPTION_BAR);
+ }
+
+ // Status bar doesn't get influenced by caption bar
+ if (type == ITYPE_STATUS_BAR) {
+ state.removeSource(ITYPE_CAPTION_BAR);
}
// IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
@@ -212,18 +219,18 @@ class InsetsStateController {
/**
* Called when the focused window that is able to control the system bars changes.
*
- * @param topControlling The target that is now able to control the top bar appearance
- * and visibility.
+ * @param statusControlling The target that is now able to control the status bar appearance
+ * and visibility.
* @param navControlling The target that is now able to control the nav bar appearance
* and visibility.
*/
- void onBarControlTargetChanged(@Nullable InsetsControlTarget topControlling,
- @Nullable InsetsControlTarget fakeTopControlling,
+ void onBarControlTargetChanged(@Nullable InsetsControlTarget statusControlling,
+ @Nullable InsetsControlTarget fakeStatusControlling,
@Nullable InsetsControlTarget navControlling,
@Nullable InsetsControlTarget fakeNavControlling) {
- onControlChanged(ITYPE_STATUS_BAR, topControlling);
+ onControlChanged(ITYPE_STATUS_BAR, statusControlling);
onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
- onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeTopControlling);
+ onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
notifyPendingInsetsControlChanged();
}
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 e71225579989..eae007d3a767 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -29,12 +29,13 @@ 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 com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
import android.platform.test.annotations.Presubmit;
import android.util.IntArray;
@@ -122,13 +123,13 @@ public class InsetsPolicyTest extends WindowTestsBase {
// TODO: adjust this test if we pretend to the app that it's still able to control it.
@Test
public void testControlsForDispatch_forceStatusBarVisible() {
- addWindow(TYPE_STATUS_BAR, "topBar").mAttrs.privateFlags |=
+ addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |=
PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
- // The app must not control the top bar.
+ // The app must not control the status bar.
assertNotNull(controls);
assertEquals(1, controls.length);
}
@@ -137,6 +138,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
public void testControlsForDispatch_statusBarForceShowNavigation() {
addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |=
PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+ addWindow(TYPE_STATUS_BAR, "statusBar");
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -169,7 +171,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
.getControllableInsetProvider().getSource().setVisible(false);
final WindowState app = addWindow(TYPE_APPLICATION, "app");
- final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(app);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
@@ -184,7 +187,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
}
@Test
- public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+ 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");
@@ -194,14 +197,15 @@ public class InsetsPolicyTest extends WindowTestsBase {
addWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
- final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(app);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
- // The app must get the fake control of the top bar, and must get the real control of the
+ // The app must get the fake control of the status bar, and must get the real control of the
// navigation bar.
assertEquals(2, controls.length);
for (int i = controls.length - 1; i >= 0; i--) {
@@ -222,7 +226,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
.getControllableInsetProvider().getSource().setVisible(false);
final WindowState app = addWindow(TYPE_APPLICATION, "app");
- final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(app);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
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 39cdd2cb907e..5cf1fbbacaf4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -20,7 +20,9 @@ import static android.view.InsetsState.ITYPE_IME;
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.TYPE_APPLICATION;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
@@ -33,14 +35,14 @@ import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
@SmallTest
@FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
@Presubmit
@@ -88,6 +90,10 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
+
+ // IME cannot be the IME target.
+ ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
@@ -98,6 +104,10 @@ public class InsetsStateControllerTest extends WindowTestsBase {
public void testImeForDispatch() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
+
+ // IME cannot be the IME target.
+ ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+
InsetsSourceProvider statusBarProvider =
getController().getSourceProvider(ITYPE_STATUS_BAR);
statusBarProvider.setWindow(statusBar, null, ((displayFrames, windowState, rect) ->