Merge "[Night] Add a new night theme trigger: bedtime"

This commit is contained in:
Steven Ng
2022-01-19 20:36:26 +00:00
committed by Android (Google) Code Review
6 changed files with 631 additions and 20 deletions

View File

@@ -919,15 +919,21 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void addOnProjectionStateChangedListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.app.UiModeManager.OnProjectionStateChangedListener);
method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public int getActiveProjectionTypes();
method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public int getNightModeCustomType();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public java.util.Set<java.lang.String> getProjectingPackages(int);
method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean releaseProjection(int);
method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void removeOnProjectionStateChangedListener(@NonNull android.app.UiModeManager.OnProjectionStateChangedListener);
method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean requestProjection(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public boolean setNightModeActivatedForCustomMode(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public void setNightModeCustomType(int);
field public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = "android.app.action.ENTER_CAR_MODE_PRIORITIZED";
field public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = "android.app.action.EXIT_CAR_MODE_PRIORITIZED";
field public static final int DEFAULT_PRIORITY = 0; // 0x0
field public static final String EXTRA_CALLING_PACKAGE = "android.app.extra.CALLING_PACKAGE";
field public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY";
field public static final int MODE_NIGHT_CUSTOM_TYPE_BEDTIME = 1; // 0x1
field public static final int MODE_NIGHT_CUSTOM_TYPE_SCHEDULE = 0; // 0x0
field public static final int MODE_NIGHT_CUSTOM_TYPE_UNKNOWN = -1; // 0xffffffff
field public static final int PROJECTION_TYPE_ALL = -1; // 0xffffffff
field public static final int PROJECTION_TYPE_AUTOMOTIVE = 1; // 0x1
field public static final int PROJECTION_TYPE_NONE = 0; // 0x0

View File

@@ -48,19 +48,42 @@ interface IUiModeManager {
/**
* Sets the night mode.
* <p>
* The mode can be one of:
* 1 - notnight mode
* 2 - night mode
* 3 - automatic mode switching
* <ol>notnight mode</ol>
* <ol>night mode</ol>
* <ol>custom schedule mode switching</ol>
*/
void setNightMode(int mode);
/**
* Gets the currently configured night mode. Return 1 for notnight,
* 2 for night, and 3 for automatic mode switching.
* Gets the currently configured night mode.
* <p>
* Returns
* <ol>notnight mode</ol>
* <ol>night mode</ol>
* <ol>custom schedule mode switching</ol>
*/
int getNightMode();
/**
* Sets the current night mode to {@link #MODE_NIGHT_CUSTOM} with the custom night mode type
* {@code nightModeCustomType}.
*
* @param nightModeCustomType
* @hide
*/
void setNightModeCustomType(int nightModeCustomType);
/**
* Returns the custom night mode type.
* <p>
* If the current night mode is not {@link #MODE_NIGHT_CUSTOM}, returns
* {@link #MODE_NIGHT_CUSTOM_TYPE_UNKNOWN}.
* @hide
*/
int getNightModeCustomType();
/**
* Sets the dark mode for the given application. This setting is persisted and will override the
* system configuration for this application.
@@ -81,8 +104,21 @@ interface IUiModeManager {
boolean isNightModeLocked();
/**
* [De]Activates night mode
*/
* [De]activating night mode for the current user if the current night mode is custom and the
* custom type matches {@code nightModeCustomType}.
*
* @param nightModeCustomType the specify type of custom mode
* @param active {@code true} to activate night mode. Otherwise, deactivate night mode
* @return {@code true} if night mode has successfully activated for the requested
* {@code nightModeCustomType}.
* @hide
*/
boolean setNightModeActivatedForCustomMode(int nightModeCustom, boolean active);
/**
* [De]Activates night mode.
* @hide
*/
boolean setNightModeActivated(boolean active);
/**

View File

@@ -243,6 +243,45 @@ public class UiModeManager {
*/
public static final int MODE_NIGHT_YES = 2;
/**
* Granular types for {@link MODE_NIGHT_CUSTOM_TYPE_BEDTIME}
* @hide
*/
@IntDef(prefix = { "MODE_NIGHT_CUSTOM_TYPE_" }, value = {
MODE_NIGHT_CUSTOM_TYPE_UNKNOWN,
MODE_NIGHT_CUSTOM_TYPE_SCHEDULE,
MODE_NIGHT_CUSTOM_TYPE_BEDTIME,
})
@Retention(RetentionPolicy.SOURCE)
public @interface NightModeCustomType {}
/**
* A granular type for {@link #MODE_NIGHT_CUSTOM} which is unknown.
* <p>
* This is the default value when the night mode is set to value other than
* {@link #MODE_NIGHT_CUSTOM}.
* @hide
*/
@SystemApi
public static final int MODE_NIGHT_CUSTOM_TYPE_UNKNOWN = -1;
/**
* A granular type for {@link #MODE_NIGHT_CUSTOM} which is based on a custom schedule.
* <p>
* This is the default value when night mode is set to {@link #MODE_NIGHT_CUSTOM} unless the
* the night mode custom type is specified by calling {@link #setNightModeCustomType(int)}.
* @hide
*/
@SystemApi
public static final int MODE_NIGHT_CUSTOM_TYPE_SCHEDULE = 0;
/**
* A granular type for {@link #MODE_NIGHT_CUSTOM} which is based on the bedtime schedule.
* @hide
*/
@SystemApi
public static final int MODE_NIGHT_CUSTOM_TYPE_BEDTIME = 1;
private IUiModeManager mService;
/**
@@ -495,6 +534,45 @@ public class UiModeManager {
}
}
/**
* Sets the current night mode to {@link #MODE_NIGHT_CUSTOM} with the custom night mode type
* {@code nightModeCustomType}.
*
* @param nightModeCustomType
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
public void setNightModeCustomType(@NightModeCustomType int nightModeCustomType) {
if (mService != null) {
try {
mService.setNightModeCustomType(nightModeCustomType);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Returns the custom night mode type.
* <p>
* If the current night mode is not {@link #MODE_NIGHT_CUSTOM}, returns
* {@link #MODE_NIGHT_CUSTOM_TYPE_UNKNOWN}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
public int getNightModeCustomType() {
if (mService != null) {
try {
return mService.getNightModeCustomType();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
}
/**
* Sets and persist the night mode for this application.
* <p>
@@ -598,12 +676,37 @@ public class UiModeManager {
return true;
}
/**
* [De]activating night mode for the current user if the current night mode is custom and the
* custom type matches {@code nightModeCustomType}.
*
* @param nightModeCustomType the specify type of custom mode
* @param active {@code true} to activate night mode. Otherwise, deactivate night mode
* @return {@code true} if night mode has successfully activated for the requested
* {@code nightModeCustomType}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
public boolean setNightModeActivatedForCustomMode(@NightModeCustomType int nightModeCustomType,
boolean active) {
if (mService != null) {
try {
return mService.setNightModeActivatedForCustomMode(nightModeCustomType, active);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return false;
}
/**
* Activating night mode for the current user
*
* @return {@code true} if the change is successful
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
public boolean setNightModeActivated(boolean active) {
if (mService != null) {
try {

View File

@@ -8983,6 +8983,15 @@ public final class Settings {
@Readable
public static final String UI_NIGHT_MODE = "ui_night_mode";
/**
* The current night mode custom type that has been selected by the user. Owned
* and controlled by UiModeManagerService. Constants are as per UiModeManager.
* @hide
*/
@Readable
@SuppressLint("NoSettingsProvider")
public static final String UI_NIGHT_MODE_CUSTOM_TYPE = "ui_night_mode_custom_type";
/**
* The current night mode that has been overridden to turn on by the system. Owned
* and controlled by UiModeManagerService. Constants are as per

View File

@@ -19,6 +19,9 @@ package com.android.server;
import static android.app.UiModeManager.DEFAULT_PRIORITY;
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
import static android.app.UiModeManager.MODE_NIGHT_NO;
import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
@@ -40,6 +43,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.app.UiModeManager.NightModeCustomType;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -115,6 +119,7 @@ final class UiModeManagerService extends SystemService {
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
private int mNightModeCustomType = UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
private final LocalTime DEFAULT_CUSTOM_NIGHT_START_TIME = LocalTime.of(22, 0);
private final LocalTime DEFAULT_CUSTOM_NIGHT_END_TIME = LocalTime.of(6, 0);
private LocalTime mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME;
@@ -136,6 +141,7 @@ final class UiModeManagerService extends SystemService {
private boolean mWatch;
private boolean mVrHeadset;
private boolean mComputedNightMode;
private boolean mLastBedtimeRequestedNightMode = false;
private int mCarModeEnableFlags;
private boolean mSetupWizardComplete;
@@ -541,7 +547,9 @@ final class UiModeManagerService extends SystemService {
mNightMode = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE, res.getInteger(
com.android.internal.R.integer.config_defaultNightMode), userId);
mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(),
mNightModeCustomType = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE_CUSTOM_TYPE, MODE_NIGHT_CUSTOM_TYPE_UNKNOWN, userId);
mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE_OVERRIDE_ON, 0, userId) != 0;
mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE_OVERRIDE_OFF, 0, userId) != 0;
@@ -702,6 +710,14 @@ final class UiModeManagerService extends SystemService {
@Override
public void setNightMode(int mode) {
// MODE_NIGHT_CUSTOM_TYPE_SCHEDULE is the default for MODE_NIGHT_CUSTOM.
int customModeType = mode == MODE_NIGHT_CUSTOM
? MODE_NIGHT_CUSTOM_TYPE_SCHEDULE
: MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
setNightModeInternal(mode, customModeType);
}
private void setNightModeInternal(int mode, int customModeType) {
if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED)) {
@@ -722,12 +738,14 @@ final class UiModeManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
if (mNightMode != mode) {
if (mNightMode != mode || mNightModeCustomType != customModeType) {
if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
unregisterScreenOffEventLocked();
cancelCustomAlarm();
}
mNightModeCustomType = mode == MODE_NIGHT_CUSTOM
? customModeType
: MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
mNightMode = mode;
resetNightModeOverrideLocked();
persistNightMode(user);
@@ -753,6 +771,30 @@ final class UiModeManagerService extends SystemService {
}
}
@Override
public void setNightModeCustomType(@NightModeCustomType int nightModeCustomType) {
if (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"setNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
}
setNightModeInternal(MODE_NIGHT_CUSTOM, nightModeCustomType);
}
@Override
public int getNightModeCustomType() {
if (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"getNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
}
synchronized (mLock) {
return mNightModeCustomType;
}
}
@Override
public void setApplicationNightMode(@UiModeManager.NightMode int mode) {
switch (mode) {
@@ -807,11 +849,20 @@ final class UiModeManagerService extends SystemService {
dumpImpl(pw);
}
@Override
public boolean setNightModeActivatedForCustomMode(int modeNightCustomType, boolean active) {
return setNightModeActivatedForModeInternal(modeNightCustomType, active);
}
@Override
public boolean setNightModeActivated(boolean active) {
if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
return setNightModeActivatedForModeInternal(mNightModeCustomType, active);
}
private boolean setNightModeActivatedForModeInternal(int modeCustomType, boolean active) {
if (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED)) {
!= PackageManager.PERMISSION_GRANTED) {
Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
return false;
}
@@ -824,6 +875,14 @@ final class UiModeManagerService extends SystemService {
return false;
}
// Store the last requested bedtime night mode state so that we don't need to notify
// anyone if the user decides to switch to the night mode to bedtime.
if (modeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
mLastBedtimeRequestedNightMode = active;
}
if (modeCustomType != mNightModeCustomType) {
return false;
}
synchronized (mLock) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1421,6 +1480,8 @@ final class UiModeManagerService extends SystemService {
if (mCarModeEnabled || mCar) return;
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mNightMode, user);
Secure.putLongForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE_CUSTOM_TYPE, mNightModeCustomType, user);
Secure.putLongForUser(getContext().getContentResolver(),
Secure.DARK_THEME_CUSTOM_START_TIME,
mCustomAutoNightModeStartMilliseconds.toNanoOfDay() / 1000, user);
@@ -1473,10 +1534,14 @@ final class UiModeManagerService extends SystemService {
}
if (mNightMode == MODE_NIGHT_CUSTOM) {
registerTimeChangeEvent();
final boolean activate = computeCustomNightMode();
updateComputedNightModeLocked(activate);
scheduleNextCustomTimeListener();
if (mNightModeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
updateComputedNightModeLocked(mLastBedtimeRequestedNightMode);
} else {
registerTimeChangeEvent();
final boolean activate = computeCustomNightMode();
updateComputedNightModeLocked(activate);
scheduleNextCustomTimeListener();
}
} else {
unregisterTimeChangeEvent();
}
@@ -1494,6 +1559,7 @@ final class UiModeManagerService extends SystemService {
"updateConfigurationLocked: mDockState=" + mDockState
+ "; mCarMode=" + mCarModeEnabled
+ "; mNightMode=" + mNightMode
+ "; mNightModeCustomType=" + mNightModeCustomType
+ "; uiMode=" + uiMode);
}
@@ -1534,7 +1600,8 @@ final class UiModeManagerService extends SystemService {
}
private boolean shouldApplyAutomaticChangesImmediately() {
return mCar || !mPowerManager.isInteractive();
return mCar || !mPowerManager.isInteractive()
|| mNightModeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
}
private void scheduleNextCustomTimeListener() {

View File

@@ -16,14 +16,20 @@
package com.android.server;
import static android.Manifest.permission.MODIFY_DAY_NIGHT_MODE;
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
import static android.app.UiModeManager.MODE_NIGHT_NO;
import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.app.UiModeManager.PROJECTION_TYPE_ALL;
import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
import static android.app.UiModeManager.PROJECTION_TYPE_NONE;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
@@ -194,7 +200,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Ignore // b/152719290 - Fails on stage-aosp-master
@Test
public void setNightMoveActivated_overridesFunctionCorrectly() throws RemoteException {
public void setNightModeActivated_overridesFunctionCorrectly() throws RemoteException {
// set up
when(mPowerManager.isInteractive()).thenReturn(false);
mService.setNightMode(MODE_NIGHT_NO);
@@ -224,6 +230,29 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
assertFalse(mUiManagerService.getConfiguration().isNightModeActive());
}
@Test
public void setNightModeActivated_true_withCustomModeBedtime_shouldOverrideNightModeCorrectly()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertFalse(mUiManagerService.getConfiguration().isNightModeActive());
mService.setNightModeActivated(true);
assertThat(mUiManagerService.getConfiguration().isNightModeActive()).isTrue();
}
@Test
public void setNightModeActivated_false_withCustomModeBedtime_shouldOverrideNightModeCorrectly()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertFalse(mUiManagerService.getConfiguration().isNightModeActive());
mService.setNightModeActivated(true);
mService.setNightModeActivated(false);
assertThat(mUiManagerService.getConfiguration().isNightModeActive()).isFalse();
}
@Test
public void setAutoMode_screenOffRegistered() throws RemoteException {
try {
@@ -247,7 +276,44 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
}
@Test
public void setNightModeActivated_fromNoToYesAndBAck() throws RemoteException {
public void setNightModeCustomType_bedtime_shouldNotActivateNightMode() throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_NO);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void setNightModeCustomType_noPermission_shouldThrow() throws RemoteException {
when(mContext.checkCallingOrSelfPermission(eq(MODIFY_DAY_NIGHT_MODE)))
.thenReturn(PackageManager.PERMISSION_DENIED);
assertThrows(SecurityException.class,
() -> mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME));
}
@Test
public void setNightModeCustomType_bedtime_shouldHaveNoScreenOffRegistered()
throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_NO);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
ArgumentCaptor<IntentFilter> intentFiltersCaptor = ArgumentCaptor.forClass(
IntentFilter.class);
verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class),
intentFiltersCaptor.capture());
List<IntentFilter> intentFilters = intentFiltersCaptor.getAllValues();
for (IntentFilter intentFilter : intentFilters) {
assertThat(intentFilter.hasAction(Intent.ACTION_SCREEN_OFF)).isFalse();
}
}
@Test
public void setNightModeActivated_fromNoToYesAndBack() throws RemoteException {
mService.setNightMode(MODE_NIGHT_NO);
mService.setNightModeActivated(true);
assertTrue(isNightModeActivated());
@@ -256,7 +322,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
}
@Test
public void setNightModeActivated_permissiontoChangeOtherUsers() throws RemoteException {
public void setNightModeActivated_permissionToChangeOtherUsers() throws RemoteException {
SystemService.TargetUser user = mock(SystemService.TargetUser.class);
doReturn(9).when(user).getUserIdentifier();
mUiManagerService.onUserSwitching(user, user);
@@ -266,6 +332,89 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
assertFalse(mService.setNightModeActivated(true));
}
@Test
public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_shouldActivate()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOffAndBedtime_shouldDeactivate()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndSchedule_shouldNotActivate()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_SCHEDULE, true /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_shouldNotActivate()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_CUSTOM);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeSchedule_withParamOnAndBedtime_thenCustomTypeBedtime_shouldActivate()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_CUSTOM);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeSchedule_shouldKeepNightModeActivate()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_CUSTOM);
LocalTime now = LocalTime.now();
mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000);
mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void setNightModeActivatedForCustomMode_customTypeBedtime_withParamOnAndBedtime_thenCustomTypeScheduleAndScreenOff_shouldDeactivateNightMode()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_CUSTOM);
LocalTime now = LocalTime.now();
mService.setCustomNightModeStart(now.plusHours(1L).toNanoOfDay() / 1000);
mService.setCustomNightModeEnd(now.plusHours(2L).toNanoOfDay() / 1000);
mScreenOffCallback.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void autoNightModeSwitch_batterySaverOn() throws RemoteException {
mService.setNightMode(MODE_NIGHT_NO);
@@ -282,6 +431,191 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
assertTrue(isNightModeActivated());
}
@Test
public void nightModeCustomBedtime_batterySaverOn_notInBedtime_shouldActivateNightMode()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeCustomBedtime_batterySaverOn_afterBedtime_shouldKeepNightModeActivated()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeBedtime_duringBedtime_batterySaverOnThenOff_shouldKeepNightModeActivated()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(false).build());
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeCustomBedtime_duringBedtime_batterySaverOnThenOff_finallyAfterBedtime_shouldDeactivateNightMode()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
mPowerSaveConsumer.accept(
new PowerSaveState.Builder().setBatterySaverEnabled(false).build());
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeCustomBedtime_duringBedtime_changeModeToNo_shouldDeactivateNightMode()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_NO);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeCustomBedtime_duringBedtime_changeModeToNoAndThenExitBedtime_shouldKeepNightModeDeactivated()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_NO);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeCustomBedtime_duringBedtime_changeModeToYes_shouldKeepNightModeActivated()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_YES);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeCustomBedtime_duringBedtime_changeModeToYesAndThenExitBedtime_shouldKeepNightModeActivated()
throws RemoteException {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
mService.setNightMode(MODE_NIGHT_YES);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, false /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeNo_duringBedtime_shouldKeepNightModeDeactivated()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_NO);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeNo_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_NO);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeYes_thenChangeToCustomTypeBedtime_shouldDeactivateNightMode()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_YES);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeYes_thenChangeToCustomTypeBedtimeAndActivate_shouldActivateNightMode()
throws RemoteException {
mService.setNightMode(MODE_NIGHT_YES);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void nightModeAuto_thenChangeToCustomTypeBedtime_notInBedtime_shouldDeactivateNightMode()
throws RemoteException {
// set mode to auto
mService.setNightMode(MODE_NIGHT_AUTO);
mService.setNightModeActivated(true);
// now it is night time
doReturn(true).when(mTwilightState).isNight();
mTwilightListener.onTwilightStateChanged(mTwilightState);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
assertThat(isNightModeActivated()).isFalse();
}
@Test
public void nightModeAuto_thenChangeToCustomTypeBedtime_duringBedtime_shouldActivateNightMode()
throws RemoteException {
// set mode to auto
mService.setNightMode(MODE_NIGHT_AUTO);
mService.setNightModeActivated(true);
// now it is night time
doReturn(true).when(mTwilightState).isNight();
mTwilightListener.onTwilightStateChanged(mTwilightState);
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
mService.setNightModeActivatedForCustomMode(
MODE_NIGHT_CUSTOM_TYPE_BEDTIME, true /* active */);
assertThat(isNightModeActivated()).isTrue();
}
@Test
public void setAutoMode_clearCache() throws RemoteException {
try {
@@ -326,6 +660,62 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
assertEquals(MODE_NIGHT_AUTO, mService.getNightMode());
}
@Test
public void getNightModeCustomType_nightModeNo_shouldReturnUnknown() throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_NO);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN);
}
@Test
public void getNightModeCustomType_nightModeYes_shouldReturnUnknown() throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_YES);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN);
}
@Test
public void getNightModeCustomType_nightModeAuto_shouldReturnUnknown() throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_AUTO);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_UNKNOWN);
}
@Test
public void getNightModeCustomType_nightModeCustom_shouldReturnSchedule()
throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_CUSTOM);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_SCHEDULE);
}
@Test
public void getNightModeCustomType_nightModeCustomBedtime_shouldReturnBedtime()
throws RemoteException {
try {
mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
} catch (SecurityException e) { /* we should ignore this update config exception*/ }
assertThat(mService.getNightModeCustomType()).isEqualTo(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
}
@Test
public void getNightModeCustomType_permissionNotGranted_shouldThrow()
throws RemoteException {
when(mContext.checkCallingOrSelfPermission(eq(MODIFY_DAY_NIGHT_MODE)))
.thenReturn(PackageManager.PERMISSION_DENIED);
assertThrows(SecurityException.class, () -> mService.getNightModeCustomType());
}
@Test
public void isNightModeActive_nightModeYes() throws RemoteException {
try {