diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index f779b4d96b45f..b0b3b1f3cb5ea 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -319,6 +319,8 @@ public class DeviceIdleController extends SystemService private SensorManager mSensorManager; private final boolean mUseMotionSensor; private Sensor mMotionSensor; + private final boolean mIsLocationPrefetchEnabled; + @Nullable private LocationRequest mLocationRequest; private Intent mIdleIntent; private Bundle mIdleIntentOptions; @@ -2460,6 +2462,11 @@ public class DeviceIdleController extends SystemService return null; } + boolean isLocationPrefetchEnabled() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_autoPowerModePrefetchLocation); + } + boolean useMotionSensor() { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_autoPowerModeUseMotionSensor); @@ -2489,6 +2496,7 @@ public class DeviceIdleController extends SystemService mAppStateTracker = mInjector.getAppStateTracker(context, AppSchedulingModuleThread.get().getLooper()); LocalServices.addService(AppStateTracker.class, mAppStateTracker); + mIsLocationPrefetchEnabled = mInjector.isLocationPrefetchEnabled(); mUseMotionSensor = mInjector.useMotionSensor(); } @@ -2602,8 +2610,7 @@ public class DeviceIdleController extends SystemService mMotionSensor = mInjector.getMotionSensor(); } - if (getContext().getResources().getBoolean( - com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { + if (mIsLocationPrefetchEnabled) { mLocationRequest = new LocationRequest.Builder(/*intervalMillis=*/ 0) .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY) .setMaxUpdates(1) @@ -3779,34 +3786,40 @@ public class DeviceIdleController extends SystemService case STATE_SENSING: cancelSensingTimeoutAlarmLocked(); moveToStateLocked(STATE_LOCATING, reason); - scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT); - LocationManager locationManager = mInjector.getLocationManager(); - if (locationManager != null - && locationManager.getProvider(LocationManager.FUSED_PROVIDER) != null) { - locationManager.requestLocationUpdates(LocationManager.FUSED_PROVIDER, - mLocationRequest, - AppSchedulingModuleThread.getExecutor(), - mGenericLocationListener); - mLocating = true; + if (mIsLocationPrefetchEnabled) { + scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT); + LocationManager locationManager = mInjector.getLocationManager(); + if (locationManager != null + && locationManager.getProvider(LocationManager.FUSED_PROVIDER) + != null) { + locationManager.requestLocationUpdates(LocationManager.FUSED_PROVIDER, + mLocationRequest, + AppSchedulingModuleThread.getExecutor(), + mGenericLocationListener); + mLocating = true; + } else { + mHasFusedLocation = false; + } + if (locationManager != null + && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { + mHasGps = true; + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, + 1000, 5, mGpsLocationListener, mHandler.getLooper()); + mLocating = true; + } else { + mHasGps = false; + } + // If we have a location provider, we're all set, the listeners will move state + // forward. + if (mLocating) { + break; + } + // Otherwise, we have to move from locating into idle maintenance. } else { - mHasFusedLocation = false; - } - if (locationManager != null - && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { - mHasGps = true; - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, - mGpsLocationListener, mHandler.getLooper()); - mLocating = true; - } else { - mHasGps = false; - } - // If we have a location provider, we're all set, the listeners will move state - // forward. - if (mLocating) { - break; + mLocating = false; } - // Otherwise, we have to move from locating into idle maintenance. + // We're not doing any locating work, so move on to the next state. case STATE_LOCATING: cancelAlarmLocked(); cancelLocatingLocked(); @@ -5303,15 +5316,19 @@ public class DeviceIdleController extends SystemService pw.print(" "); pw.print(mStationaryListeners.size()); pw.println(" stationary listeners registered"); } - pw.print(" mLocating="); pw.print(mLocating); - pw.print(" mHasGps="); pw.print(mHasGps); - pw.print(" mHasFused="); pw.print(mHasFusedLocation); - pw.print(" mLocated="); pw.println(mLocated); - if (mLastGenericLocation != null) { - pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); - } - if (mLastGpsLocation != null) { - pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation); + if (mIsLocationPrefetchEnabled) { + pw.print(" mLocating="); pw.print(mLocating); + pw.print(" mHasGps="); pw.print(mHasGps); + pw.print(" mHasFused="); pw.print(mHasFusedLocation); + pw.print(" mLocated="); pw.println(mLocated); + if (mLastGenericLocation != null) { + pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); + } + if (mLastGpsLocation != null) { + pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation); + } + } else { + pw.println(" Location prefetching disabled"); } pw.print(" mState="); pw.print(stateToString(mState)); pw.print(" mLightState="); diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index 3a47b476a131c..2b57c59276784 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -154,6 +154,7 @@ public class DeviceIdleControllerTest { // Freeze time for testing. long nowElapsed; boolean useMotionSensor = true; + boolean isLocationPrefetchEnabled = true; InjectorForTest(Context ctx) { super(ctx); @@ -222,6 +223,11 @@ public class DeviceIdleControllerTest { return mMotionSensor; } + @Override + boolean isLocationPrefetchEnabled() { + return isLocationPrefetchEnabled; + } + @Override PowerManager getPowerManager() { return mPowerManager; @@ -990,6 +996,43 @@ public class DeviceIdleControllerTest { verifyStateConditions(STATE_IDLE_MAINTENANCE); } + @Test + public void testStepIdleStateLocked_ValidStates_LocationPrefetchDisabled() { + mInjector.locationManager = mLocationManager; + mInjector.isLocationPrefetchEnabled = false; + cleanupDeviceIdleController(); + setupDeviceIdleController(); + doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString()); + // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon. + setAlarmSoon(false); + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyStateConditions(STATE_INACTIVE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_PENDING); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_SENSING); + + mDeviceIdleController.stepIdleStateLocked("testing"); + // Prefetch location is off, so SENSING should go straight through to IDLE. + verifyStateConditions(STATE_IDLE); + + // Should just alternate between IDLE and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_MAINTENANCE); + } + @Test public void testStepIdleStateLocked_ValidStates_WithLocationManager_NoProviders() { // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon. @@ -1023,6 +1066,46 @@ public class DeviceIdleControllerTest { verifyStateConditions(STATE_IDLE_MAINTENANCE); } + @Test + public void testStepIdleStateLocked_ValidStates_WithLocationManager_MissingProviders() { + mInjector.locationManager = mLocationManager; + doReturn(null).when(mLocationManager) + .getProvider(eq(LocationManager.FUSED_PROVIDER)); + doReturn(null).when(mLocationManager) + .getProvider(eq(LocationManager.GPS_PROVIDER)); + doReturn(mock(LocationProvider.class)).when(mLocationManager) + .getProvider(eq(LocationManager.NETWORK_PROVIDER)); + // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon. + setAlarmSoon(false); + // Set state to INACTIVE. + mDeviceIdleController.becomeActiveLocked("testing", 0); + setChargingOn(false); + setScreenOn(false); + verifyStateConditions(STATE_INACTIVE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_PENDING); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_SENSING); + + mDeviceIdleController.stepIdleStateLocked("testing"); + // Location manager exists, but the required providers don't exist, + // so SENSING should go straight through to IDLE. + verifyStateConditions(STATE_IDLE); + + // Should just alternate between IDLE and IDLE_MAINTENANCE now. + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_MAINTENANCE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE); + + mDeviceIdleController.stepIdleStateLocked("testing"); + verifyStateConditions(STATE_IDLE_MAINTENANCE); + } + @Test public void testStepIdleStateLocked_ValidStates_WithLocationManager_WithProviders() { mInjector.locationManager = mLocationManager;