Loading apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +84 −6 Original line number Diff line number Diff line Loading @@ -79,6 +79,9 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.provider.DeviceConfig; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; Loading Loading @@ -146,15 +149,17 @@ import java.util.stream.Collectors; label="deep"; STATE_ACTIVE [ label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon", label="STATE_ACTIVE\nScreen on OR charging OR alarm going off soon\n" + "OR active emergency call", color=black,shape=diamond ] STATE_INACTIVE [ label="STATE_INACTIVE\nScreen off AND Not charging",color=black,shape=diamond label="STATE_INACTIVE\nScreen off AND not charging AND no active emergency call", color=black,shape=diamond ] STATE_QUICK_DOZE_DELAY [ label="STATE_QUICK_DOZE_DELAY\n" + "Screen off AND Not charging\n" + "Screen off AND not charging AND no active emergency call\n" + "Location, motion detection, and significant motion monitoring turned off", color=black,shape=diamond ] Loading Loading @@ -237,11 +242,12 @@ import java.util.stream.Collectors; label="light" LIGHT_STATE_ACTIVE [ label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon", label="LIGHT_STATE_ACTIVE\n" + "Screen on OR charging OR alarm going off soon OR active emergency call", color=black,shape=diamond ] LIGHT_STATE_INACTIVE [ label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging", label="LIGHT_STATE_INACTIVE\nScreen off AND not charging AND no active emergency call", color=black,shape=diamond ] LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box] Loading Loading @@ -411,6 +417,7 @@ public class DeviceIdleController extends SystemService private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5; private static final int ACTIVE_REASON_FORCED = 6; private static final int ACTIVE_REASON_ALARM = 7; private static final int ACTIVE_REASON_EMERGENCY_CALL = 8; @VisibleForTesting static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1; @VisibleForTesting Loading Loading @@ -765,6 +772,8 @@ public class DeviceIdleController extends SystemService } }; private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener(); /** Post stationary status only to this listener. */ private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) { mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget(); Loading Loading @@ -2323,6 +2332,39 @@ public class DeviceIdleController extends SystemService } } private class EmergencyCallListener extends TelephonyCallback implements TelephonyCallback.OutgoingEmergencyCallListener, TelephonyCallback.CallStateListener { private volatile boolean mIsEmergencyCallActive; @Override public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, int subscriptionId) { mIsEmergencyCallActive = true; if (DEBUG) Slog.d(TAG, "onOutgoingEmergencyCall(): subId = " + subscriptionId); synchronized (DeviceIdleController.this) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency call", Process.myUid()); } } @Override public void onCallStateChanged(int state) { if (DEBUG) Slog.d(TAG, "onCallStateChanged(): state is " + state); // An emergency call just finished if (state == TelephonyManager.CALL_STATE_IDLE && mIsEmergencyCallActive) { mIsEmergencyCallActive = false; synchronized (DeviceIdleController.this) { becomeInactiveIfAppropriateLocked(); } } } boolean isEmergencyCallActive() { return mIsEmergencyCallActive; } } static class Injector { private final Context mContext; private ConnectivityManager mConnectivityManager; Loading Loading @@ -2406,6 +2448,10 @@ public class DeviceIdleController extends SystemService return mContext.getSystemService(SensorManager.class); } TelephonyManager getTelephonyManager() { return mContext.getSystemService(TelephonyManager.class); } ConstraintController getConstraintController(Handler handler, DeviceIdleInternal localService) { if (mContext.getPackageManager() Loading Loading @@ -2634,6 +2680,9 @@ public class DeviceIdleController extends SystemService mLocalActivityTaskManager.registerScreenObserver(mScreenObserver); mInjector.getTelephonyManager().registerTelephonyCallback( JobSchedulerBackgroundThread.getExecutor(), mEmergencyCallListener); passWhiteListsToForceAppStandbyTrackerLocked(); updateInteractivityLocked(); } Loading Loading @@ -3435,6 +3484,7 @@ public class DeviceIdleController extends SystemService final boolean isScreenBlockingInactive = mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked); final boolean isEmergencyCallActive = mEmergencyCallListener.isEmergencyCallActive(); if (DEBUG) { Slog.d(TAG, "becomeInactiveIfAppropriateLocked():" + " isScreenBlockingInactive=" + isScreenBlockingInactive Loading @@ -3442,10 +3492,11 @@ public class DeviceIdleController extends SystemService + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK + ", mScreenLocked=" + mScreenLocked + ")" + " mCharging=" + mCharging + " emergencyCall=" + isEmergencyCallActive + " mForceIdle=" + mForceIdle ); } if (!mForceIdle && (mCharging || isScreenBlockingInactive)) { if (!mForceIdle && (mCharging || isScreenBlockingInactive || isEmergencyCallActive)) { return; } // Become inactive and determine if we will ultimately go idle. Loading Loading @@ -3568,6 +3619,17 @@ public class DeviceIdleController extends SystemService } EventLogTags.writeDeviceIdleLightStep(); if (mEmergencyCallListener.isEmergencyCallActive()) { // The emergency call should have raised the state to ACTIVE and kept it there, // so this method shouldn't be called. Don't proceed further. Slog.wtf(TAG, "stepLightIdleStateLocked called when emergency call is active"); if (mLightState != LIGHT_STATE_ACTIVE) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency", Process.myUid()); } return; } switch (mLightState) { case LIGHT_STATE_INACTIVE: mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; Loading Loading @@ -3650,6 +3712,17 @@ public class DeviceIdleController extends SystemService if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState); EventLogTags.writeDeviceIdleStep(); if (mEmergencyCallListener.isEmergencyCallActive()) { // The emergency call should have raised the state to ACTIVE and kept it there, // so this method shouldn't be called. Don't proceed further. Slog.wtf(TAG, "stepIdleStateLocked called when emergency call is active"); if (mState != STATE_ACTIVE) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency", Process.myUid()); } return; } if (isUpcomingAlarmClock()) { // Whoops, there is an upcoming alarm. We don't actually want to go idle. if (mState != STATE_ACTIVE) { Loading Loading @@ -3984,6 +4057,11 @@ public class DeviceIdleController extends SystemService } } @VisibleForTesting boolean isEmergencyCallActive() { return mEmergencyCallListener.isEmergencyCallActive(); } @GuardedBy("this") boolean isOpsInactiveLocked() { return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive; Loading services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +148 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.SystemClock; import android.provider.DeviceConfig; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import androidx.test.runner.AndroidJUnit4; Loading Loading @@ -119,6 +122,8 @@ public class DeviceIdleControllerTest { private AnyMotionDetectorForTest mAnyMotionDetector; private AppStateTrackerForTest mAppStateTracker; private DeviceIdleController.Constants mConstants; private TelephonyCallback.OutgoingEmergencyCallListener mEmergencyCallListener; private TelephonyCallback.CallStateListener mCallStateListener; private InjectorForTest mInjector; private MockitoSession mMockingSession; Loading @@ -140,6 +145,8 @@ public class DeviceIdleControllerTest { private Sensor mMotionSensor; @Mock private SensorManager mSensorManager; @Mock private TelephonyManager mTelephonyManager; class InjectorForTest extends DeviceIdleController.Injector { ConnectivityManager connectivityManager; Loading Loading @@ -231,6 +238,11 @@ public class DeviceIdleControllerTest { return constraintController; } @Override TelephonyManager getTelephonyManager() { return mTelephonyManager; } @Override boolean useMotionSensor() { return true; Loading Loading @@ -343,6 +355,15 @@ public class DeviceIdleControllerTest { // Get the same Constants object that mDeviceIdleController got. mConstants = mInjector.getConstants(mDeviceIdleController); final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor = ArgumentCaptor.forClass(TelephonyCallback.class); verify(mTelephonyManager) .registerTelephonyCallback(any(), telephonyCallbackCaptor.capture()); mEmergencyCallListener = (TelephonyCallback.OutgoingEmergencyCallListener) telephonyCallbackCaptor.getValue(); mCallStateListener = (TelephonyCallback.CallStateListener) telephonyCallbackCaptor.getValue(); } @After Loading Loading @@ -531,6 +552,16 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_ACTIVE); // All other conditions allow for going INACTIVE... setAlarmSoon(false); setChargingOn(false); setScreenOn(false); // ...except the emergency call. setEmergencyCallActive(true); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_ACTIVE); } @Test Loading Loading @@ -559,6 +590,15 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_ACTIVE); // All other conditions allow for going INACTIVE... setChargingOn(false); setScreenOn(false); // ...except the emergency call. setEmergencyCallActive(true); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_ACTIVE); } @Test Loading @@ -569,6 +609,7 @@ public class DeviceIdleControllerTest { setAlarmSoon(false); setChargingOn(false); setScreenOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_INACTIVE); Loading Loading @@ -613,6 +654,7 @@ public class DeviceIdleControllerTest { setChargingOn(false); setScreenOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_INACTIVE); Loading Loading @@ -1147,6 +1189,22 @@ public class DeviceIdleControllerTest { eq(true)); } @Test public void testEmergencyCallEndTriggersInactive() { setAlarmSoon(false); setChargingOn(false); setScreenOn(false); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); verifyLightStateConditions(LIGHT_STATE_ACTIVE); setEmergencyCallActive(false); verifyStateConditions(STATE_INACTIVE); verifyLightStateConditions(LIGHT_STATE_INACTIVE); } ///////////////// EXIT conditions /////////////////// @Test Loading Loading @@ -2096,6 +2154,75 @@ public class DeviceIdleControllerTest { .onDeviceStationaryChanged(eq(true)); } @Test public void testEmergencyEndsIdle() { enterDeepState(STATE_ACTIVE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_INACTIVE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE_PENDING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_SENSING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_LOCATING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); // Quick doze enabled or not shouldn't affect the end state. enterDeepState(STATE_QUICK_DOZE_DELAY); setQuickDozeEnabled(true); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_QUICK_DOZE_DELAY); setQuickDozeEnabled(false); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE_MAINTENANCE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); } @Test public void testEmergencyEndsLightIdle() { enterLightState(LIGHT_STATE_ACTIVE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_INACTIVE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_IDLE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_IDLE_MAINTENANCE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_OVERRIDE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); } private void enterDeepState(int state) { switch (state) { case STATE_ACTIVE: Loading @@ -2108,6 +2235,7 @@ public class DeviceIdleControllerTest { setQuickDozeEnabled(true); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); break; case STATE_LOCATING: Loading @@ -2128,6 +2256,7 @@ public class DeviceIdleControllerTest { setQuickDozeEnabled(false); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); int count = 0; while (mDeviceIdleController.getState() != state) { Loading Loading @@ -2159,6 +2288,7 @@ public class DeviceIdleControllerTest { enterLightState(LIGHT_STATE_ACTIVE); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); int count = 0; mDeviceIdleController.becomeInactiveIfAppropriateLocked(); while (mDeviceIdleController.getLightState() != lightState) { Loading @@ -2177,6 +2307,7 @@ public class DeviceIdleControllerTest { case LIGHT_STATE_OVERRIDE: setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.setLightStateForTest(lightState); break; default: Loading @@ -2188,6 +2319,14 @@ public class DeviceIdleControllerTest { mDeviceIdleController.updateChargingLocked(on); } private void setEmergencyCallActive(boolean active) { if (active) { mEmergencyCallListener.onOutgoingEmergencyCall(mock(EmergencyNumber.class), 0); } else { mCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE); } } private void setScreenLocked(boolean locked) { mDeviceIdleController.keyguardShowingLocked(locked); } Loading Loading @@ -2235,6 +2374,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE_PENDING: assertEquals( Loading @@ -2244,6 +2384,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_SENSING: assertEquals( Loading @@ -2255,6 +2396,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_LOCATING: assertEquals( Loading @@ -2263,6 +2405,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE: if (mDeviceIdleController.hasMotionSensor()) { Loading @@ -2276,6 +2419,7 @@ public class DeviceIdleControllerTest { && !mDeviceIdleController.isKeyguardShowing()); // Light state should be OVERRIDE at this point. verifyLightStateConditions(LIGHT_STATE_OVERRIDE); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE_MAINTENANCE: if (mDeviceIdleController.hasMotionSensor()) { Loading @@ -2287,6 +2431,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_QUICK_DOZE_DELAY: // If quick doze is enabled, the motion listener should NOT be active. Loading @@ -2295,6 +2440,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; default: fail("Conditions for " + stateToString(expectedState) + " unknown."); Loading @@ -2312,6 +2458,7 @@ public class DeviceIdleControllerTest { case LIGHT_STATE_ACTIVE: assertTrue( mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn() || mDeviceIdleController.isEmergencyCallActive() // Or there's an alarm coming up soon. || SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM > mAlarmManager.getNextWakeFromIdleTime()); Loading @@ -2324,6 +2471,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; default: fail("Conditions for " + lightStateToString(expectedLightState) + " unknown."); Loading Loading
apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +84 −6 Original line number Diff line number Diff line Loading @@ -79,6 +79,9 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.provider.DeviceConfig; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; Loading Loading @@ -146,15 +149,17 @@ import java.util.stream.Collectors; label="deep"; STATE_ACTIVE [ label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon", label="STATE_ACTIVE\nScreen on OR charging OR alarm going off soon\n" + "OR active emergency call", color=black,shape=diamond ] STATE_INACTIVE [ label="STATE_INACTIVE\nScreen off AND Not charging",color=black,shape=diamond label="STATE_INACTIVE\nScreen off AND not charging AND no active emergency call", color=black,shape=diamond ] STATE_QUICK_DOZE_DELAY [ label="STATE_QUICK_DOZE_DELAY\n" + "Screen off AND Not charging\n" + "Screen off AND not charging AND no active emergency call\n" + "Location, motion detection, and significant motion monitoring turned off", color=black,shape=diamond ] Loading Loading @@ -237,11 +242,12 @@ import java.util.stream.Collectors; label="light" LIGHT_STATE_ACTIVE [ label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon", label="LIGHT_STATE_ACTIVE\n" + "Screen on OR charging OR alarm going off soon OR active emergency call", color=black,shape=diamond ] LIGHT_STATE_INACTIVE [ label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging", label="LIGHT_STATE_INACTIVE\nScreen off AND not charging AND no active emergency call", color=black,shape=diamond ] LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box] Loading Loading @@ -411,6 +417,7 @@ public class DeviceIdleController extends SystemService private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5; private static final int ACTIVE_REASON_FORCED = 6; private static final int ACTIVE_REASON_ALARM = 7; private static final int ACTIVE_REASON_EMERGENCY_CALL = 8; @VisibleForTesting static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1; @VisibleForTesting Loading Loading @@ -765,6 +772,8 @@ public class DeviceIdleController extends SystemService } }; private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener(); /** Post stationary status only to this listener. */ private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) { mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget(); Loading Loading @@ -2323,6 +2332,39 @@ public class DeviceIdleController extends SystemService } } private class EmergencyCallListener extends TelephonyCallback implements TelephonyCallback.OutgoingEmergencyCallListener, TelephonyCallback.CallStateListener { private volatile boolean mIsEmergencyCallActive; @Override public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, int subscriptionId) { mIsEmergencyCallActive = true; if (DEBUG) Slog.d(TAG, "onOutgoingEmergencyCall(): subId = " + subscriptionId); synchronized (DeviceIdleController.this) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency call", Process.myUid()); } } @Override public void onCallStateChanged(int state) { if (DEBUG) Slog.d(TAG, "onCallStateChanged(): state is " + state); // An emergency call just finished if (state == TelephonyManager.CALL_STATE_IDLE && mIsEmergencyCallActive) { mIsEmergencyCallActive = false; synchronized (DeviceIdleController.this) { becomeInactiveIfAppropriateLocked(); } } } boolean isEmergencyCallActive() { return mIsEmergencyCallActive; } } static class Injector { private final Context mContext; private ConnectivityManager mConnectivityManager; Loading Loading @@ -2406,6 +2448,10 @@ public class DeviceIdleController extends SystemService return mContext.getSystemService(SensorManager.class); } TelephonyManager getTelephonyManager() { return mContext.getSystemService(TelephonyManager.class); } ConstraintController getConstraintController(Handler handler, DeviceIdleInternal localService) { if (mContext.getPackageManager() Loading Loading @@ -2634,6 +2680,9 @@ public class DeviceIdleController extends SystemService mLocalActivityTaskManager.registerScreenObserver(mScreenObserver); mInjector.getTelephonyManager().registerTelephonyCallback( JobSchedulerBackgroundThread.getExecutor(), mEmergencyCallListener); passWhiteListsToForceAppStandbyTrackerLocked(); updateInteractivityLocked(); } Loading Loading @@ -3435,6 +3484,7 @@ public class DeviceIdleController extends SystemService final boolean isScreenBlockingInactive = mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked); final boolean isEmergencyCallActive = mEmergencyCallListener.isEmergencyCallActive(); if (DEBUG) { Slog.d(TAG, "becomeInactiveIfAppropriateLocked():" + " isScreenBlockingInactive=" + isScreenBlockingInactive Loading @@ -3442,10 +3492,11 @@ public class DeviceIdleController extends SystemService + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK + ", mScreenLocked=" + mScreenLocked + ")" + " mCharging=" + mCharging + " emergencyCall=" + isEmergencyCallActive + " mForceIdle=" + mForceIdle ); } if (!mForceIdle && (mCharging || isScreenBlockingInactive)) { if (!mForceIdle && (mCharging || isScreenBlockingInactive || isEmergencyCallActive)) { return; } // Become inactive and determine if we will ultimately go idle. Loading Loading @@ -3568,6 +3619,17 @@ public class DeviceIdleController extends SystemService } EventLogTags.writeDeviceIdleLightStep(); if (mEmergencyCallListener.isEmergencyCallActive()) { // The emergency call should have raised the state to ACTIVE and kept it there, // so this method shouldn't be called. Don't proceed further. Slog.wtf(TAG, "stepLightIdleStateLocked called when emergency call is active"); if (mLightState != LIGHT_STATE_ACTIVE) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency", Process.myUid()); } return; } switch (mLightState) { case LIGHT_STATE_INACTIVE: mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; Loading Loading @@ -3650,6 +3712,17 @@ public class DeviceIdleController extends SystemService if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState); EventLogTags.writeDeviceIdleStep(); if (mEmergencyCallListener.isEmergencyCallActive()) { // The emergency call should have raised the state to ACTIVE and kept it there, // so this method shouldn't be called. Don't proceed further. Slog.wtf(TAG, "stepIdleStateLocked called when emergency call is active"); if (mState != STATE_ACTIVE) { mActiveReason = ACTIVE_REASON_EMERGENCY_CALL; becomeActiveLocked("emergency", Process.myUid()); } return; } if (isUpcomingAlarmClock()) { // Whoops, there is an upcoming alarm. We don't actually want to go idle. if (mState != STATE_ACTIVE) { Loading Loading @@ -3984,6 +4057,11 @@ public class DeviceIdleController extends SystemService } } @VisibleForTesting boolean isEmergencyCallActive() { return mEmergencyCallListener.isEmergencyCallActive(); } @GuardedBy("this") boolean isOpsInactiveLocked() { return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive; Loading
services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +148 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.SystemClock; import android.provider.DeviceConfig; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; import androidx.test.runner.AndroidJUnit4; Loading Loading @@ -119,6 +122,8 @@ public class DeviceIdleControllerTest { private AnyMotionDetectorForTest mAnyMotionDetector; private AppStateTrackerForTest mAppStateTracker; private DeviceIdleController.Constants mConstants; private TelephonyCallback.OutgoingEmergencyCallListener mEmergencyCallListener; private TelephonyCallback.CallStateListener mCallStateListener; private InjectorForTest mInjector; private MockitoSession mMockingSession; Loading @@ -140,6 +145,8 @@ public class DeviceIdleControllerTest { private Sensor mMotionSensor; @Mock private SensorManager mSensorManager; @Mock private TelephonyManager mTelephonyManager; class InjectorForTest extends DeviceIdleController.Injector { ConnectivityManager connectivityManager; Loading Loading @@ -231,6 +238,11 @@ public class DeviceIdleControllerTest { return constraintController; } @Override TelephonyManager getTelephonyManager() { return mTelephonyManager; } @Override boolean useMotionSensor() { return true; Loading Loading @@ -343,6 +355,15 @@ public class DeviceIdleControllerTest { // Get the same Constants object that mDeviceIdleController got. mConstants = mInjector.getConstants(mDeviceIdleController); final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor = ArgumentCaptor.forClass(TelephonyCallback.class); verify(mTelephonyManager) .registerTelephonyCallback(any(), telephonyCallbackCaptor.capture()); mEmergencyCallListener = (TelephonyCallback.OutgoingEmergencyCallListener) telephonyCallbackCaptor.getValue(); mCallStateListener = (TelephonyCallback.CallStateListener) telephonyCallbackCaptor.getValue(); } @After Loading Loading @@ -531,6 +552,16 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_ACTIVE); // All other conditions allow for going INACTIVE... setAlarmSoon(false); setChargingOn(false); setScreenOn(false); // ...except the emergency call. setEmergencyCallActive(true); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_ACTIVE); } @Test Loading Loading @@ -559,6 +590,15 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_ACTIVE); // All other conditions allow for going INACTIVE... setChargingOn(false); setScreenOn(false); // ...except the emergency call. setEmergencyCallActive(true); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_ACTIVE); } @Test Loading @@ -569,6 +609,7 @@ public class DeviceIdleControllerTest { setAlarmSoon(false); setChargingOn(false); setScreenOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_INACTIVE); Loading Loading @@ -613,6 +654,7 @@ public class DeviceIdleControllerTest { setChargingOn(false); setScreenOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyLightStateConditions(LIGHT_STATE_INACTIVE); Loading Loading @@ -1147,6 +1189,22 @@ public class DeviceIdleControllerTest { eq(true)); } @Test public void testEmergencyCallEndTriggersInactive() { setAlarmSoon(false); setChargingOn(false); setScreenOn(false); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); verifyLightStateConditions(LIGHT_STATE_ACTIVE); setEmergencyCallActive(false); verifyStateConditions(STATE_INACTIVE); verifyLightStateConditions(LIGHT_STATE_INACTIVE); } ///////////////// EXIT conditions /////////////////// @Test Loading Loading @@ -2096,6 +2154,75 @@ public class DeviceIdleControllerTest { .onDeviceStationaryChanged(eq(true)); } @Test public void testEmergencyEndsIdle() { enterDeepState(STATE_ACTIVE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_INACTIVE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE_PENDING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_SENSING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_LOCATING); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); // Quick doze enabled or not shouldn't affect the end state. enterDeepState(STATE_QUICK_DOZE_DELAY); setQuickDozeEnabled(true); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_QUICK_DOZE_DELAY); setQuickDozeEnabled(false); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); enterDeepState(STATE_IDLE_MAINTENANCE); setEmergencyCallActive(true); verifyStateConditions(STATE_ACTIVE); } @Test public void testEmergencyEndsLightIdle() { enterLightState(LIGHT_STATE_ACTIVE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_INACTIVE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_IDLE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_IDLE_MAINTENANCE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); enterLightState(LIGHT_STATE_OVERRIDE); setEmergencyCallActive(true); verifyLightStateConditions(LIGHT_STATE_ACTIVE); } private void enterDeepState(int state) { switch (state) { case STATE_ACTIVE: Loading @@ -2108,6 +2235,7 @@ public class DeviceIdleControllerTest { setQuickDozeEnabled(true); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); break; case STATE_LOCATING: Loading @@ -2128,6 +2256,7 @@ public class DeviceIdleControllerTest { setQuickDozeEnabled(false); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); int count = 0; while (mDeviceIdleController.getState() != state) { Loading Loading @@ -2159,6 +2288,7 @@ public class DeviceIdleControllerTest { enterLightState(LIGHT_STATE_ACTIVE); setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); int count = 0; mDeviceIdleController.becomeInactiveIfAppropriateLocked(); while (mDeviceIdleController.getLightState() != lightState) { Loading @@ -2177,6 +2307,7 @@ public class DeviceIdleControllerTest { case LIGHT_STATE_OVERRIDE: setScreenOn(false); setChargingOn(false); setEmergencyCallActive(false); mDeviceIdleController.setLightStateForTest(lightState); break; default: Loading @@ -2188,6 +2319,14 @@ public class DeviceIdleControllerTest { mDeviceIdleController.updateChargingLocked(on); } private void setEmergencyCallActive(boolean active) { if (active) { mEmergencyCallListener.onOutgoingEmergencyCall(mock(EmergencyNumber.class), 0); } else { mCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE); } } private void setScreenLocked(boolean locked) { mDeviceIdleController.keyguardShowingLocked(locked); } Loading Loading @@ -2235,6 +2374,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE_PENDING: assertEquals( Loading @@ -2244,6 +2384,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_SENSING: assertEquals( Loading @@ -2255,6 +2396,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_LOCATING: assertEquals( Loading @@ -2263,6 +2405,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE: if (mDeviceIdleController.hasMotionSensor()) { Loading @@ -2276,6 +2419,7 @@ public class DeviceIdleControllerTest { && !mDeviceIdleController.isKeyguardShowing()); // Light state should be OVERRIDE at this point. verifyLightStateConditions(LIGHT_STATE_OVERRIDE); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_IDLE_MAINTENANCE: if (mDeviceIdleController.hasMotionSensor()) { Loading @@ -2287,6 +2431,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; case STATE_QUICK_DOZE_DELAY: // If quick doze is enabled, the motion listener should NOT be active. Loading @@ -2295,6 +2440,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; default: fail("Conditions for " + stateToString(expectedState) + " unknown."); Loading @@ -2312,6 +2458,7 @@ public class DeviceIdleControllerTest { case LIGHT_STATE_ACTIVE: assertTrue( mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn() || mDeviceIdleController.isEmergencyCallActive() // Or there's an alarm coming up soon. || SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM > mAlarmManager.getNextWakeFromIdleTime()); Loading @@ -2324,6 +2471,7 @@ public class DeviceIdleControllerTest { assertFalse(mDeviceIdleController.isCharging()); assertFalse(mDeviceIdleController.isScreenOn() && !mDeviceIdleController.isKeyguardShowing()); assertFalse(mDeviceIdleController.isEmergencyCallActive()); break; default: fail("Conditions for " + lightStateToString(expectedLightState) + " unknown."); Loading