diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index ae412152b10ec..96c35d43052e1 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -20,7 +20,6 @@ import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWA import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; import android.annotation.MainThread; -import android.app.UiModeManager; import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Trace; @@ -145,10 +144,9 @@ public class DozeMachine { private final Service mDozeService; private final WakeLock mWakeLock; - private final AmbientDisplayConfiguration mConfig; + private final AmbientDisplayConfiguration mAmbientDisplayConfig; private final WakefulnessLifecycle mWakefulnessLifecycle; private final DozeHost mDozeHost; - private final UiModeManager mUiModeManager; private final DockManager mDockManager; private final Part[] mParts; @@ -156,18 +154,18 @@ public class DozeMachine { private State mState = State.UNINITIALIZED; private int mPulseReason; private boolean mWakeLockHeldForCurrentState = false; + private int mUiModeType = Configuration.UI_MODE_TYPE_NORMAL; @Inject - public DozeMachine(@WrappedService Service service, AmbientDisplayConfiguration config, + public DozeMachine(@WrappedService Service service, + AmbientDisplayConfiguration ambientDisplayConfig, WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle, - UiModeManager uiModeManager, DozeLog dozeLog, DockManager dockManager, DozeHost dozeHost, Part[] parts) { mDozeService = service; - mConfig = config; + mAmbientDisplayConfig = ambientDisplayConfig; mWakefulnessLifecycle = wakefulnessLifecycle; mWakeLock = wakeLock; - mUiModeManager = uiModeManager; mDozeLog = dozeLog; mDockManager = dockManager; mDozeHost = dozeHost; @@ -186,6 +184,18 @@ public class DozeMachine { } } + /** + * Notifies the {@link DozeMachine} that {@link Configuration} has changed. + */ + public void onConfigurationChanged(Configuration newConfiguration) { + int newUiModeType = newConfiguration.uiMode & Configuration.UI_MODE_TYPE_MASK; + if (mUiModeType == newUiModeType) return; + mUiModeType = newUiModeType; + for (Part part : mParts) { + part.onUiModeTypeChanged(mUiModeType); + } + } + /** * Requests transitioning to {@code requestedState}. * @@ -211,6 +221,14 @@ public class DozeMachine { requestState(State.DOZE_REQUEST_PULSE, pulseReason); } + /** + * @return true if {@link DozeMachine} is currently in either {@link State#UNINITIALIZED} + * or {@link State#FINISH} + */ + public boolean isUninitializedOrFinished() { + return mState == State.UNINITIALIZED || mState == State.FINISH; + } + void onScreenState(int state) { mDozeLog.traceDisplayState(state); for (Part part : mParts) { @@ -360,7 +378,7 @@ public class DozeMachine { if (mState == State.FINISH) { return State.FINISH; } - if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR + if (mUiModeType == Configuration.UI_MODE_TYPE_CAR && (requestedState.canPulse() || requestedState.staysAwake())) { Log.i(TAG, "Doze is suppressed with all triggers disabled as car mode is active"); mDozeLog.traceCarModeStarted(); @@ -411,7 +429,7 @@ public class DozeMachine { nextState = State.FINISH; } else if (mDockManager.isDocked()) { nextState = mDockManager.isHidden() ? State.DOZE : State.DOZE_AOD_DOCKED; - } else if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) { + } else if (mAmbientDisplayConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) { nextState = State.DOZE_AOD; } else { nextState = State.DOZE; @@ -427,6 +445,7 @@ public class DozeMachine { /** Dumps the current state */ public void dump(PrintWriter pw) { pw.print(" state="); pw.println(mState); + pw.print(" mUiModeType="); pw.println(mUiModeType); pw.print(" wakeLockHeldForCurrentState="); pw.println(mWakeLockHeldForCurrentState); pw.print(" wakeLock="); pw.println(mWakeLock); pw.println("Parts:"); @@ -459,6 +478,19 @@ public class DozeMachine { /** Sets the {@link DozeMachine} when this Part is associated with one. */ default void setDozeMachine(DozeMachine dozeMachine) {} + + /** + * Notifies the Part about a change in {@link Configuration#uiMode}. + * + * @param newUiModeType {@link Configuration#UI_MODE_TYPE_NORMAL}, + * {@link Configuration#UI_MODE_TYPE_DESK}, + * {@link Configuration#UI_MODE_TYPE_CAR}, + * {@link Configuration#UI_MODE_TYPE_TELEVISION}, + * {@link Configuration#UI_MODE_TYPE_APPLIANCE}, + * {@link Configuration#UI_MODE_TYPE_WATCH}, + * or {@link Configuration#UI_MODE_TYPE_VR_HEADSET} + */ + default void onUiModeTypeChanged(int newUiModeType) {} } /** A wrapper interface for {@link android.service.dreams.DreamService} */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index a2eb4e3bb640a..e8d7e4642e3eb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -17,6 +17,7 @@ package com.android.systemui.doze; import android.content.Context; +import android.content.res.Configuration; import android.os.PowerManager; import android.os.SystemClock; import android.service.dreams.DreamService; @@ -59,6 +60,7 @@ public class DozeService extends DreamService mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */); DozeComponent dozeComponent = mDozeComponentBuilder.build(this); mDozeMachine = dozeComponent.getDozeMachine(); + mDozeMachine.onConfigurationChanged(getResources().getConfiguration()); } @Override @@ -126,6 +128,12 @@ public class DozeService extends DreamService } } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mDozeMachine.onConfigurationChanged(newConfig); + } + @Override public void onRequestHideDoze() { if (mDozeMachine != null) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java index 7ed4b35e1ee7b..e6d98655b119b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java @@ -16,21 +16,13 @@ package com.android.systemui.doze; -import static android.app.UiModeManager.ACTION_ENTER_CAR_MODE; -import static android.app.UiModeManager.ACTION_EXIT_CAR_MODE; +import static android.content.res.Configuration.UI_MODE_TYPE_CAR; -import android.app.UiModeManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.os.PowerManager; import android.os.UserHandle; import android.text.TextUtils; -import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.statusbar.phone.BiometricUnlockController; @@ -43,7 +35,9 @@ import dagger.Lazy; /** * Handles suppressing doze on: * 1. INITIALIZED, don't allow dozing at all when: - * - in CAR_MODE + * - in CAR_MODE, in this scenario the device is asleep and won't listen for any triggers + * to wake up. In this state, no UI shows. Unlike other conditions, this suppression is only + * temporary and stops when the device exits CAR_MODE * - device is NOT provisioned * - there's a pending authentication * 2. PowerSaveMode active @@ -57,34 +51,46 @@ import dagger.Lazy; */ @DozeScope public class DozeSuppressor implements DozeMachine.Part { - private static final String TAG = "DozeSuppressor"; private DozeMachine mMachine; private final DozeHost mDozeHost; private final AmbientDisplayConfiguration mConfig; private final DozeLog mDozeLog; - private final BroadcastDispatcher mBroadcastDispatcher; - private final UiModeManager mUiModeManager; private final Lazy mBiometricUnlockControllerLazy; - private boolean mBroadcastReceiverRegistered; + private boolean mIsCarModeEnabled = false; @Inject public DozeSuppressor( DozeHost dozeHost, AmbientDisplayConfiguration config, DozeLog dozeLog, - BroadcastDispatcher broadcastDispatcher, - UiModeManager uiModeManager, Lazy biometricUnlockControllerLazy) { mDozeHost = dozeHost; mConfig = config; mDozeLog = dozeLog; - mBroadcastDispatcher = broadcastDispatcher; - mUiModeManager = uiModeManager; mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; } + @Override + public void onUiModeTypeChanged(int newUiModeType) { + boolean isCarModeEnabled = newUiModeType == UI_MODE_TYPE_CAR; + if (mIsCarModeEnabled == isCarModeEnabled) { + return; + } + mIsCarModeEnabled = isCarModeEnabled; + // Do not handle the event if doze machine is not initialized yet. + // It will be handled upon initialization. + if (mMachine.isUninitializedOrFinished()) { + return; + } + if (mIsCarModeEnabled) { + handleCarModeStarted(); + } else { + handleCarModeExited(); + } + } + @Override public void setDozeMachine(DozeMachine dozeMachine) { mMachine = dozeMachine; @@ -94,7 +100,6 @@ public class DozeSuppressor implements DozeMachine.Part { public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { switch (newState) { case INITIALIZED: - registerBroadcastReceiver(); mDozeHost.addCallback(mHostCallback); checkShouldImmediatelyEndDoze(); checkShouldImmediatelySuspendDoze(); @@ -108,14 +113,12 @@ public class DozeSuppressor implements DozeMachine.Part { @Override public void destroy() { - unregisterBroadcastReceiver(); mDozeHost.removeCallback(mHostCallback); } private void checkShouldImmediatelySuspendDoze() { - if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) { - mDozeLog.traceCarModeStarted(); - mMachine.requestState(DozeMachine.State.DOZE_SUSPEND_TRIGGERS); + if (mIsCarModeEnabled) { + handleCarModeStarted(); } } @@ -135,7 +138,7 @@ public class DozeSuppressor implements DozeMachine.Part { @Override public void dump(PrintWriter pw) { - pw.println(" uiMode=" + mUiModeManager.getCurrentModeType()); + pw.println(" isCarModeEnabled=" + mIsCarModeEnabled); pw.println(" hasPendingAuth=" + mBiometricUnlockControllerLazy.get().hasPendingAuthentication()); pw.println(" isProvisioned=" + mDozeHost.isProvisioned()); @@ -143,40 +146,18 @@ public class DozeSuppressor implements DozeMachine.Part { pw.println(" aodPowerSaveActive=" + mDozeHost.isPowerSaveActive()); } - private void registerBroadcastReceiver() { - if (mBroadcastReceiverRegistered) { - return; - } - IntentFilter filter = new IntentFilter(ACTION_ENTER_CAR_MODE); - filter.addAction(ACTION_EXIT_CAR_MODE); - mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter); - mBroadcastReceiverRegistered = true; + private void handleCarModeExited() { + mDozeLog.traceCarModeEnded(); + mMachine.requestState(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) + ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE); } - private void unregisterBroadcastReceiver() { - if (!mBroadcastReceiverRegistered) { - return; - } - mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); - mBroadcastReceiverRegistered = false; + private void handleCarModeStarted() { + mDozeLog.traceCarModeStarted(); + mMachine.requestState(DozeMachine.State.DOZE_SUSPEND_TRIGGERS); } - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (ACTION_ENTER_CAR_MODE.equals(action)) { - mDozeLog.traceCarModeStarted(); - mMachine.requestState(DozeMachine.State.DOZE_SUSPEND_TRIGGERS); - } else if (ACTION_EXIT_CAR_MODE.equals(action)) { - mDozeLog.traceCarModeEnded(); - mMachine.requestState(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) - ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE); - } - } - }; - - private DozeHost.Callback mHostCallback = new DozeHost.Callback() { + private final DozeHost.Callback mHostCallback = new DozeHost.Callback() { @Override public void onPowerSaveChanged(boolean active) { // handles suppression changes, while DozeMachine#transitionPolicy handles gating diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java index 6a55a60c2fdaa..5bbd8109d8f9c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java @@ -16,6 +16,9 @@ package com.android.systemui.doze; +import static android.content.res.Configuration.UI_MODE_NIGHT_YES; +import static android.content.res.Configuration.UI_MODE_TYPE_CAR; + import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED; @@ -38,16 +41,17 @@ 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; -import android.app.UiModeManager; import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.testing.AndroidTestingRunner; import android.testing.UiThreadTest; import android.view.Display; +import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -78,25 +82,30 @@ public class DozeMachineTest extends SysuiTestCase { @Mock private DozeHost mHost; @Mock - private UiModeManager mUiModeManager; + private DozeMachine.Part mPartMock; + @Mock + private DozeMachine.Part mAnotherPartMock; private DozeServiceFake mServiceFake; private WakeLockFake mWakeLockFake; - private AmbientDisplayConfiguration mConfigMock; - private DozeMachine.Part mPartMock; + private AmbientDisplayConfiguration mAmbientDisplayConfigMock; @Before public void setUp() { MockitoAnnotations.initMocks(this); mServiceFake = new DozeServiceFake(); mWakeLockFake = new WakeLockFake(); - mConfigMock = mock(AmbientDisplayConfiguration.class); - mPartMock = mock(DozeMachine.Part.class); + mAmbientDisplayConfigMock = mock(AmbientDisplayConfiguration.class); when(mDockManager.isDocked()).thenReturn(false); when(mDockManager.isHidden()).thenReturn(false); - mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake, - mWakefulnessLifecycle, mUiModeManager, mDozeLog, mDockManager, - mHost, new DozeMachine.Part[]{mPartMock}); + mMachine = new DozeMachine(mServiceFake, + mAmbientDisplayConfigMock, + mWakeLockFake, + mWakefulnessLifecycle, + mDozeLog, + mDockManager, + mHost, + new DozeMachine.Part[]{mPartMock, mAnotherPartMock}); } @Test @@ -108,7 +117,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_goesToDoze() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); mMachine.requestState(INITIALIZED); @@ -118,7 +127,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_goesToAod() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); @@ -138,7 +147,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_afterDockPaused_goesToDoze() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); @@ -151,7 +160,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_alwaysOnSuppressed_alwaysOnDisabled_goesToDoze() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); mMachine.requestState(INITIALIZED); @@ -162,7 +171,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_alwaysOnSuppressed_alwaysOnEnabled_goesToDoze() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); @@ -184,7 +193,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_alwaysOnSuppressed_alwaysOnDisabled_afterDockPaused_goesToDoze() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); @@ -197,7 +206,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testInitialize_alwaysOnSuppressed_alwaysOnEnabled_afterDockPaused_goesToDoze() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); @@ -209,7 +218,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testPulseDone_goesToDoze() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); mMachine.requestState(INITIALIZED); mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); @@ -222,7 +231,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testPulseDone_goesToAoD() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); @@ -236,7 +245,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testPulseDone_alwaysOnSuppressed_goesToSuppressed() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); @@ -287,7 +296,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testPulseDone_afterDockPaused_goesToDoze() { - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); mMachine.requestState(INITIALIZED); @@ -303,7 +312,7 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testPulseDone_alwaysOnSuppressed_afterDockPaused_goesToDoze() { when(mHost.isAlwaysOnSuppressed()).thenReturn(true); - when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); mMachine.requestState(INITIALIZED); @@ -471,7 +480,9 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testTransitionToInitialized_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); verify(mPartMock).transitionTo(UNINITIALIZED, INITIALIZED); @@ -481,7 +492,9 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testTransitionToFinish_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); mMachine.requestState(FINISH); @@ -490,7 +503,9 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testDozeToDozeSuspendTriggers_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); @@ -499,7 +514,9 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testDozeAoDToDozeSuspendTriggers_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE_AOD); @@ -508,7 +525,9 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testDozePulsingBrightDozeSuspendTriggers_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE_PULSING_BRIGHT); @@ -517,15 +536,45 @@ public class DozeMachineTest extends SysuiTestCase { @Test public void testDozeAodDockedDozeSuspendTriggers_carModeIsEnabled() { - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + Configuration configuration = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(configuration); mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE_AOD_DOCKED); assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState()); } + @Test + public void testOnConfigurationChanged_propagatesUiModeTypeToParts() { + Configuration newConfig = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(newConfig); + + verify(mPartMock).onUiModeTypeChanged(UI_MODE_TYPE_CAR); + verify(mAnotherPartMock).onUiModeTypeChanged(UI_MODE_TYPE_CAR); + } + + @Test + public void testOnConfigurationChanged_propagatesOnlyUiModeChangesToParts() { + Configuration newConfig = configWithCarNightUiMode(); + + mMachine.onConfigurationChanged(newConfig); + mMachine.onConfigurationChanged(newConfig); + + verify(mPartMock, times(1)).onUiModeTypeChanged(UI_MODE_TYPE_CAR); + verify(mAnotherPartMock, times(1)).onUiModeTypeChanged(UI_MODE_TYPE_CAR); + } + @Test public void testDozeSuppressTriggers_screenState() { assertEquals(Display.STATE_OFF, DOZE_SUSPEND_TRIGGERS.screenState(null)); } + + @NonNull + private Configuration configWithCarNightUiMode() { + Configuration configuration = Configuration.EMPTY; + configuration.uiMode = UI_MODE_TYPE_CAR | UI_MODE_NIGHT_YES; + return configuration; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java index 0f29dcd5a9392..32b994538e129 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java @@ -10,14 +10,14 @@ * 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 andatest + * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.doze; -import static android.app.UiModeManager.ACTION_ENTER_CAR_MODE; -import static android.app.UiModeManager.ACTION_EXIT_CAR_MODE; +import static android.content.res.Configuration.UI_MODE_TYPE_CAR; +import static android.content.res.Configuration.UI_MODE_TYPE_NORMAL; import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; @@ -26,17 +26,16 @@ import static com.android.systemui.doze.DozeMachine.State.FINISH; import static com.android.systemui.doze.DozeMachine.State.INITIALIZED; import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.UiModeManager; -import android.content.BroadcastReceiver; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.testing.AndroidTestingRunner; import android.testing.UiThreadTest; @@ -44,13 +43,13 @@ import android.testing.UiThreadTest; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.phone.BiometricUnlockController; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.AdditionalMatchers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -71,10 +70,6 @@ public class DozeSuppressorTest extends SysuiTestCase { @Mock private AmbientDisplayConfiguration mConfig; @Mock - private BroadcastDispatcher mBroadcastDispatcher; - @Mock - private UiModeManager mUiModeManager; - @Mock private Lazy mBiometricUnlockControllerLazy; @Mock private BiometricUnlockController mBiometricUnlockController; @@ -82,13 +77,6 @@ public class DozeSuppressorTest extends SysuiTestCase { @Mock private DozeMachine mDozeMachine; - @Captor - private ArgumentCaptor mBroadcastReceiverCaptor; - @Captor - private ArgumentCaptor mIntentFilterCaptor; - private BroadcastReceiver mBroadcastReceiver; - private IntentFilter mIntentFilter; - @Captor private ArgumentCaptor mDozeHostCaptor; private DozeHost.Callback mDozeHostCallback; @@ -106,8 +94,6 @@ public class DozeSuppressorTest extends SysuiTestCase { mDozeHost, mConfig, mDozeLog, - mBroadcastDispatcher, - mUiModeManager, mBiometricUnlockControllerLazy); mDozeSuppressor.setDozeMachine(mDozeMachine); @@ -122,36 +108,35 @@ public class DozeSuppressorTest extends SysuiTestCase { public void testRegistersListenersOnInitialized_unregisteredOnFinish() { // check that receivers and callbacks registered mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); - captureBroadcastReceiver(); captureDozeHostCallback(); // check that receivers and callbacks are unregistered mDozeSuppressor.transitionTo(INITIALIZED, FINISH); - verify(mBroadcastDispatcher).unregisterReceiver(mBroadcastReceiver); verify(mDozeHost).removeCallback(mDozeHostCallback); } @Test public void testSuspendTriggersDoze_carMode() { // GIVEN car mode - when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); // WHEN dozing begins mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); // THEN doze continues with all doze triggers disabled. - verify(mDozeMachine).requestState(DOZE_SUSPEND_TRIGGERS); + verify(mDozeMachine, atLeastOnce()).requestState(DOZE_SUSPEND_TRIGGERS); + verify(mDozeMachine, never()) + .requestState(AdditionalMatchers.not(eq(DOZE_SUSPEND_TRIGGERS))); } @Test public void testSuspendTriggersDoze_enterCarMode() { // GIVEN currently dozing mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); - captureBroadcastReceiver(); mDozeSuppressor.transitionTo(INITIALIZED, DOZE); // WHEN car mode entered - mBroadcastReceiver.onReceive(null, new Intent(ACTION_ENTER_CAR_MODE)); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); // THEN doze continues with all doze triggers disabled. verify(mDozeMachine).requestState(DOZE_SUSPEND_TRIGGERS); @@ -160,13 +145,13 @@ public class DozeSuppressorTest extends SysuiTestCase { @Test public void testDozeResume_exitCarMode() { // GIVEN currently suspended, with AOD not enabled + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); when(mConfig.alwaysOnEnabled(anyInt())).thenReturn(false); mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); - captureBroadcastReceiver(); mDozeSuppressor.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS); // WHEN exiting car mode - mBroadcastReceiver.onReceive(null, new Intent(ACTION_EXIT_CAR_MODE)); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_NORMAL); // THEN doze is resumed verify(mDozeMachine).requestState(DOZE); @@ -175,18 +160,52 @@ public class DozeSuppressorTest extends SysuiTestCase { @Test public void testDozeAoDResume_exitCarMode() { // GIVEN currently suspended, with AOD not enabled + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); when(mConfig.alwaysOnEnabled(anyInt())).thenReturn(true); mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); - captureBroadcastReceiver(); mDozeSuppressor.transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS); // WHEN exiting car mode - mBroadcastReceiver.onReceive(null, new Intent(ACTION_EXIT_CAR_MODE)); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_NORMAL); // THEN doze AOD is resumed verify(mDozeMachine).requestState(DOZE_AOD); } + @Test + public void testUiModeDoesNotChange_noStateTransition() { + mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); + clearInvocations(mDozeMachine); + + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); + + verify(mDozeMachine, times(1)).requestState(DOZE_SUSPEND_TRIGGERS); + verify(mDozeMachine, never()) + .requestState(AdditionalMatchers.not(eq(DOZE_SUSPEND_TRIGGERS))); + } + + @Test + public void testUiModeTypeChange_whenDozeMachineIsNotReady_doesNotDoAnything() { + when(mDozeMachine.isUninitializedOrFinished()).thenReturn(true); + + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); + + verify(mDozeMachine, never()).requestState(any()); + } + + @Test + public void testUiModeTypeChange_CarModeEnabledAndDozeMachineNotReady_suspendsTriggersAfter() { + when(mDozeMachine.isUninitializedOrFinished()).thenReturn(true); + mDozeSuppressor.onUiModeTypeChanged(UI_MODE_TYPE_CAR); + verify(mDozeMachine, never()).requestState(any()); + + mDozeSuppressor.transitionTo(UNINITIALIZED, INITIALIZED); + + verify(mDozeMachine, times(1)).requestState(DOZE_SUSPEND_TRIGGERS); + } + @Test public void testEndDoze_unprovisioned() { // GIVEN device unprovisioned @@ -276,14 +295,4 @@ public class DozeSuppressorTest extends SysuiTestCase { verify(mDozeHost).addCallback(mDozeHostCaptor.capture()); mDozeHostCallback = mDozeHostCaptor.getValue(); } - - private void captureBroadcastReceiver() { - verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(), - mIntentFilterCaptor.capture()); - mBroadcastReceiver = mBroadcastReceiverCaptor.getValue(); - mIntentFilter = mIntentFilterCaptor.getValue(); - assertEquals(2, mIntentFilter.countActions()); - org.hamcrest.MatcherAssert.assertThat(() -> mIntentFilter.actionsIterator(), - containsInAnyOrder(ACTION_ENTER_CAR_MODE, ACTION_EXIT_CAR_MODE)); - } }