summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jay Aliomer <aaliomer@google.com> 2020-02-05 17:58:15 -0500
committer Jay Aliomer <aaliomer@google.com> 2020-02-26 15:19:36 +0000
commit1314cf615f20c9ae9d1b3dc24375be9205a83fa4 (patch)
tree504cd4cd2857999adbbb7f156aa3d98c3c7ab62f
parent6f01c62d29d90c143b93e461f5b61d4f11127e6c (diff)
Battery saver dark mode bug
When battery saver is on and the dark mode is in automatic scheduling, the battery saver does not apply before the screen turns off which is a bug. some refactoring has been done also to speedup startup time Test: atest UiModeManagerTest UiModeManagerServiceTest Fixes: 148798405 Fixes: 149546098 Change-Id: I0bee6517b39216146681097262cf55c7192b0131 (cherry picked from commit 2a76f8145bffad6d644f9edf1a3621c8805a03ac)
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java91
-rw-r--r--services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java50
2 files changed, 95 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 6763c513ec93..f619d6927fdb 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -98,7 +98,8 @@ final class UiModeManagerService extends SystemService {
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
// we use the override auto mode
- // for example: force night mode off in the night time while in auto mode
+ // for example: force night mode off in the night time
+ // while in auto mode
private int mNightModeOverride = mNightMode;
private final LocalTime DEFAULT_CUSTOM_NIGHT_START_TIME = LocalTime.of(22, 0);
private final LocalTime DEFAULT_CUSTOM_NIGHT_END_TIME = LocalTime.of(6, 0);
@@ -152,6 +153,7 @@ final class UiModeManagerService extends SystemService {
private PowerManager.WakeLock mWakeLock;
private final LocalService mLocalService = new LocalService();
+ private PowerManagerInternal mLocalPowerManager;
public UiModeManagerService(Context context) {
super(context);
@@ -160,6 +162,7 @@ final class UiModeManagerService extends SystemService {
@VisibleForTesting
protected UiModeManagerService(Context context, WindowManagerInternal wm, AlarmManager am,
PowerManager pm, PowerManager.WakeLock wl, TwilightManager tm,
+ PowerManagerInternal localPowerManager,
boolean setupWizardComplete) {
super(context);
mWindowManager = wm;
@@ -168,6 +171,8 @@ final class UiModeManagerService extends SystemService {
mSetupWizardComplete = setupWizardComplete;
mAlarmManager = am;
mPowerManager = pm;
+ mLocalPowerManager = localPowerManager;
+ initPowerSave();
}
private static Intent buildHomeIntent(String category) {
@@ -230,11 +235,11 @@ final class UiModeManagerService extends SystemService {
@Override
public void onTwilightStateChanged(@Nullable TwilightState state) {
synchronized (mLock) {
- if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+ if (mNightMode == UiModeManager.MODE_NIGHT_AUTO && mSystemReady) {
if (mCar) {
updateLocked(0, 0);
} else {
- registerScreenOffEvent();
+ registerScreenOffEventLocked();
}
}
}
@@ -250,7 +255,7 @@ final class UiModeManagerService extends SystemService {
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
// must unregister first before updating
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
updateLocked(0, 0);
}
}
@@ -326,8 +331,7 @@ final class UiModeManagerService extends SystemService {
public void onStart() {
final Context context = getContext();
- mPowerManager =
- (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
mWindowManager = LocalServices.getService(WindowManagerInternal.class);
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
@@ -341,21 +345,11 @@ final class UiModeManagerService extends SystemService {
IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
context.registerReceiver(mBatteryReceiver, batteryFilter);
- PowerManagerInternal localPowerManager =
+ mLocalPowerManager =
LocalServices.getService(PowerManagerInternal.class);
- mPowerSave = localPowerManager.getLowPowerState(ServiceType.NIGHT_MODE).batterySaverEnabled;
- localPowerManager.registerLowPowerModeObserver(ServiceType.NIGHT_MODE,
- state -> {
- synchronized (mLock) {
- if (mPowerSave == state.batterySaverEnabled) {
- return;
- }
- mPowerSave = state.batterySaverEnabled;
- if (mSystemReady) {
- updateLocked(0, 0);
- }
- }
- });
+ initPowerSave();
+
+ mTwilightManager = getLocalService(TwilightManager.class);
mConfiguration.setToDefaults();
@@ -396,7 +390,24 @@ final class UiModeManagerService extends SystemService {
context.getContentResolver().registerContentObserver(Secure.getUriFor(Secure.UI_NIGHT_MODE),
false, mDarkThemeObserver, 0);
- updateSystemProperties();
+ mHandler.post(() -> updateSystemProperties());
+ }
+
+ private void initPowerSave() {
+ mPowerSave =
+ mLocalPowerManager.getLowPowerState(ServiceType.NIGHT_MODE)
+ .batterySaverEnabled;
+ mLocalPowerManager.registerLowPowerModeObserver(ServiceType.NIGHT_MODE, state -> {
+ synchronized (mLock) {
+ if (mPowerSave == state.batterySaverEnabled) {
+ return;
+ }
+ mPowerSave = state.batterySaverEnabled;
+ if (mSystemReady) {
+ updateLocked(0, 0);
+ }
+ }
+ });
}
@VisibleForTesting
@@ -433,7 +444,7 @@ final class UiModeManagerService extends SystemService {
if (shouldApplyAutomaticChangesImmediately()) {
updateLocked(0, 0);
} else {
- registerScreenOffEvent();
+ registerScreenOffEventLocked();
}
scheduleNextCustomTimeListener();
}
@@ -473,7 +484,8 @@ final class UiModeManagerService extends SystemService {
return oldNightMode != mNightMode;
}
- private void registerScreenOffEvent() {
+ private void registerScreenOffEventLocked() {
+ if (mPowerSave) return;
mWaitForScreenOff = true;
final IntentFilter intentFilter =
new IntentFilter(Intent.ACTION_SCREEN_OFF);
@@ -484,7 +496,7 @@ final class UiModeManagerService extends SystemService {
mAlarmManager.cancel(mCustomTimeListener);
}
- private void unregisterScreenOffEvent() {
+ private void unregisterScreenOffEventLocked() {
mWaitForScreenOff = false;
try {
getContext().unregisterReceiver(mOnScreenOffHandler);
@@ -630,7 +642,7 @@ final class UiModeManagerService extends SystemService {
synchronized (mLock) {
if (mNightMode != mode) {
if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
cancelCustomAlarm();
}
@@ -643,10 +655,10 @@ final class UiModeManagerService extends SystemService {
// on screen off will update configuration instead
if ((mNightMode != MODE_NIGHT_AUTO && mNightMode != MODE_NIGHT_CUSTOM)
|| shouldApplyAutomaticChangesImmediately()) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
updateLocked(0, 0);
} else {
- registerScreenOffEvent();
+ registerScreenOffEventLocked();
}
}
}
@@ -695,7 +707,7 @@ final class UiModeManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
mNightModeOverride = active
? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
} else if (mNightMode == UiModeManager.MODE_NIGHT_NO
@@ -737,7 +749,7 @@ final class UiModeManagerService extends SystemService {
persistNightMode(user);
onCustomTimeUpdated(user);
} catch (DateTimeException e) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -764,7 +776,7 @@ final class UiModeManagerService extends SystemService {
mCustomAutoNightModeEndMilliseconds = newTime;
onCustomTimeUpdated(user);
} catch (DateTimeException e) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -775,10 +787,10 @@ final class UiModeManagerService extends SystemService {
persistNightMode(user);
if (mNightMode != MODE_NIGHT_CUSTOM) return;
if (shouldApplyAutomaticChangesImmediately()) {
- unregisterScreenOffEvent();
+ unregisterScreenOffEventLocked();
updateLocked(0, 0);
} else {
- registerScreenOffEvent();
+ registerScreenOffEventLocked();
}
}
@@ -788,6 +800,7 @@ final class UiModeManagerService extends SystemService {
pw.print(" mDockState="); pw.print(mDockState);
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
+ pw.print(" mNightModeOverride="); pw.print(mNightModeOverride);
pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" (");
pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") ");
pw.print(" mNightModeLocked="); pw.println(mNightModeLocked);
@@ -802,6 +815,8 @@ final class UiModeManagerService extends SystemService {
}
pw.println("");
pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
+ pw.print(" customStart="); pw.print(mCustomAutoNightModeStartMilliseconds);
+ pw.print(" customEnd"); pw.print(mCustomAutoNightModeEndMilliseconds);
pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags);
pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch);
@@ -824,7 +839,6 @@ final class UiModeManagerService extends SystemService {
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
synchronized (mLock) {
- mTwilightManager = getLocalService(TwilightManager.class);
mSystemReady = true;
mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
registerVrStateListener();
@@ -1011,6 +1025,10 @@ final class UiModeManagerService extends SystemService {
uiMode = Configuration.UI_MODE_TYPE_VR_HEADSET;
}
+ if (mNightMode == MODE_NIGHT_YES || mNightMode == UiModeManager.MODE_NIGHT_NO) {
+ updateComputedNightModeLocked(mNightMode == MODE_NIGHT_YES);
+ }
+
if (mNightMode == MODE_NIGHT_AUTO) {
boolean activateNightMode = mComputedNightMode;
if (mTwilightManager != null) {
@@ -1020,12 +1038,10 @@ final class UiModeManagerService extends SystemService {
}
updateComputedNightModeLocked(activateNightMode);
- uiMode = getComputedUiModeConfiguration(uiMode);
} else {
if (mTwilightManager != null) {
mTwilightManager.unregisterListener(mTwilightListener);
}
- uiMode |= mNightMode << 4;
}
if (mNightMode == MODE_NIGHT_CUSTOM) {
@@ -1033,7 +1049,6 @@ final class UiModeManagerService extends SystemService {
final boolean activate = computeCustomNightMode();
updateComputedNightModeLocked(activate);
scheduleNextCustomTimeListener();
- uiMode = getComputedUiModeConfiguration(uiMode);
} else {
unregisterTimeChangeEvent();
}
@@ -1042,6 +1057,8 @@ final class UiModeManagerService extends SystemService {
if (mPowerSave && !mCarModeEnabled) {
uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
uiMode |= Configuration.UI_MODE_NIGHT_YES;
+ } else {
+ uiMode = getComputedUiModeConfiguration(uiMode);
}
if (LOG) {
@@ -1053,7 +1070,7 @@ final class UiModeManagerService extends SystemService {
}
mCurUiMode = uiMode;
- if (!mHoldingConfiguration && !mWaitForScreenOff) {
+ if (!mHoldingConfiguration && (!mWaitForScreenOff || mPowerSave)) {
mConfiguration.uiMode = uiMode;
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
index 22046a51d059..6a707eb36160 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -28,6 +28,8 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -42,6 +44,7 @@ import org.mockito.Mock;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
+import java.util.function.Consumer;
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
@@ -79,29 +82,34 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Mock
private Resources mResources;
@Mock
- TwilightManager mTwilightManager;
+ private TwilightManager mTwilightManager;
@Mock
- PowerManager.WakeLock mWakeLock;
+ private PowerManager.WakeLock mWakeLock;
@Mock
- AlarmManager mAlarmManager;
+ private AlarmManager mAlarmManager;
@Mock
- PowerManager mPowerManager;
+ private PowerManager mPowerManager;
@Mock
- TwilightState mTwilightState;
+ private TwilightState mTwilightState;
+ @Mock
+ PowerManagerInternal mLocalPowerManager;
private BroadcastReceiver mScreenOffCallback;
private BroadcastReceiver mTimeChangedCallback;
private AlarmManager.OnAlarmListener mCustomListener;
+ private Consumer<PowerSaveState> mPowerSaveConsumer;
@Before
public void setUp() {
initMocks(this);
- mUiManagerService = new UiModeManagerService(mContext,
- mWindowManager, mAlarmManager, mPowerManager,
- mWakeLock, mTwilightManager, true);
- mService = mUiManagerService.getService();
when(mContext.checkCallingOrSelfPermission(anyString()))
.thenReturn(PackageManager.PERMISSION_GRANTED);
+ doAnswer(inv -> {
+ mPowerSaveConsumer = (Consumer<PowerSaveState>) inv.getArgument(1);
+ return null;
+ }).when(mLocalPowerManager).registerLowPowerModeObserver(anyInt(), any());
+ when(mLocalPowerManager.getLowPowerState(anyInt()))
+ .thenReturn(new PowerSaveState.Builder().setBatterySaverEnabled(false).build());
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mPowerManager.isInteractive()).thenReturn(true);
@@ -127,6 +135,14 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
mCustomListener = () -> {};
return null;
}).when(mAlarmManager).cancel(eq(mCustomListener));
+
+ mUiManagerService = new UiModeManagerService(mContext,
+ mWindowManager, mAlarmManager, mPowerManager,
+ mWakeLock, mTwilightManager, mLocalPowerManager, true);
+ try {
+ mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+ } catch (SecurityException e) {/* ignore for permission denial */}
+ mService = mUiManagerService.getService();
}
@Test
@@ -151,6 +167,22 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void autoNightModeSwitch_batterySaverOn() throws RemoteException {
+ mService.setNightMode(MODE_NIGHT_NO);
+ when(mTwilightState.isNight()).thenReturn(false);
+ mService.setNightMode(MODE_NIGHT_AUTO);
+
+ // night NO
+ assertFalse(isNightModeActivated());
+
+ mPowerSaveConsumer.accept(
+ new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
+
+ // night YES
+ assertTrue(isNightModeActivated());
+ }
+
+ @Test
public void setAutoMode_clearCache() throws RemoteException {
try {
mService.setNightMode(MODE_NIGHT_AUTO);