From 593266739fbe703abdfada8ab7735df323ca2dc8 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 21 Jan 2022 11:38:20 -0800 Subject: [PATCH] Group window relayout requests Various places in sysui might call into NotificationShadeWindowController. Some of these calls can lead to relayoutWindow(), which is quite expensive. We should group these calls, and execute them in batch. Test: manual Test: perfetto trace Test: atest NotificationPanelViewControllerTest Test: atest NotificationShadeWindowControllerImplTest Fixes: 190382751 Bug: 210432290 Change-Id: Ib08f7ba66048eb023ee2d5e9c09461381c390f0d --- .../keyguard/KeyguardViewMediator.java | 28 +++++++--- .../keyguard/dagger/KeyguardModule.java | 7 ++- .../NotificationShadeWindowController.java | 9 +++ .../NotificationPanelViewController.java | 3 + ...NotificationShadeWindowControllerImpl.java | 26 ++++++++- .../statusbar/phone/PanelViewController.java | 56 ++++++++++--------- .../systemui/statusbar/phone/StatusBar.java | 38 +++++++------ .../keyguard/KeyguardViewMediatorTest.java | 7 ++- .../NotificationPanelViewControllerTest.java | 11 +++- ...ficationShadeWindowControllerImplTest.java | 14 +++++ 10 files changed, 139 insertions(+), 60 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 08e1654c8dbf9..701d1391d2711 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -113,6 +113,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; @@ -318,6 +319,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, // the properties of the keyguard private final KeyguardUpdateMonitor mUpdateMonitor; + private final Lazy mNotificationShadeWindowControllerLazy; /** * Last SIM state reported by the telephony system. @@ -833,7 +835,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, ScreenOffAnimationController screenOffAnimationController, Lazy notificationShadeDepthController, ScreenOnCoordinator screenOnCoordinator, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + Lazy notificationShadeWindowControllerLazy) { super(context); mFalsingCollector = falsingCollector; mLockPatternUtils = lockPatternUtils; @@ -850,6 +853,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, dumpManager.registerDumpable(getClass().getName(), this); mDeviceConfig = deviceConfig; mScreenOnCoordinator = screenOnCoordinator; + mNotificationShadeWindowControllerLazy = notificationShadeWindowControllerLazy; mShowHomeOverLockscreen = mDeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, @@ -1837,10 +1841,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, Trace.beginSection( "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM"); StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj; - handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration, - params.mApps, params.mWallpapers, params.mNonApps, - params.mFinishedCallback); - mFalsingCollector.onSuccessfulUnlock(); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams( + () -> { + handleStartKeyguardExitAnimation(params.startTime, + params.fadeoutDuration, + params.mApps, params.mWallpapers, params.mNonApps, + params.mFinishedCallback); + mFalsingCollector.onSuccessfulUnlock(); + }); Trace.endSection(); break; case CANCEL_KEYGUARD_EXIT_ANIM: @@ -2139,10 +2147,12 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, mKeyguardGoingAwayRunnable.run(); } else { // TODO(bc-unlock): Fill parameters - handleStartKeyguardExitAnimation( - SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), - mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, - null /* nonApps */, null /* finishedCallback */); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> { + handleStartKeyguardExitAnimation( + SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), + mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, + null /* nonApps */, null /* finishedCallback */); + }); } } Trace.endSection(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index dd844e8d49abe..f14d130936206 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -44,6 +44,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardLiftController; @@ -98,7 +99,8 @@ public class KeyguardModule { ScreenOffAnimationController screenOffAnimationController, Lazy notificationShadeDepthController, ScreenOnCoordinator screenOnCoordinator, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + Lazy notificationShadeWindowController) { return new KeyguardViewMediator( context, falsingCollector, @@ -122,7 +124,8 @@ public class KeyguardModule { screenOffAnimationController, notificationShadeDepthController, screenOnCoordinator, - interactionJankMonitor + interactionJankMonitor, + notificationShadeWindowController ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index 4adf2bc836c46..ebd610bb0af44 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar; import android.graphics.Region; import android.view.ViewGroup; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; @@ -191,6 +192,14 @@ public interface NotificationShadeWindowController extends RemoteInputController */ default void setLightRevealScrimOpaque(boolean opaque) {} + /** + * Defer any application of window {@link WindowManager.LayoutParams} until {@code scope} is + * fully applied. + */ + default void batchApplyWindowLayoutParams(@NonNull Runnable scope) { + scope.run(); + } + /** * Custom listener to pipe data back to plugins about whether or not the status bar would be * collapsed if not for the plugin. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 769f689769587..57973c9b90e03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -162,6 +162,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.QsFrameTranslateController; @@ -741,6 +742,7 @@ public class NotificationPanelViewController extends PanelViewController { KeyguardStateController keyguardStateController, StatusBarStateController statusBarStateController, StatusBarWindowStateController statusBarWindowStateController, + NotificationShadeWindowController notificationShadeWindowController, DozeLog dozeLog, DozeParameters dozeParameters, CommandQueue commandQueue, VibratorHelper vibratorHelper, LatencyTracker latencyTracker, PowerManager powerManager, @@ -800,6 +802,7 @@ public class NotificationPanelViewController extends PanelViewController { dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, + notificationShadeWindowController, vibratorHelper, statusBarKeyguardViewManager, latencyTracker, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index c859e70e6c767..474653b9728c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -111,6 +111,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final SysuiColorExtractor mColorExtractor; private final ScreenOffAnimationController mScreenOffAnimationController; private float mFaceAuthDisplayBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + /** + * Layout params would be aggregated and dispatched all at once if this is > 0. + * + * @see #batchApplyWindowLayoutParams(Runnable) + */ + private int mDeferWindowLayoutParams; @Inject public NotificationShadeWindowControllerImpl(Context context, WindowManager windowManager, @@ -437,6 +443,20 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } } + private void applyWindowLayoutParams() { + if (mDeferWindowLayoutParams == 0 && mLp != null && mLp.copyFrom(mLpChanged) != 0) { + mWindowManager.updateViewLayout(mNotificationShadeView, mLp); + } + } + + @Override + public void batchApplyWindowLayoutParams(Runnable scope) { + mDeferWindowLayoutParams++; + scope.run(); + mDeferWindowLayoutParams--; + applyWindowLayoutParams(); + } + private void apply(State state) { applyKeyguardFlags(state); applyFocusableFlag(state); @@ -451,9 +471,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW applyHasTopUi(state); applyNotTouchable(state); applyStatusBarColorSpaceAgnosticFlag(state); - if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { - mWindowManager.updateViewLayout(mNotificationShadeView, mLp); - } + applyWindowLayoutParams(); + if (mHasTopUi != mHasTopUiChanged) { whitelistIpcs(() -> { try { @@ -739,6 +758,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW pw.println(TAG + ":"); pw.println(" mKeyguardMaxRefreshRate=" + mKeyguardMaxRefreshRate); pw.println(" mKeyguardPreferredRefreshRate=" + mKeyguardPreferredRefreshRate); + pw.println(" mDeferWindowLayoutParams=" + mDeferWindowLayoutParams); pw.println(mCurrentState); if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) { mNotificationShadeView.getViewRootImpl().dump(" ", pw); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 05ac2a35c7777..54d0b0351a8f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -57,6 +57,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; @@ -180,6 +181,7 @@ public abstract class PanelViewController { private boolean mExpandLatencyTracking; private final PanelView mView; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + private final NotificationShadeWindowController mNotificationShadeWindowController; protected final Resources mResources; protected final KeyguardStateController mKeyguardStateController; protected final SysuiStatusBarStateController mStatusBarStateController; @@ -222,6 +224,7 @@ public abstract class PanelViewController { DozeLog dozeLog, KeyguardStateController keyguardStateController, SysuiStatusBarStateController statusBarStateController, + NotificationShadeWindowController notificationShadeWindowController, VibratorHelper vibratorHelper, StatusBarKeyguardViewManager statusBarKeyguardViewManager, LatencyTracker latencyTracker, @@ -263,6 +266,7 @@ public abstract class PanelViewController { mResources = mView.getResources(); mKeyguardStateController = keyguardStateController; mStatusBarStateController = statusBarStateController; + mNotificationShadeWindowController = notificationShadeWindowController; mFlingAnimationUtils = flingAnimationUtilsBuilder .reset() .setMaxLengthSeconds(0.6f) @@ -760,34 +764,36 @@ public abstract class PanelViewController { if (isNaN(h)) { Log.wtf(TAG, "ExpandedHeight set to NaN"); } - if (mExpandLatencyTracking && h != 0f) { - DejankUtils.postAfterTraversal( - () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); - mExpandLatencyTracking = false; - } - float maxPanelHeight = getMaxPanelHeight(); - if (mHeightAnimator == null) { - if (mTracking) { - float overExpansionPixels = Math.max(0, h - maxPanelHeight); - setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + if (mExpandLatencyTracking && h != 0f) { + DejankUtils.postAfterTraversal( + () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); + mExpandLatencyTracking = false; + } + float maxPanelHeight = getMaxPanelHeight(); + if (mHeightAnimator == null) { + if (mTracking) { + float overExpansionPixels = Math.max(0, h - maxPanelHeight); + setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + } + mExpandedHeight = Math.min(h, maxPanelHeight); + } else { + mExpandedHeight = h; } - mExpandedHeight = Math.min(h, maxPanelHeight); - } else { - mExpandedHeight = h; - } - // If we are closing the panel and we are almost there due to a slow decelerating - // interpolator, abort the animation. - if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { - mExpandedHeight = 0f; - if (mHeightAnimator != null) { - mHeightAnimator.end(); + // If we are closing the panel and we are almost there due to a slow decelerating + // interpolator, abort the animation. + if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { + mExpandedHeight = 0f; + if (mHeightAnimator != null) { + mHeightAnimator.end(); + } } - } - mExpandedFraction = Math.min(1f, - maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - onHeightUpdated(mExpandedHeight); - updatePanelExpansionAndVisibility(); + mExpandedFraction = Math.min(1f, + maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + onHeightUpdated(mExpandedHeight); + updatePanelExpansionAndVisibility(); + }); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index ae4a19e2b2127..2a44c5cc12e82 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3597,26 +3597,28 @@ public class StatusBar extends CoreStartable implements public void onStartedWakingUp() { String tag = "StatusBar#onStartedWakingUp"; DejankUtils.startDetectingBlockingIpcs(tag); - mDeviceInteractive = true; - mWakeUpCoordinator.setWakingUp(true); - if (!mKeyguardBypassController.getBypassEnabled()) { - mHeadsUpManager.releaseAllImmediately(); - } - updateVisibleToUser(); - updateIsKeyguard(); - mDozeServiceHost.stopDozing(); - // This is intentionally below the stopDozing call above, since it avoids that we're - // unnecessarily animating the wakeUp transition. Animations should only be enabled - // once we fully woke up. - updateRevealEffect(true /* wakingUp */); - updateNotificationPanelTouchState(); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mDeviceInteractive = true; + mWakeUpCoordinator.setWakingUp(true); + if (!mKeyguardBypassController.getBypassEnabled()) { + mHeadsUpManager.releaseAllImmediately(); + } + updateVisibleToUser(); + updateIsKeyguard(); + mDozeServiceHost.stopDozing(); + // This is intentionally below the stopDozing call above, since it avoids that we're + // unnecessarily animating the wakeUp transition. Animations should only be enabled + // once we fully woke up. + updateRevealEffect(true /* wakingUp */); + updateNotificationPanelTouchState(); - // If we are waking up during the screen off animation, we should undo making the - // expanded visible (we did that so the LightRevealScrim would be visible). - if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) { - makeExpandedInvisible(); - } + // If we are waking up during the screen off animation, we should undo making the + // expanded visible (we did that so the LightRevealScrim would be visible). + if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) { + makeExpandedInvisible(); + } + }); DejankUtils.stopDetectingBlockingIpcs(tag); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 9827d21e29b07..da8ab27d7e3d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -51,6 +51,7 @@ import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.dump.DumpManager; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; @@ -68,6 +69,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import dagger.Lazy; + @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @SmallTest @@ -94,6 +97,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock ScreenOffAnimationController mScreenOffAnimationController; private @Mock InteractionJankMonitor mInteractionJankMonitor; private @Mock ScreenOnCoordinator mScreenOnCoordinator; + private @Mock Lazy mNotificationShadeWindowControllerLazy; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -197,7 +201,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mScreenOffAnimationController, () -> mNotificationShadeDepthController, mScreenOnCoordinator, - mInteractionJankMonitor); + mInteractionJankMonitor, + mNotificationShadeWindowControllerLazy); mViewMediator.start(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 1c8b35aeaeaf5..dee88dbfe29d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -23,7 +23,6 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; -import static com.android.systemui.statusbar.notification.ViewGroupFadeHelper.reset; import static com.google.common.truth.Truth.assertThat; @@ -38,6 +37,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -120,6 +120,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.QsFrameTranslateController; @@ -365,6 +366,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { private StatusBarWindowStateController mStatusBarWindowStateController; @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock + private NotificationShadeWindowController mNotificationShadeWindowController; private Optional mSysUIUnfoldComponent = Optional.empty(); private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; @@ -490,7 +493,10 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { .thenReturn(true); when(mInteractionJankMonitor.end(anyInt())) .thenReturn(true); - reset(mView); + doAnswer(invocation -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); mMainHandler = new Handler(Looper.getMainLooper()); @@ -505,6 +511,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mCommunalStateController, mKeyguardStateController, mStatusBarStateController, mStatusBarWindowStateController, + mNotificationShadeWindowController, mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper, mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor, mCommunalSourceMonitor, mMetricsLogger, mActivityManager, mConfigurationController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java index a5651f3bd43e1..671ab597eb2a0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -225,4 +226,17 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue(); assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue(); } + + @Test + public void batchApplyWindowLayoutParams_doesNotDispatchEvents() { + mNotificationShadeWindowController.setForceDozeBrightness(true); + verify(mWindowManager).updateViewLayout(any(), any()); + + clearInvocations(mWindowManager); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mNotificationShadeWindowController.setForceDozeBrightness(false); + verify(mWindowManager, never()).updateViewLayout(any(), any()); + }); + verify(mWindowManager).updateViewLayout(any(), any()); + } }