From ff7e671a891715d43848261d9ef9a1ea378d9b3f Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 4 Feb 2022 17:25:44 -0800 Subject: [PATCH] Add ability to show a low-light clock when dozing. This change introduces the hooks in SystemUI to show a low-light clock while dozing. The default is to use the AOD clock instead. Test: atest NotificationShadeWindowViewControllerTest Bug: 217755348 Change-Id: I621eddeaf4e0e5da263e1bee0595cec60bc236a9 --- .../systemui/dagger/SystemUIModule.java | 17 +++++++ .../LowLightClockController.java | 48 +++++++++++++++++++ .../statusbar/phone/DozeServiceHost.java | 2 + ...NotificationShadeWindowViewController.java | 24 +++++++++- ...tificationShadeWindowViewControllerTest.kt | 33 ++++++++++++- .../NotificationShadeWindowViewTest.java | 7 ++- 6 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockController.java diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index b96c5aee4673e..13067bf711656 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -42,6 +42,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FlagsModule; import com.android.systemui.fragments.FragmentService; import com.android.systemui.log.dagger.LogModule; +import com.android.systemui.lowlightclock.LowLightClockController; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.BcSmartspaceDataPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -86,6 +87,7 @@ import com.android.systemui.util.time.SystemClockImpl; import com.android.systemui.wallet.dagger.WalletModule; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; +import com.android.wm.shell.dagger.DynamicOverride; import java.util.Optional; import java.util.concurrent.Executor; @@ -214,4 +216,19 @@ public abstract class SystemUIModule { groupManager, entryManager, notifCollection, notifPipeline, sysUiState, notifPipelineFlags, dumpManager, sysuiMainExecutor)); } + + @BindsOptionalOf + @DynamicOverride + abstract LowLightClockController optionalLowLightClockController(); + + @SysUISingleton + @Provides + static Optional provideLowLightClockController( + @DynamicOverride Optional optionalController) { + if (optionalController.isPresent() && optionalController.get().isLowLightClockEnabled()) { + return optionalController; + } else { + return Optional.empty(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockController.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockController.java new file mode 100644 index 0000000000000..0b15f4f2feed0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockController.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.lowlightclock; + +import android.view.ViewGroup; + +/** + * A controller responsible for attaching and showing an optional low-light clock while dozing. + */ +public interface LowLightClockController { + /** + * Returns {@code true} if the low-light clock is enabled. + */ + boolean isLowLightClockEnabled(); + + /** + * Attach the low light-clock to the given parent {@link ViewGroup}. + * @param parent The parent {@link ViewGroup} to which the low-light clock view should be + * attached. + */ + void attachLowLightClockView(ViewGroup parent); + + /** + * Show or hide the low-light clock. + * @param show Whether to show the low-light clock. + * @return {@code true} if the low-light clock was shown. + */ + boolean showLowLightClock(boolean show); + + /** + * An opportunity to perform burn-in prevention. + */ + void dozeTimeTick(); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index b35e684203e14..6d7748388e143 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -214,6 +214,7 @@ public final class DozeServiceHost implements DozeHost { } mStatusBarStateController.setIsDozing(dozing); + mNotificationShadeWindowViewController.setDozing(dozing); } @Override @@ -294,6 +295,7 @@ public final class DozeServiceHost implements DozeHost { public void dozeTimeTick() { mNotificationPanel.dozeTimeTick(); mAuthController.dozeTimeTick(); + mNotificationShadeWindowViewController.dozeTimeTick(); if (mAmbientIndicationContainer instanceof DozeReceiver) { ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 4e2eb6a19d537..396703b11a42a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -36,6 +36,7 @@ import com.android.keyguard.LockIconViewController; import com.android.systemui.R; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.dock.DockManager; +import com.android.systemui.lowlightclock.LowLightClockController; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationShadeDepthController; @@ -49,6 +50,7 @@ import com.android.systemui.tuner.TunerService; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Optional; import javax.inject.Inject; @@ -84,6 +86,7 @@ public class NotificationShadeWindowViewController { private final DockManager mDockManager; private final NotificationPanelViewController mNotificationPanelViewController; private final PanelExpansionStateManager mPanelExpansionStateManager; + private final Optional mLowLightClockController; private boolean mIsTrackingBarGesture = false; @@ -101,7 +104,8 @@ public class NotificationShadeWindowViewController { NotificationStackScrollLayoutController notificationStackScrollLayoutController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, StatusBarWindowStateController statusBarWindowStateController, - LockIconViewController lockIconViewController) { + LockIconViewController lockIconViewController, + Optional lowLightClockController) { mLockscreenShadeTransitionController = transitionController; mFalsingCollector = falsingCollector; mTunerService = tunerService; @@ -115,6 +119,7 @@ public class NotificationShadeWindowViewController { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mStatusBarWindowStateController = statusBarWindowStateController; mLockIconViewController = lockIconViewController; + mLowLightClockController = lowLightClockController; // This view is not part of the newly inflated expanded status bar. mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container); @@ -171,6 +176,8 @@ public class NotificationShadeWindowViewController { }; mGestureDetector = new GestureDetector(mView.getContext(), gestureListener); + mLowLightClockController.ifPresent(controller -> controller.attachLowLightClockView(mView)); + mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() { @Override public Boolean handleDispatchTouchEvent(MotionEvent ev) { @@ -450,6 +457,21 @@ public class NotificationShadeWindowViewController { mNotificationShadeWindowController = controller; } + /** + * Tell the controller that dozing has begun or ended. + * @param dozing True if dozing has begun. + */ + public void setDozing(boolean dozing) { + mLowLightClockController.ifPresent(controller -> controller.showLowLightClock(dozing)); + } + + /** + * Tell the controller to perform burn-in prevention. + */ + public void dozeTimeTick() { + mLowLightClockController.ifPresent(LowLightClockController::dozeTimeTick); + } + @VisibleForTesting void setDragDownHelper(DragDownHelper dragDownHelper) { mDragDownHelper = dragDownHelper; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewControllerTest.kt index 12e71af6997ed..34a5d4b03dbbf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewControllerTest.kt @@ -24,6 +24,7 @@ import com.android.keyguard.LockIconViewController import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.dock.DockManager +import com.android.systemui.lowlightclock.LowLightClockController import com.android.systemui.statusbar.LockscreenShadeTransitionController import com.android.systemui.statusbar.NotificationShadeDepthController import com.android.systemui.statusbar.NotificationShadeWindowController @@ -38,11 +39,13 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers import org.mockito.Mock import org.mockito.MockitoAnnotations import org.mockito.Mockito.anyFloat import org.mockito.Mockito.never import org.mockito.Mockito.verify +import java.util.Optional import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) @@ -79,6 +82,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { private lateinit var mLockIconViewController: LockIconViewController @Mock private lateinit var mPhoneStatusBarViewController: PhoneStatusBarViewController + @Mock + private lateinit var mLowLightClockController: LowLightClockController private lateinit var mInteractionEventHandlerCaptor: ArgumentCaptor private lateinit var mInteractionEventHandler: InteractionEventHandler @@ -101,7 +106,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { stackScrollLayoutController, mStatusBarKeyguardViewManager, mStatusBarWindowStateController, - mLockIconViewController + mLockIconViewController, + Optional.of(mLowLightClockController) ) mController.setupExpandedStatusBar() mController.setService(mStatusBar, mNotificationShadeWindowController) @@ -235,6 +241,31 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { verify(mPhoneStatusBarViewController).sendTouchToView(nextEvent) assertThat(returnVal).isTrue() } + + @Test + fun testLowLightClockAttachedWhenExpandedStatusBarSetup() { + verify(mLowLightClockController).attachLowLightClockView(ArgumentMatchers.any()) + } + + @Test + fun testLowLightClockShownWhenDozing() { + mController.setDozing(true) + verify(mLowLightClockController).showLowLightClock(true) + } + + @Test + fun testLowLightClockDozeTimeTickCalled() { + mController.dozeTimeTick() + verify(mLowLightClockController).dozeTimeTick() + } + + @Test + fun testLowLightClockHiddenWhenNotDozing() { + mController.setDozing(true) + verify(mLowLightClockController).showLowLightClock(true) + mController.setDozing(false) + verify(mLowLightClockController).showLowLightClock(false) + } } private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index d885da8b738c3..6c33113ae58b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -37,6 +37,7 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.dock.DockManager; +import com.android.systemui.lowlightclock.LowLightClockController; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationShadeDepthController; @@ -56,6 +57,8 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; + @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest @@ -79,6 +82,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private StatusBarWindowStateController mStatusBarWindowStateController; @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController; @Mock private LockIconViewController mLockIconViewController; + @Mock private LowLightClockController mLowLightClockController; @Captor private ArgumentCaptor mInteractionEventHandlerCaptor; @@ -110,7 +114,8 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mNotificationStackScrollLayoutController, mStatusBarKeyguardViewManager, mStatusBarWindowStateController, - mLockIconViewController); + mLockIconViewController, + Optional.of(mLowLightClockController)); mController.setupExpandedStatusBar(); mController.setService(mStatusBar, mNotificationShadeWindowController); mController.setDragDownHelper(mDragDownHelper);