diff options
| author | 2020-02-05 17:10:03 +0800 | |
|---|---|---|
| committer | 2020-02-07 18:19:21 +0800 | |
| commit | a1663403045248f94e88fb6d9558dc589d86114e (patch) | |
| tree | cc18c772dd4e1e1be720ab49833ed6745549c54e | |
| parent | be5015b00aee39ff6956701942dca2383bdff13c (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
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) -> |