Uses Configuration.uiMode in DozeMachine to determine if car mode is active

Other changes:
 - Use onConfigurationChanged instead of intents to detect when we enter/exit car mode to avoid any race conditions.
 - Renames mConfig field to mAmbientDisplayConfig.

Fixes: 254228426
Test: atest com.android.systemui.doze
Test: manual, revert ag/16853283 locally, go to AoD, run 'adb shell cmd uimode car yes', no doze triggers should wake up the device. run 'adb shell cmd uimode car no', doze triggers (tap, pickup, etc) should wake up the device.
Change-Id: I017a00ae776482f6ff329f72250bd0584961aedf
This commit is contained in:
Chandru
2022-10-18 11:31:32 +00:00
parent f71a0036c0
commit f4805e05a6
5 changed files with 213 additions and 134 deletions

View File

@@ -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} */

View File

@@ -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) {

View File

@@ -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<BiometricUnlockController> mBiometricUnlockControllerLazy;
private boolean mBroadcastReceiverRegistered;
private boolean mIsCarModeEnabled = false;
@Inject
public DozeSuppressor(
DozeHost dozeHost,
AmbientDisplayConfiguration config,
DozeLog dozeLog,
BroadcastDispatcher broadcastDispatcher,
UiModeManager uiModeManager,
Lazy<BiometricUnlockController> 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

View File

@@ -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;
}
}

View File

@@ -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<BiometricUnlockController> mBiometricUnlockControllerLazy;
@Mock
private BiometricUnlockController mBiometricUnlockController;
@@ -82,13 +77,6 @@ public class DozeSuppressorTest extends SysuiTestCase {
@Mock
private DozeMachine mDozeMachine;
@Captor
private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
@Captor
private ArgumentCaptor<IntentFilter> mIntentFilterCaptor;
private BroadcastReceiver mBroadcastReceiver;
private IntentFilter mIntentFilter;
@Captor
private ArgumentCaptor<DozeHost.Callback> 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));
}
}