Night display status restores on reboot/user change

Fixes: 30086742
Test: runtest -c com.android.server.NightDisplayServiceTest \
      frameworks-services
Change-Id: I264be077e607baf8e19496f0c57549a907668005
This commit is contained in:
Christine Franks
2017-02-10 17:36:10 -08:00
committed by Justin Klaassen
parent 40d0f86783
commit e5bb03e2ea
5 changed files with 690 additions and 40 deletions

View File

@@ -6789,7 +6789,8 @@ public final class Settings {
* Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
* @hide
*/
public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time";
public static final String NIGHT_DISPLAY_CUSTOM_START_TIME =
"night_display_custom_start_time";
/**
* Custom time when Night display is scheduled to deactivate.
@@ -6798,6 +6799,14 @@ public final class Settings {
*/
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
* Time in milliseconds (since epoch) when Night display was last activated. Use to decide
* whether to apply the current activated state after a reboot or user change.
* @hide
*/
public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
"night_display_last_activated_time";
/**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
@@ -7024,6 +7033,7 @@ public final class Settings {
NIGHT_DISPLAY_CUSTOM_END_TIME,
NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_AUTO_MODE,
NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
NIGHT_DISPLAY_ACTIVATED,
SYNC_PARENT_SOUNDS,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,

View File

@@ -47,7 +47,6 @@ import com.android.server.SystemService;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
import com.android.server.vr.VrManagerService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Calendar;
@@ -62,7 +61,6 @@ public final class NightDisplayService extends SystemService
implements NightDisplayController.Callback {
private static final String TAG = "NightDisplayService";
private static final boolean DEBUG = false;
/**
* The transition time, in milliseconds, for Night Display to turn on/off.
@@ -151,8 +149,9 @@ public final class NightDisplayService extends SystemService
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
if (phase >= PHASE_SYSTEM_SERVICES_READY) {
final IVrManager vrManager = IVrManager.Stub.asInterface(
getBinderService(Context.VR_SERVICE));
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
@@ -160,7 +159,9 @@ public final class NightDisplayService extends SystemService
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
}
} else if (phase == PHASE_BOOT_COMPLETED) {
}
if (phase >= PHASE_BOOT_COMPLETED) {
mBootCompleted = true;
// Register listeners now that boot is complete.
@@ -284,12 +285,18 @@ public final class NightDisplayService extends SystemService
if (mIsActivated == null || mIsActivated != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
if (mAutoMode != null) {
mAutoMode.onActivated(activated);
if (mIsActivated != null) {
Secure.putLongForUser(getContext().getContentResolver(),
Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
mCurrentUser);
}
mIsActivated = activated;
if (mAutoMode != null) {
mAutoMode.onActivated(activated);
}
applyTint(false);
}
}
@@ -401,7 +408,7 @@ public final class NightDisplayService extends SystemService
* Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
*
* @param colorTemperature color temperature in Kelvin
* @param outTemp the 4x4 display transformation matrix for that color temperature
* @param outTemp the 4x4 display transformation matrix for that color temperature
*/
private void setMatrix(int colorTemperature, float[] outTemp) {
if (outTemp.length != 16) {
@@ -423,8 +430,22 @@ public final class NightDisplayService extends SystemService
outTemp[10] = blue;
}
private Calendar getLastActivatedTime() {
final ContentResolver cr = getContext().getContentResolver();
final long lastActivatedTimeMillis = Secure.getLongForUser(
cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
if (lastActivatedTimeMillis < 0) {
return null;
}
final Calendar lastActivatedTime = Calendar.getInstance();
lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
return lastActivatedTime;
}
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
public abstract void onStop();
}
@@ -438,7 +459,7 @@ public final class NightDisplayService extends SystemService
private Calendar mLastActivatedTime;
public CustomAutoMode() {
CustomAutoMode() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mTimeChangedReceiver = new BroadcastReceiver() {
@Override
@@ -452,10 +473,10 @@ public final class NightDisplayService extends SystemService
final Calendar now = Calendar.getInstance();
final Calendar startTime = mStartTime.getDateTimeBefore(now);
final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
final boolean activated = now.before(endTime);
boolean setActivated = mIsActivated == null || mLastActivatedTime == null;
if (!setActivated && mIsActivated != activated) {
boolean activate = now.before(endTime);
if (mLastActivatedTime != null) {
// Convert mLastActivatedTime to the current timezone if needed.
final TimeZone currentTimeZone = now.getTimeZone();
if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
final int year = mLastActivatedTime.get(Calendar.YEAR);
@@ -470,17 +491,16 @@ public final class NightDisplayService extends SystemService
mLastActivatedTime.set(Calendar.MINUTE, minute);
}
if (mIsActivated) {
setActivated = now.before(mStartTime.getDateTimeBefore(mLastActivatedTime))
|| now.after(mEndTime.getDateTimeAfter(mLastActivatedTime));
} else {
setActivated = now.before(mEndTime.getDateTimeBefore(mLastActivatedTime))
|| now.after(mStartTime.getDateTimeAfter(mLastActivatedTime));
// Maintain the existing activated state if within the current period.
if (mLastActivatedTime.before(now)
&& mLastActivatedTime.after(startTime)
&& (mLastActivatedTime.after(endTime) || now.before(endTime))) {
activate = mController.isActivated();
}
}
if (setActivated) {
mController.setActivated(activated);
if (mIsActivated == null || mIsActivated != activate) {
mController.setActivated(activate);
}
updateNextAlarm(mIsActivated, now);
}
@@ -502,6 +522,8 @@ public final class NightDisplayService extends SystemService
mStartTime = mController.getCustomStartTime();
mEndTime = mController.getCustomEndTime();
mLastActivatedTime = getLastActivatedTime();
// Force an update to initialize state.
updateActivated();
}
@@ -516,11 +538,8 @@ public final class NightDisplayService extends SystemService
@Override
public void onActivated(boolean activated) {
final Calendar now = Calendar.getInstance();
if (mIsActivated != null) {
mLastActivatedTime = now;
}
updateNextAlarm(activated, now);
mLastActivatedTime = getLastActivatedTime();
updateNextAlarm(activated, Calendar.getInstance());
}
@Override
@@ -550,33 +569,33 @@ public final class NightDisplayService extends SystemService
private Calendar mLastActivatedTime;
public TwilightAutoMode() {
TwilightAutoMode() {
mTwilightManager = getLocalService(TwilightManager.class);
}
private void updateActivated(TwilightState state) {
final boolean isNight = state != null && state.isNight();
boolean setActivated = mIsActivated == null || mIsActivated != isNight;
if (setActivated && state != null && mLastActivatedTime != null) {
boolean activate = state != null && state.isNight();
if (state != null && mLastActivatedTime != null) {
final Calendar now = Calendar.getInstance();
final Calendar sunrise = state.sunrise();
final Calendar sunset = state.sunset();
if (sunrise.before(sunset)) {
setActivated = mLastActivatedTime.before(sunrise)
|| mLastActivatedTime.after(sunset);
} else {
setActivated = mLastActivatedTime.before(sunset)
|| mLastActivatedTime.after(sunrise);
// Maintain the existing activated state if within the current period.
if (mLastActivatedTime.before(now)
&& (mLastActivatedTime.after(sunrise) ^ mLastActivatedTime.after(sunset))) {
activate = mController.isActivated();
}
}
if (setActivated) {
mController.setActivated(isNight);
if (mIsActivated == null || mIsActivated != activate) {
mController.setActivated(activate);
}
}
@Override
public void onStart() {
mTwilightManager.registerListener(this, mHandler);
mLastActivatedTime = getLastActivatedTime();
// Force an update to initialize state.
updateActivated(mTwilightManager.getLastTwilightState());
@@ -591,7 +610,7 @@ public final class NightDisplayService extends SystemService
@Override
public void onActivated(boolean activated) {
if (mIsActivated != null) {
mLastActivatedTime = Calendar.getInstance();
mLastActivatedTime = getLastActivatedTime();
}
}

View File

@@ -31,7 +31,7 @@ public final class TwilightState {
private final long mSunriseTimeMillis;
private final long mSunsetTimeMillis;
TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
public TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
mSunriseTimeMillis = sunriseTimeMillis;
mSunsetTimeMillis = sunsetTimeMillis;
}

View File

@@ -18,6 +18,7 @@
package="com.android.frameworks.servicestests">
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />

View File

@@ -0,0 +1,620 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
import com.android.internal.app.NightDisplayController;
import com.android.internal.app.NightDisplayController.LocalTime;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.display.DisplayTransformManager;
import com.android.server.display.NightDisplayService;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.Calendar;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.Mockito.doReturn;
@RunWith(AndroidJUnit4.class)
public class NightDisplayServiceTest {
private Context mContext;
private int mUserId;
private TwilightManager mTwilightManager;
private NightDisplayController mNightDisplayController;
private NightDisplayService mNightDisplayService;
@Before
public void setUp() {
mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
mUserId = ActivityManager.getCurrentUser();
doReturn(mContext).when(mContext).getApplicationContext();
final MockContentResolver cr = new MockContentResolver(mContext);
cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
doReturn(cr).when(mContext).getContentResolver();
final AlarmManager am = Mockito.mock(AlarmManager.class);
doReturn(am).when(mContext).getSystemService(Context.ALARM_SERVICE);
final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class);
LocalServices.addService(DisplayTransformManager.class, dtm);
mTwilightManager = Mockito.mock(TwilightManager.class);
LocalServices.addService(TwilightManager.class, mTwilightManager);
mNightDisplayController = new NightDisplayController(mContext, mUserId);
mNightDisplayService = new NightDisplayService(mContext);
}
@After
public void tearDown() {
LocalServices.removeServiceForTest(DisplayTransformManager.class);
LocalServices.removeServiceForTest(TwilightManager.class);
mNightDisplayService = null;
mNightDisplayController = null;
mTwilightManager = null;
mUserId = UserHandle.USER_NULL;
mContext = null;
}
@Test
public void customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(false /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
@Test
public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
startService();
assertActivated(true /* activated */);
}
/**
* Convenience for making a {@link LocalTime} instance with an offset relative to now.
*
* @param offsetMinutes the offset relative to now (in minutes)
* @return the LocalTime instance
*/
private LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
final Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, offsetMinutes);
return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
}
/**
* Configures Night display to use a custom schedule.
*
* @param startTimeOffset the offset relative to now to activate Night display (in minutes)
* @param endTimeOffset the offset relative to now to deactivate Night display (in minutes)
*/
private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) {
mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_CUSTOM);
mNightDisplayController.setCustomStartTime(getLocalTimeRelativeToNow(startTimeOffset));
mNightDisplayController.setCustomEndTime(getLocalTimeRelativeToNow(endTimeOffset));
}
/**
* Configures Night display to use the twilight schedule.
*
* @param sunsetOffset the offset relative to now for sunset (in minutes)
* @param sunriseOffset the offset relative to now for sunrise (in minutes)
*/
private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) {
mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_TWILIGHT);
final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
final Calendar now = Calendar.getInstance();
long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis();
long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis();
if (sunsetMillis < sunriseMillis) {
sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis();
} else {
sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis();
}
final TwilightState state = new TwilightState(sunriseMillis, sunsetMillis);
doReturn(state).when(mTwilightManager).getLastTwilightState();
}
/**
* Configures the Night display activated state.
*
* @param activated {@code true} if Night display should be activated
* @param lastActivatedTimeOffset the offset relative to now to record that Night display was
activated (in minutes)
*/
private void setActivated(boolean activated, int lastActivatedTimeOffset) {
mNightDisplayController.setActivated(activated);
final Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, lastActivatedTimeOffset);
Secure.putLongForUser(mContext.getContentResolver(),
Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId);
}
/**
* Convenience method to start {@link #mNightDisplayService}.
*/
private void startService() {
Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
mNightDisplayService.onStart();
mNightDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
mNightDisplayService.onStartUser(mUserId);
}
});
}
/**
* Convenience method for asserting whether Night display should be activated.
*
* @param activated the expected activated state of Night display
*/
private void assertActivated(boolean activated) {
assertWithMessage("Invalid Night display activated state")
.that(mNightDisplayController.isActivated())
.isEqualTo(activated);
}
}