Merge "Ensure AlarmManager is brought out of device idle."
This commit is contained in:
committed by
Android (Google) Code Review
commit
29bdd5d13c
@@ -26,6 +26,8 @@ public interface AlarmManagerInternal {
|
||||
void broadcastAlarmComplete(int recipientUid);
|
||||
}
|
||||
|
||||
/** Returns true if AlarmManager is delaying alarms due to device idle. */
|
||||
boolean isIdling();
|
||||
public void removeAlarmsForUid(int uid);
|
||||
public void registerInFlightListener(InFlightListener callback);
|
||||
}
|
||||
|
||||
@@ -1990,6 +1990,11 @@ class AlarmManagerService extends SystemService {
|
||||
* System-process internal API
|
||||
*/
|
||||
private final class LocalService implements AlarmManagerInternal {
|
||||
@Override
|
||||
public boolean isIdling() {
|
||||
return isIdlingImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAlarmsForUid(int uid) {
|
||||
synchronized (mLock) {
|
||||
@@ -2823,6 +2828,12 @@ class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIdlingImpl() {
|
||||
synchronized (mLock) {
|
||||
return mPendingIdleUntil != null;
|
||||
}
|
||||
}
|
||||
|
||||
AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
|
||||
synchronized (mLock) {
|
||||
return mNextAlarmClockForUser.get(userId);
|
||||
|
||||
@@ -271,6 +271,7 @@ public class DeviceIdleController extends SystemService
|
||||
private static final int EVENT_BUFFER_SIZE = 100;
|
||||
|
||||
private AlarmManager mAlarmManager;
|
||||
private AlarmManagerInternal mLocalAlarmManager;
|
||||
private IBatteryStats mBatteryStats;
|
||||
private ActivityManagerInternal mLocalActivityManager;
|
||||
private ActivityTaskManagerInternal mLocalActivityTaskManager;
|
||||
@@ -616,7 +617,8 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
};
|
||||
|
||||
private final AlarmManager.OnAlarmListener mDeepAlarmListener
|
||||
@VisibleForTesting
|
||||
final AlarmManager.OnAlarmListener mDeepAlarmListener
|
||||
= new AlarmManager.OnAlarmListener() {
|
||||
@Override
|
||||
public void onAlarm() {
|
||||
@@ -1874,6 +1876,7 @@ public class DeviceIdleController extends SystemService
|
||||
if (phase == PHASE_SYSTEM_SERVICES_READY) {
|
||||
synchronized (this) {
|
||||
mAlarmManager = mInjector.getAlarmManager();
|
||||
mLocalAlarmManager = getLocalService(AlarmManagerInternal.class);
|
||||
mBatteryStats = BatteryStatsService.getService();
|
||||
mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
|
||||
mLocalActivityTaskManager = getLocalService(ActivityTaskManagerInternal.class);
|
||||
@@ -2605,6 +2608,16 @@ public class DeviceIdleController extends SystemService
|
||||
// next natural time to come out of it.
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if the screen is locked. */
|
||||
@VisibleForTesting
|
||||
boolean isKeyguardShowing() {
|
||||
synchronized (this) {
|
||||
return mScreenLocked;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void keyguardShowingLocked(boolean showing) {
|
||||
if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
|
||||
if (mScreenLocked != showing) {
|
||||
@@ -2616,25 +2629,38 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void scheduleReportActiveLocked(String activeReason, int activeUid) {
|
||||
Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
void becomeActiveLocked(String activeReason, int activeUid) {
|
||||
if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
|
||||
becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
|
||||
}
|
||||
|
||||
private void becomeActiveLocked(String activeReason, int activeUid,
|
||||
long newInactiveTimeout, boolean changeLightIdle) {
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason
|
||||
+ ", changeLightIdle=" + changeLightIdle);
|
||||
}
|
||||
if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
|
||||
EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
|
||||
EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
|
||||
scheduleReportActiveLocked(activeReason, activeUid);
|
||||
mState = STATE_ACTIVE;
|
||||
mLightState = LIGHT_STATE_ACTIVE;
|
||||
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
|
||||
mInactiveTimeout = newInactiveTimeout;
|
||||
mCurIdleBudget = 0;
|
||||
mMaintenanceStartTime = 0;
|
||||
resetIdleManagementLocked();
|
||||
resetLightIdleManagementLocked();
|
||||
addEvent(EVENT_NORMAL, activeReason);
|
||||
|
||||
if (changeLightIdle) {
|
||||
EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
|
||||
mLightState = LIGHT_STATE_ACTIVE;
|
||||
resetLightIdleManagementLocked();
|
||||
// Only report active if light is also ACTIVE.
|
||||
scheduleReportActiveLocked(activeReason, activeUid);
|
||||
addEvent(EVENT_NORMAL, activeReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2654,49 +2680,81 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
/** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
|
||||
private void verifyAlarmStateLocked() {
|
||||
if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
|
||||
Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
|
||||
}
|
||||
if (mState != STATE_IDLE && mLocalAlarmManager.isIdling()) {
|
||||
Slog.wtf(TAG, "mState=" + stateToString(mState) + " but AlarmManager is idling");
|
||||
}
|
||||
if (mState == STATE_IDLE && !mLocalAlarmManager.isIdling()) {
|
||||
Slog.wtf(TAG, "mState=IDLE but AlarmManager is not idling");
|
||||
}
|
||||
if (mLightState == LIGHT_STATE_ACTIVE && mNextLightAlarmTime != 0) {
|
||||
Slog.wtf(TAG, "mLightState=ACTIVE but mNextLightAlarmTime is "
|
||||
+ TimeUtils.formatDuration(mNextLightAlarmTime - SystemClock.elapsedRealtime())
|
||||
+ " from now");
|
||||
}
|
||||
}
|
||||
|
||||
void becomeInactiveIfAppropriateLocked() {
|
||||
if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
|
||||
if ((!mScreenOn && !mCharging) || mForceIdle) {
|
||||
// Become inactive and determine if we will ultimately go idle.
|
||||
if (mDeepEnabled) {
|
||||
if (mQuickDozeActivated) {
|
||||
if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
|
||||
|| mState == STATE_IDLE_MAINTENANCE) {
|
||||
// Already "idling". Don't want to restart the process.
|
||||
// mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
|
||||
// values, so returning here is safe.
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Moved from "
|
||||
+ stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
|
||||
}
|
||||
mState = STATE_QUICK_DOZE_DELAY;
|
||||
// Make sure any motion sensing or locating is stopped.
|
||||
resetIdleManagementLocked();
|
||||
// Wait a small amount of time in case something (eg: background service from
|
||||
// recently closed app) needs to finish running.
|
||||
scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
|
||||
EventLogTags.writeDeviceIdle(mState, "no activity");
|
||||
} else if (mState == STATE_ACTIVE) {
|
||||
mState = STATE_INACTIVE;
|
||||
if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
|
||||
resetIdleManagementLocked();
|
||||
long delay = mInactiveTimeout;
|
||||
if (shouldUseIdleTimeoutFactorLocked()) {
|
||||
delay = (long) (mPreIdleFactor * delay);
|
||||
}
|
||||
scheduleAlarmLocked(delay, false);
|
||||
EventLogTags.writeDeviceIdle(mState, "no activity");
|
||||
verifyAlarmStateLocked();
|
||||
|
||||
final boolean isScreenBlockingInactive =
|
||||
mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
|
||||
+ " isScreenBlockingInactive=" + isScreenBlockingInactive
|
||||
+ " (mScreenOn=" + mScreenOn
|
||||
+ ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
|
||||
+ ", mScreenLocked=" + mScreenLocked + ")"
|
||||
+ " mCharging=" + mCharging
|
||||
+ " mForceIdle=" + mForceIdle
|
||||
);
|
||||
}
|
||||
if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
|
||||
return;
|
||||
}
|
||||
// Become inactive and determine if we will ultimately go idle.
|
||||
if (mDeepEnabled) {
|
||||
if (mQuickDozeActivated) {
|
||||
if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
|
||||
|| mState == STATE_IDLE_MAINTENANCE) {
|
||||
// Already "idling". Don't want to restart the process.
|
||||
// mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
|
||||
// values, so returning here is safe.
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Moved from "
|
||||
+ stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
|
||||
}
|
||||
mState = STATE_QUICK_DOZE_DELAY;
|
||||
// Make sure any motion sensing or locating is stopped.
|
||||
resetIdleManagementLocked();
|
||||
// Wait a small amount of time in case something (eg: background service from
|
||||
// recently closed app) needs to finish running.
|
||||
scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
|
||||
EventLogTags.writeDeviceIdle(mState, "no activity");
|
||||
} else if (mState == STATE_ACTIVE) {
|
||||
mState = STATE_INACTIVE;
|
||||
if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
|
||||
resetIdleManagementLocked();
|
||||
long delay = mInactiveTimeout;
|
||||
if (shouldUseIdleTimeoutFactorLocked()) {
|
||||
delay = (long) (mPreIdleFactor * delay);
|
||||
}
|
||||
scheduleAlarmLocked(delay, false);
|
||||
EventLogTags.writeDeviceIdle(mState, "no activity");
|
||||
}
|
||||
if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
|
||||
mLightState = LIGHT_STATE_INACTIVE;
|
||||
if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
|
||||
resetLightIdleManagementLocked();
|
||||
scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
|
||||
EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
|
||||
}
|
||||
}
|
||||
if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
|
||||
mLightState = LIGHT_STATE_INACTIVE;
|
||||
if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
|
||||
resetLightIdleManagementLocked();
|
||||
scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
|
||||
EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3216,33 +3274,10 @@ public class DeviceIdleController extends SystemService
|
||||
// The device is not yet active, so we want to go back to the pending idle
|
||||
// state to wait again for no motion. Note that we only monitor for motion
|
||||
// after moving out of the inactive state, so no need to worry about that.
|
||||
boolean becomeInactive = false;
|
||||
if (mState != STATE_ACTIVE) {
|
||||
// Motion shouldn't affect light state, if it's already in doze-light or maintenance
|
||||
boolean lightIdle = mLightState == LIGHT_STATE_IDLE
|
||||
|| mLightState == LIGHT_STATE_WAITING_FOR_NETWORK
|
||||
|| mLightState == LIGHT_STATE_IDLE_MAINTENANCE;
|
||||
if (!lightIdle) {
|
||||
// Only switch to active state if we're not in either idle state
|
||||
scheduleReportActiveLocked(type, Process.myUid());
|
||||
addEvent(EVENT_NORMAL, type);
|
||||
}
|
||||
mActiveReason = ACTIVE_REASON_MOTION;
|
||||
mState = STATE_ACTIVE;
|
||||
mInactiveTimeout = timeout;
|
||||
mCurIdleBudget = 0;
|
||||
mMaintenanceStartTime = 0;
|
||||
EventLogTags.writeDeviceIdle(mState, type);
|
||||
becomeInactive = true;
|
||||
updateActiveConstraintsLocked();
|
||||
}
|
||||
if (mLightState == LIGHT_STATE_OVERRIDE) {
|
||||
// We went out of light idle mode because we had started deep idle mode... let's
|
||||
// now go back and reset things so we resume light idling if appropriate.
|
||||
mLightState = LIGHT_STATE_ACTIVE;
|
||||
EventLogTags.writeDeviceIdleLight(mLightState, type);
|
||||
becomeInactive = true;
|
||||
}
|
||||
final boolean becomeInactive = mState != STATE_ACTIVE
|
||||
|| mLightState == LIGHT_STATE_OVERRIDE;
|
||||
// We only want to change the IDLE state if it's OVERRIDE.
|
||||
becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);
|
||||
if (becomeInactive) {
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static androidx.test.InstrumentationRegistry.getContext;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
@@ -51,6 +52,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AlarmManager;
|
||||
@@ -82,6 +86,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
@@ -105,6 +110,8 @@ public class DeviceIdleControllerTest {
|
||||
@Mock
|
||||
private ContentResolver mContentResolver;
|
||||
@Mock
|
||||
private DeviceIdleController.MyHandler mHandler;
|
||||
@Mock
|
||||
private IActivityManager mIActivityManager;
|
||||
@Mock
|
||||
private LocationManager mLocationManager;
|
||||
@@ -154,7 +161,7 @@ public class DeviceIdleControllerTest {
|
||||
|
||||
@Override
|
||||
DeviceIdleController.MyHandler getHandler(DeviceIdleController controller) {
|
||||
return mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,10 +239,12 @@ public class DeviceIdleControllerTest {
|
||||
.when(() -> LocalServices.getService(ActivityManagerInternal.class));
|
||||
doReturn(mock(ActivityTaskManagerInternal.class))
|
||||
.when(() -> LocalServices.getService(ActivityTaskManagerInternal.class));
|
||||
doReturn(mock(AlarmManagerInternal.class))
|
||||
.when(() -> LocalServices.getService(AlarmManagerInternal.class));
|
||||
doReturn(mPowerManagerInternal)
|
||||
.when(() -> LocalServices.getService(PowerManagerInternal.class));
|
||||
when(mPowerManagerInternal.getLowPowerState(anyInt())).thenReturn(
|
||||
mock(PowerSaveState.class));
|
||||
when(mPowerManagerInternal.getLowPowerState(anyInt()))
|
||||
.thenReturn(mock(PowerSaveState.class));
|
||||
doReturn(mock(NetworkPolicyManagerInternal.class))
|
||||
.when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class));
|
||||
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
|
||||
@@ -246,8 +255,11 @@ public class DeviceIdleControllerTest {
|
||||
doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
|
||||
mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
|
||||
mAnyMotionDetector = new AnyMotionDetectorForTest();
|
||||
mHandler = mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
|
||||
doNothing().when(mHandler).handleMessage(any());
|
||||
mInjector = new InjectorForTest(getContext());
|
||||
doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any());
|
||||
|
||||
mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
|
||||
spyOn(mDeviceIdleController);
|
||||
doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
|
||||
@@ -423,6 +435,29 @@ public class DeviceIdleControllerTest {
|
||||
|
||||
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
|
||||
mConstants.WAIT_FOR_UNLOCK = false;
|
||||
setScreenLocked(true);
|
||||
setScreenOn(true);
|
||||
setChargingOn(false);
|
||||
|
||||
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
|
||||
setScreenLocked(false);
|
||||
setScreenOn(true);
|
||||
setChargingOn(false);
|
||||
|
||||
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
|
||||
mConstants.WAIT_FOR_UNLOCK = true;
|
||||
setScreenLocked(false);
|
||||
setScreenOn(true);
|
||||
setChargingOn(false);
|
||||
|
||||
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1307,7 +1342,7 @@ public class DeviceIdleControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testbecomeActiveLocked_deep() {
|
||||
public void testBecomeActiveLocked_deep() {
|
||||
// becomeActiveLocked should put everything into ACTIVE.
|
||||
|
||||
enterDeepState(STATE_ACTIVE);
|
||||
@@ -1344,7 +1379,7 @@ public class DeviceIdleControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testbecomeActiveLocked_light() {
|
||||
public void testBecomeActiveLocked_light() {
|
||||
// becomeActiveLocked should put everything into ACTIVE.
|
||||
|
||||
enterLightState(LIGHT_STATE_ACTIVE);
|
||||
@@ -1376,6 +1411,163 @@ public class DeviceIdleControllerTest {
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
/** Test based on b/119058625. */
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_ScreenThenMotion() {
|
||||
mConstants.WAIT_FOR_UNLOCK = true;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
mDeviceIdleController.keyguardShowingLocked(true);
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
|
||||
// shouldn't bring the device out of deep IDLE.
|
||||
verifyStateConditions(STATE_IDLE);
|
||||
mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
|
||||
// Motion should bring the device out of Doze. Since the screen is still locked (albeit
|
||||
// on), the states should go back into INACTIVE.
|
||||
verifyStateConditions(STATE_INACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
|
||||
verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
/** Test based on b/119058625. */
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_ScreenThenMotion() {
|
||||
mConstants.WAIT_FOR_UNLOCK = true;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
mDeviceIdleController.keyguardShowingLocked(false);
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
|
||||
// should bring the device out of deep IDLE.
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
/** Test based on b/119058625. */
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_MotionThenScreen() {
|
||||
mConstants.WAIT_FOR_UNLOCK = true;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
InOrder alarmManagerInOrder = inOrder(mAlarmManager);
|
||||
InOrder controllerInOrder = inOrder(mDeviceIdleController);
|
||||
|
||||
mDeviceIdleController.keyguardShowingLocked(true);
|
||||
mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
|
||||
// The screen is still off, so motion should result in the INACTIVE state.
|
||||
verifyStateConditions(STATE_INACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
|
||||
// shouldn't bring the device all the way to ACTIVE.
|
||||
verifyStateConditions(STATE_INACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager, never()).cancel(
|
||||
eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
|
||||
// User finally unlocks the device. Device should be fully active.
|
||||
mDeviceIdleController.keyguardShowingLocked(false);
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
/** Test based on b/119058625. */
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_MotionThenScreen() {
|
||||
mConstants.WAIT_FOR_UNLOCK = true;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
InOrder alarmManagerInOrder = inOrder(mAlarmManager);
|
||||
InOrder controllerInOrder = inOrder(mDeviceIdleController);
|
||||
|
||||
mDeviceIdleController.keyguardShowingLocked(false);
|
||||
mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
|
||||
// The screen is still off, so motion should result in the INACTIVE state.
|
||||
verifyStateConditions(STATE_INACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
|
||||
// should bring the device out of deep IDLE.
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOff_Screen() {
|
||||
mConstants.WAIT_FOR_UNLOCK = false;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
|
||||
// should bring the device out of deep IDLE.
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitNotifiesDependencies_WaitForUnlockOff_MotionThenScreen() {
|
||||
mConstants.WAIT_FOR_UNLOCK = false;
|
||||
enterDeepState(STATE_IDLE);
|
||||
reset(mAlarmManager);
|
||||
spyOn(mDeviceIdleController);
|
||||
|
||||
InOrder alarmManagerInOrder = inOrder(mAlarmManager);
|
||||
InOrder controllerInOrder = inOrder(mDeviceIdleController);
|
||||
|
||||
mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
|
||||
// The screen is still off, so motion should result in the INACTIVE state.
|
||||
verifyStateConditions(STATE_INACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
|
||||
setScreenOn(true);
|
||||
// With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
|
||||
// should bring the device out of deep IDLE.
|
||||
verifyStateConditions(STATE_ACTIVE);
|
||||
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
|
||||
alarmManagerInOrder.verify(mAlarmManager)
|
||||
.cancel(eq(mDeviceIdleController.mDeepAlarmListener));
|
||||
controllerInOrder.verify(mDeviceIdleController)
|
||||
.scheduleReportActiveLocked(anyString(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStepToIdleMode() {
|
||||
float delta = mDeviceIdleController.MIN_PRE_IDLE_FACTOR_CHANGE;
|
||||
@@ -1508,6 +1700,10 @@ public class DeviceIdleControllerTest {
|
||||
mDeviceIdleController.updateChargingLocked(on);
|
||||
}
|
||||
|
||||
private void setScreenLocked(boolean locked) {
|
||||
mDeviceIdleController.keyguardShowingLocked(locked);
|
||||
}
|
||||
|
||||
private void setScreenOn(boolean on) {
|
||||
doReturn(on).when(mPowerManager).isInteractive();
|
||||
mDeviceIdleController.updateInteractivityLocked();
|
||||
@@ -1549,7 +1745,8 @@ public class DeviceIdleControllerTest {
|
||||
assertFalse(mDeviceIdleController.mMotionListener.isActive());
|
||||
assertFalse(mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
case STATE_IDLE_PENDING:
|
||||
assertEquals(
|
||||
@@ -1557,7 +1754,8 @@ public class DeviceIdleControllerTest {
|
||||
mDeviceIdleController.mMotionListener.isActive());
|
||||
assertFalse(mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
case STATE_SENSING:
|
||||
assertEquals(
|
||||
@@ -1567,14 +1765,16 @@ public class DeviceIdleControllerTest {
|
||||
mDeviceIdleController.hasMotionSensor(),
|
||||
mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
case STATE_LOCATING:
|
||||
assertEquals(
|
||||
mDeviceIdleController.hasMotionSensor(),
|
||||
mDeviceIdleController.mMotionListener.isActive());
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
case STATE_IDLE:
|
||||
if (mDeviceIdleController.hasMotionSensor()) {
|
||||
@@ -1584,7 +1784,8 @@ public class DeviceIdleControllerTest {
|
||||
}
|
||||
assertFalse(mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
// Light state should be OVERRIDE at this point.
|
||||
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
|
||||
break;
|
||||
@@ -1596,14 +1797,16 @@ public class DeviceIdleControllerTest {
|
||||
}
|
||||
assertFalse(mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
case STATE_QUICK_DOZE_DELAY:
|
||||
// If quick doze is enabled, the motion listener should NOT be active.
|
||||
assertFalse(mDeviceIdleController.mMotionListener.isActive());
|
||||
assertFalse(mAnyMotionDetector.isMonitoring);
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
default:
|
||||
fail("Conditions for " + stateToString(expectedState) + " unknown.");
|
||||
@@ -1632,7 +1835,8 @@ public class DeviceIdleControllerTest {
|
||||
case LIGHT_STATE_IDLE_MAINTENANCE:
|
||||
case LIGHT_STATE_OVERRIDE:
|
||||
assertFalse(mDeviceIdleController.isCharging());
|
||||
assertFalse(mDeviceIdleController.isScreenOn());
|
||||
assertFalse(mDeviceIdleController.isScreenOn()
|
||||
&& !mDeviceIdleController.isKeyguardShowing());
|
||||
break;
|
||||
default:
|
||||
fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
|
||||
|
||||
Reference in New Issue
Block a user