diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index d16c019769b08..8b39e5c24ded0 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -542,7 +542,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return mNavigationBarView; } - public View createView(Bundle savedState) { + public View createView(Bundle savedState, boolean initialVisibility) { mFrame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate( R.layout.navigation_bar_window, null); View barView = LayoutInflater.from(mFrame.getContext()).inflate( @@ -550,6 +550,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, barView.addOnAttachStateChangeListener(this); mNavigationBarView = barView.findViewById(R.id.navigation_bar_view); + mNavigationBarView.setVisibility(initialVisibility ? View.VISIBLE : View.INVISIBLE); + if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + barView); mWindowManager.addView(mFrame, getBarLayoutParams(mContext.getResources().getConfiguration().windowConfiguration diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 98b49b1c48903..21eeeb34f3bbe 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -58,6 +58,7 @@ import com.android.systemui.statusbar.CommandQueue.Callbacks; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode; import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; @@ -84,6 +85,7 @@ public class NavigationBarController implements private final NavigationBar.Factory mNavigationBarFactory; private final DisplayManager mDisplayManager; private final TaskbarDelegate mTaskbarDelegate; + private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private int mNavMode; @VisibleForTesting boolean mIsTablet; @@ -107,6 +109,7 @@ public class NavigationBarController implements NavBarHelper navBarHelper, TaskbarDelegate taskbarDelegate, NavigationBar.Factory navigationBarFactory, + StatusBarKeyguardViewManager statusBarKeyguardViewManager, DumpManager dumpManager, AutoHideController autoHideController, LightBarController lightBarController, @@ -121,6 +124,7 @@ public class NavigationBarController implements mConfigChanges.applyNewConfig(mContext.getResources()); mNavMode = navigationModeController.addListener(this); mTaskbarDelegate = taskbarDelegate; + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService, navBarHelper, navigationModeController, sysUiFlagsContainer, dumpManager, autoHideController, lightBarController, pipOptional, @@ -320,7 +324,8 @@ public class NavigationBarController implements mNavigationBars.put(displayId, navBar); - View navigationBarView = navBar.createView(savedState); + boolean navBarVisible = mStatusBarKeyguardViewManager.isNavBarVisible(); + View navigationBarView = navBar.createView(savedState, navBarVisible); navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index d42a42364f213..11d9c311fb6c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -68,10 +68,13 @@ import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.unfold.FoldAodAnimationController; +import com.android.systemui.unfold.SysUIUnfoldComponent; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Objects; +import java.util.Optional; import javax.inject.Inject; @@ -87,7 +90,7 @@ import dagger.Lazy; public class StatusBarKeyguardViewManager implements RemoteInputController.Callback, StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener, PanelExpansionListener, NavigationModeController.ModeChangedListener, - KeyguardViewController { + KeyguardViewController, FoldAodAnimationController.FoldAodAnimationStatus { // When hiding the Keyguard with timing supplied from WindowManager, better be early than late. private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3; @@ -113,6 +116,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private final KeyguardBouncer.Factory mKeyguardBouncerFactory; private final KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory; private final DreamOverlayStateController mDreamOverlayStateController; + @Nullable + private final FoldAodAnimationController mFoldAodAnimationController; private KeyguardMessageAreaController mKeyguardMessageAreaController; private final Lazy mShadeController; private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { @@ -186,6 +191,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private boolean mPulsing; private boolean mGesturalNav; private boolean mIsDocked; + private boolean mScreenOffAnimationPlaying; protected boolean mFirstUpdate = true; protected boolean mLastShowing; @@ -199,6 +205,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private boolean mLastIsDocked; private boolean mLastPulsing; private int mLastBiometricMode; + private boolean mLastScreenOffAnimationPlaying; private boolean mQsExpanded; private OnDismissAction mAfterKeyguardGoneAction; @@ -246,6 +253,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb NotificationMediaManager notificationMediaManager, KeyguardBouncer.Factory keyguardBouncerFactory, KeyguardMessageAreaController.Factory keyguardMessageAreaFactory, + Optional sysUIUnfoldComponent, Lazy shadeController, LatencyTracker latencyTracker) { mContext = context; @@ -264,6 +272,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mKeyguardMessageAreaFactory = keyguardMessageAreaFactory; mShadeController = shadeController; mLatencyTracker = latencyTracker; + mFoldAodAnimationController = sysUIUnfoldComponent + .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null); } @Override @@ -317,6 +327,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mConfigurationController.addCallback(this); mGesturalNav = QuickStepContract.isGesturalMode( mNavigationModeController.addListener(this)); + if (mFoldAodAnimationController != null) { + mFoldAodAnimationController.addCallback(this); + } if (mDockManager != null) { mDockManager.addListener(mDockEventListener); mIsDocked = mDockManager.isDocked(); @@ -965,6 +978,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { @Override public void run() { + NavigationBarView view = mStatusBar.getNavigationBarView(); + if (view != null) { + view.setVisibility(View.VISIBLE); + } mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() .show(navigationBars()); } @@ -1019,6 +1036,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mLastRemoteInputActive = remoteInputActive; mLastDozing = mDozing; mLastPulsing = mPulsing; + mLastScreenOffAnimationPlaying = mScreenOffAnimationPlaying; mLastBiometricMode = mBiometricUnlockController.getMode(); mLastGesturalNav = mGesturalNav; mLastIsDocked = mIsDocked; @@ -1054,14 +1072,15 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb /** * @return Whether the navigation bar should be made visible based on the current state. */ - protected boolean isNavBarVisible() { - int biometricMode = mBiometricUnlockController.getMode(); + public boolean isNavBarVisible() { + boolean isWakeAndUnlockPulsing = mBiometricUnlockController != null + && mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; boolean keyguardShowing = mShowing && !mOccluded; - boolean hideWhileDozing = mDozing && biometricMode != MODE_WAKE_AND_UNLOCK_PULSING; + boolean hideWhileDozing = mDozing && !isWakeAndUnlockPulsing; boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked) && mGesturalNav; - return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing() - || mRemoteInputActive || keyguardWithGestureNav + return (!keyguardShowing && !hideWhileDozing && !mScreenOffAnimationPlaying + || mBouncer.isShowing() || mRemoteInputActive || keyguardWithGestureNav || mGlobalActionsVisible); } @@ -1073,8 +1092,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING; boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing || mLastPulsing && !mLastIsDocked) && mLastGesturalNav; - return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing - || mLastRemoteInputActive || keyguardWithGestureNav + return (!keyguardShowing && !hideWhileDozing && !mLastScreenOffAnimationPlaying + || mLastBouncerShowing || mLastRemoteInputActive || keyguardWithGestureNav || mLastGlobalActionsVisible); } @@ -1224,6 +1243,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb setDozing(isDozing); } + @Override + public void onFoldToAodAnimationChanged() { + if (mFoldAodAnimationController != null) { + mScreenOffAnimationPlaying = mFoldAodAnimationController.shouldPlayAnimation(); + } + } + /** * Whether qs is currently expanded. */ diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt index 2e627a872c247..2a9076e8f848d 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt @@ -48,17 +48,17 @@ constructor( private var pendingScrimReadyCallback: Runnable? = null private var shouldPlayAnimation = false + private var isAnimationPlaying = false + private val statusListeners = arrayListOf() private val startAnimationRunnable = Runnable { statusBar.notificationPanelViewController.startFoldToAodAnimation { // End action - isAnimationPlaying = false + setAnimationState(playing = false) } } - private var isAnimationPlaying = false - override fun initialize(statusBar: StatusBar, lightRevealScrim: LightRevealScrim) { this.statusBar = statusBar @@ -71,17 +71,13 @@ constructor( override fun startAnimation(): Boolean = if (alwaysOnEnabled && wakefulnessLifecycle.lastSleepReason == PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD && - globalSettings.getString(Settings.Global.ANIMATOR_DURATION_SCALE) != "0") { - shouldPlayAnimation = true - - isAnimationPlaying = true + globalSettings.getString(Settings.Global.ANIMATOR_DURATION_SCALE) != "0" + ) { + setAnimationState(playing = true) statusBar.notificationPanelViewController.prepareFoldToAodAnimation() - - statusListeners.forEach(FoldAodAnimationStatus::onFoldToAodAnimationChanged) - true } else { - shouldPlayAnimation = false + setAnimationState(playing = false) false } @@ -91,8 +87,13 @@ constructor( statusBar.notificationPanelViewController.cancelFoldToAodAnimation(); } - shouldPlayAnimation = false - isAnimationPlaying = false + setAnimationState(playing = false) + } + + private fun setAnimationState(playing: Boolean) { + shouldPlayAnimation = playing + isAnimationPlaying = playing + statusListeners.forEach(FoldAodAnimationStatus::onFoldToAodAnimationChanged) } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java index 73d2b0bf1a0f9..bb42c1277b904 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -46,6 +46,7 @@ import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; @@ -90,6 +91,7 @@ public class NavigationBarControllerTest extends SysuiTestCase { mock(NavBarHelper.class), mock(TaskbarDelegate.class), mNavigationBarFactory, + mock(StatusBarKeyguardViewManager.class), mock(DumpManager.class), mock(AutoHideController.class), mock(LightBarController.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 090ce436340bc..48d38571cf3c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -28,6 +28,7 @@ import static android.view.WindowInsets.Type.ime; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS; import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -228,7 +229,8 @@ public class NavigationBarTest extends SysuiTestCase { @Test public void testHomeLongPress() { - mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); + mNavigationBar.onViewAttachedToWindow(mNavigationBar + .createView(null, /* initialVisibility= */ true)); mNavigationBar.onHomeLongClick(mNavigationBar.getView()); verify(mUiEventLogger, times(1)).log(NAVBAR_ASSIST_LONGPRESS); @@ -241,7 +243,8 @@ public class NavigationBarTest extends SysuiTestCase { .setLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 100) .build()); when(mNavBarHelper.getLongPressHomeEnabled()).thenReturn(true); - mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); + mNavigationBar.onViewAttachedToWindow(mNavigationBar + .createView(null, /* initialVisibility= */ true)); mNavigationBar.onHomeTouch(mNavigationBar.getView(), MotionEvent.obtain( /*downTime=*/SystemClock.uptimeMillis(), @@ -263,7 +266,8 @@ public class NavigationBarTest extends SysuiTestCase { @Test public void testRegisteredWithDispatcher() { - mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); + mNavigationBar.onViewAttachedToWindow(mNavigationBar + .createView(null, /* initialVisibility= */ true)); verify(mBroadcastDispatcher).registerReceiverWithHandler( any(BroadcastReceiver.class), any(IntentFilter.class), @@ -283,8 +287,8 @@ public class NavigationBarTest extends SysuiTestCase { doReturn(true).when(mockShadeWindowView).isAttachedToWindow(); doNothing().when(defaultNavBar).checkNavBarModes(); doNothing().when(externalNavBar).checkNavBarModes(); - defaultNavBar.createView(null); - externalNavBar.createView(null); + defaultNavBar.createView(null, /* initialVisibility= */ true); + externalNavBar.createView(null, /* initialVisibility= */ true); defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true); @@ -318,7 +322,7 @@ public class NavigationBarTest extends SysuiTestCase { doReturn(mockShadeWindowView).when(mStatusBar).getNotificationShadeWindowView(); doReturn(true).when(mockShadeWindowView).isAttachedToWindow(); doNothing().when(mNavigationBar).checkNavBarModes(); - mNavigationBar.createView(null); + mNavigationBar.createView(null, /* initialVisibility= */ true); WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build(); doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets(); @@ -354,7 +358,7 @@ public class NavigationBarTest extends SysuiTestCase { @Test public void testA11yEventAfterDetach() { - View v = mNavigationBar.createView(null); + View v = mNavigationBar.createView(null, /* initialVisibility= */ true); mNavigationBar.onViewAttachedToWindow(v); verify(mNavBarHelper).registerNavTaskStateUpdater(any( NavBarHelper.NavbarTaskbarStateUpdater.class)); @@ -366,6 +370,20 @@ public class NavigationBarTest extends SysuiTestCase { mNavigationBar.updateAccessibilityStateFlags(); } + @Test + public void testCreateView_initiallyVisible_viewIsVisible() { + mNavigationBar.createView(null, /* initialVisibility= */ true); + + assertThat(mNavigationBar.getView().getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void testCreateView_initiallyNotVisible_viewIsNotVisible() { + mNavigationBar.createView(null, /* initialVisibility= */ false); + + assertThat(mNavigationBar.getView().getVisibility()).isEqualTo(View.INVISIBLE); + } + private NavigationBar createNavBar(Context context) { DeviceProvisionedController deviceProvisionedController = mock(DeviceProvisionedController.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 107ba8130349d..8b93de571cc9a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -53,6 +53,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.unfold.SysUIUnfoldComponent; import org.junit.Before; import org.junit.Test; @@ -60,6 +61,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -100,6 +103,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { @Mock private ShadeController mShadeController; @Mock + private SysUIUnfoldComponent mSysUiUnfoldComponent; + @Mock private DreamOverlayStateController mDreamOverlayStateController; @Mock private LatencyTracker mLatencyTracker; @@ -130,6 +135,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mock(NotificationMediaManager.class), mKeyguardBouncerFactory, mKeyguardMessageAreaFactory, + Optional.of(mSysUiUnfoldComponent), () -> mShadeController, mLatencyTracker); mStatusBarKeyguardViewManager.registerStatusBar(