Merge "DeviceIdleController light state transition tests."

This commit is contained in:
TreeHugger Robot
2018-10-16 19:11:04 +00:00
committed by Android (Google) Code Review
3 changed files with 281 additions and 34 deletions

View File

@@ -242,11 +242,9 @@ public class DeviceIdleController extends SystemService
private ActivityTaskManagerInternal mLocalActivityTaskManager;
private PowerManagerInternal mLocalPowerManager;
private PowerManager mPowerManager;
private ConnectivityService mConnectivityService;
private INetworkPolicyManager mNetworkPolicyManager;
private SensorManager mSensorManager;
private Sensor mMotionSensor;
private LocationManager mLocationManager;
private LocationRequest mLocationRequest;
private Intent mIdleIntent;
private Intent mLightIdleIntent;
@@ -1508,6 +1506,8 @@ public class DeviceIdleController extends SystemService
static class Injector {
private final Context mContext;
private ConnectivityService mConnectivityService;
private LocationManager mLocationManager;
Injector(Context ctx) {
mContext = ctx;
@@ -1527,7 +1527,11 @@ public class DeviceIdleController extends SystemService
}
ConnectivityService getConnectivityService() {
return (ConnectivityService) ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (mConnectivityService == null) {
mConnectivityService = (ConnectivityService) ServiceManager.getService(
Context.CONNECTIVITY_SERVICE);
}
return mConnectivityService;
}
Constants getConstants(DeviceIdleController controller, Handler handler,
@@ -1536,7 +1540,10 @@ public class DeviceIdleController extends SystemService
}
LocationManager getLocationManager() {
return mContext.getSystemService(LocationManager.class);
if (mLocationManager == null) {
mLocationManager = mContext.getSystemService(LocationManager.class);
}
return mLocationManager;
}
MyHandler getHandler(DeviceIdleController controller) {
@@ -1666,7 +1673,6 @@ public class DeviceIdleController extends SystemService
mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"deviceidle_going_idle");
mGoingIdleWakeLock.setReferenceCounted(true);
mConnectivityService = mInjector.getConnectivityService();
mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class);
@@ -1689,7 +1695,6 @@ public class DeviceIdleController extends SystemService
if (getContext().getResources().getBoolean(
com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
mLocationManager = mInjector.getLocationManager();
mLocationRequest = new LocationRequest()
.setQuality(LocationRequest.ACCURACY_FINE)
.setInterval(0)
@@ -2160,10 +2165,17 @@ public class DeviceIdleController extends SystemService
}
}
@VisibleForTesting
boolean isNetworkConnected() {
synchronized (this) {
return mNetworkConnected;
}
}
void updateConnectivityState(Intent connIntent) {
ConnectivityService cm;
synchronized (this) {
cm = mConnectivityService;
cm = mInjector.getConnectivityService();
}
if (cm == null) {
return;
@@ -2276,13 +2288,17 @@ public class DeviceIdleController extends SystemService
/** Must only be used in tests. */
@VisibleForTesting
void setDeepEnabledForTest(boolean enabled) {
mDeepEnabled = enabled;
synchronized (this) {
mDeepEnabled = enabled;
}
}
/** Must only be used in tests. */
@VisibleForTesting
void setLightEnabledForTest(boolean enabled) {
mLightEnabled = enabled;
synchronized (this) {
mLightEnabled = enabled;
}
}
void becomeInactiveIfAppropriateLocked() {
@@ -2338,7 +2354,9 @@ public class DeviceIdleController extends SystemService
*/
@VisibleForTesting
void setLightStateForTest(int lightState) {
mLightState = lightState;
synchronized (this) {
mLightState = lightState;
}
}
@VisibleForTesting
@@ -2429,12 +2447,6 @@ public class DeviceIdleController extends SystemService
}
}
/** Must only be used in tests. */
@VisibleForTesting
void setLocationManagerForTest(LocationManager lm) {
mLocationManager = lm;
}
@VisibleForTesting
int getState() {
return mState;
@@ -2486,18 +2498,19 @@ public class DeviceIdleController extends SystemService
if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
EventLogTags.writeDeviceIdle(mState, reason);
scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
if (mLocationManager != null
&& mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
mLocationManager.requestLocationUpdates(mLocationRequest,
LocationManager locationManager = mInjector.getLocationManager();
if (locationManager != null
&& locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
locationManager.requestLocationUpdates(mLocationRequest,
mGenericLocationListener, mHandler.getLooper());
mLocating = true;
} else {
mHasNetworkLocation = false;
}
if (mLocationManager != null
&& mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
if (locationManager != null
&& locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
mHasGps = true;
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
mGpsLocationListener, mHandler.getLooper());
mLocating = true;
} else {
@@ -2575,7 +2588,9 @@ public class DeviceIdleController extends SystemService
/** Must only be used in tests. */
@VisibleForTesting
void setActiveIdleOpsForTest(int count) {
mActiveIdleOpCount = count;
synchronized (this) {
mActiveIdleOpCount = count;
}
}
void setJobsActive(boolean active) {
@@ -2751,8 +2766,9 @@ public class DeviceIdleController extends SystemService
void cancelLocatingLocked() {
if (mLocating) {
mLocationManager.removeUpdates(mGenericLocationListener);
mLocationManager.removeUpdates(mGpsLocationListener);
LocationManager locationManager = mInjector.getLocationManager();
locationManager.removeUpdates(mGenericLocationListener);
locationManager.removeUpdates(mGpsLocationListener);
mLocating = false;
}
}

View File

@@ -22,6 +22,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
frameworks-base-testutils \
services.core \
services.net \
androidx-test \
mockito-target-extended-minus-junit4 \
platform-test-annotations \

View File

@@ -41,6 +41,9 @@ import static com.android.server.DeviceIdleController.lightStateToString;
import static com.android.server.DeviceIdleController.stateToString;
import static org.junit.Assert.assertEquals;
import android.net.NetworkInfo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -50,6 +53,8 @@ import static org.mockito.ArgumentMatchers.anyString;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.net.ConnectivityManager;
import android.content.Intent;
import android.app.IActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -83,11 +88,14 @@ public class DeviceIdleControllerTest {
private DeviceIdleController mDeviceIdleController;
private AnyMotionDetectorForTest mAnyMotionDetector;
private AppStateTrackerForTest mAppStateTracker;
private InjectorForTest mInjector;
private MockitoSession mMockingSession;
@Mock
private AlarmManager mAlarmManager;
@Mock
private ConnectivityService mConnectivityService;
@Mock
private DeviceIdleController.Constants mConstants;
@Mock
private IActivityManager mIActivityManager;
@@ -99,6 +107,8 @@ public class DeviceIdleControllerTest {
private PowerManager.WakeLock mWakeLock;
class InjectorForTest extends DeviceIdleController.Injector {
ConnectivityService connectivityService;
LocationManager locationManager;
InjectorForTest(Context ctx) {
super(ctx);
@@ -122,18 +132,19 @@ public class DeviceIdleControllerTest {
@Override
ConnectivityService getConnectivityService() {
return null;
return connectivityService;
}
@Override
DeviceIdleController.Constants getConstants(DeviceIdleController controller, Handler handler,
DeviceIdleController.Constants getConstants(DeviceIdleController controller,
Handler handler,
ContentResolver resolver) {
return mConstants;
}
@Override
LocationManager getLocationManager() {
return mLocationManager;
return locationManager;
}
@Override
@@ -201,8 +212,8 @@ public class DeviceIdleControllerTest {
doNothing().when(mWakeLock).acquire();
mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
mAnyMotionDetector = new AnyMotionDetectorForTest();
mDeviceIdleController = new DeviceIdleController(getContext(),
new InjectorForTest(getContext()));
mInjector = new InjectorForTest(getContext());
mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
spyOn(mDeviceIdleController);
doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
mDeviceIdleController.onStart();
@@ -270,6 +281,60 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
}
@Test
public void testUpdateConnectivityState() {
// No connectivity service
final boolean isConnected = mDeviceIdleController.isNetworkConnected();
mInjector.connectivityService = null;
mDeviceIdleController.updateConnectivityState(null);
assertEquals(isConnected, mDeviceIdleController.isNetworkConnected());
// No active network info
mInjector.connectivityService = mConnectivityService;
doReturn(null).when(mConnectivityService).getActiveNetworkInfo();
mDeviceIdleController.updateConnectivityState(null);
assertFalse(mDeviceIdleController.isNetworkConnected());
// Active network info says connected.
final NetworkInfo ani = mock(NetworkInfo.class);
doReturn(ani).when(mConnectivityService).getActiveNetworkInfo();
doReturn(true).when(ani).isConnected();
mDeviceIdleController.updateConnectivityState(null);
assertTrue(mDeviceIdleController.isNetworkConnected());
// Active network info says not connected.
doReturn(false).when(ani).isConnected();
mDeviceIdleController.updateConnectivityState(null);
assertFalse(mDeviceIdleController.isNetworkConnected());
// Wrong intent passed (false).
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3);
doReturn(true).when(ani).isConnected();
doReturn(1).when(ani).getType();
mDeviceIdleController.updateConnectivityState(intent);
// Wrong intent means we shouldn't update the connected state.
assertFalse(mDeviceIdleController.isNetworkConnected());
// Intent says connected.
doReturn(1).when(ani).getType();
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1);
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
mDeviceIdleController.updateConnectivityState(intent);
assertTrue(mDeviceIdleController.isNetworkConnected());
// Wrong intent passed (true).
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3);
// Wrong intent means we shouldn't update the connected state.
assertTrue(mDeviceIdleController.isNetworkConnected());
// Intent says not connected.
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1);
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
mDeviceIdleController.updateConnectivityState(intent);
assertFalse(mDeviceIdleController.isNetworkConnected());
}
@Test
public void testStateActiveToStateInactive_ConditionsNotMet() {
mDeviceIdleController.becomeActiveLocked("testing", 0);
@@ -361,7 +426,7 @@ public class DeviceIdleControllerTest {
@Test
public void testStepIdleStateLocked_ValidStates_NoLocationManager() {
mDeviceIdleController.setLocationManagerForTest(null);
mInjector.locationManager = null;
// Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
// Set state to INACTIVE.
@@ -427,6 +492,7 @@ public class DeviceIdleControllerTest {
@Test
public void testStepIdleStateLocked_ValidStates_WithLocationManager_WithProviders() {
mInjector.locationManager = mLocationManager;
doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString());
// Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
// TODO: add tests for when there's a wake-from-idle alarm coming soon.
@@ -462,6 +528,160 @@ public class DeviceIdleControllerTest {
verifyStateConditions(STATE_IDLE_MAINTENANCE);
}
@Test
public void testLightStepIdleStateLocked_InvalidStates() {
mDeviceIdleController.becomeActiveLocked("testing", 0);
mDeviceIdleController.stepLightIdleStateLocked("testing");
// stepLightIdleStateLocked doesn't handle the ACTIVE case, so the state
// should stay as ACTIVE.
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
}
/**
* Make sure stepLightIdleStateLocked doesn't change state when the state is
* LIGHT_STATE_OVERRIDE.
*/
@Test
public void testLightStepIdleStateLocked_Overriden() {
enterLightState(LIGHT_STATE_OVERRIDE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
}
@Test
public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NetworkConnected() {
setNetworkConnected(true);
mDeviceIdleController.setJobsActive(false);
mDeviceIdleController.setAlarmsActive(false);
mDeviceIdleController.setActiveIdleOpsForTest(0);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
setScreenOn(false);
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
// No active ops means INACTIVE should go straight to IDLE.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
// Should just alternate between IDLE and IDLE_MAINTENANCE now.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
}
@Test
public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NetworkConnected() {
setNetworkConnected(true);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
setScreenOn(false);
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
// Active ops means INACTIVE should go to PRE_IDLE to wait.
mDeviceIdleController.setJobsActive(true);
mDeviceIdleController.setAlarmsActive(true);
mDeviceIdleController.setActiveIdleOpsForTest(1);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
// Even with active ops, PRE_IDLE should go to IDLE.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
// Should just alternate between IDLE and IDLE_MAINTENANCE now.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
}
@Test
public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NoNetworkConnected() {
setNetworkConnected(false);
mDeviceIdleController.setJobsActive(false);
mDeviceIdleController.setAlarmsActive(false);
mDeviceIdleController.setActiveIdleOpsForTest(0);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
setScreenOn(false);
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
// No active ops means INACTIVE should go straight to IDLE.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
// Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
}
@Test
public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NoNetworkConnected() {
setNetworkConnected(false);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
setScreenOn(false);
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
// Active ops means INACTIVE should go to PRE_IDLE to wait.
mDeviceIdleController.setJobsActive(true);
mDeviceIdleController.setAlarmsActive(true);
mDeviceIdleController.setActiveIdleOpsForTest(1);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
// Even with active ops, PRE_IDLE should go to IDLE.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
// Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
}
@Test
public void testExitMaintenanceEarlyIfNeededLocked_deep_noActiveOps() {
mDeviceIdleController.setJobsActive(false);
@@ -903,6 +1123,7 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.becomeActiveLocked("testing", 0);
break;
case STATE_LOCATING:
mInjector.locationManager = mLocationManager;
doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(
anyString());
// Fallthrough to step loop.
@@ -917,7 +1138,6 @@ public class DeviceIdleControllerTest {
setScreenOn(false);
setChargingOn(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
//fail(stateToString(mDeviceIdleController.getState()));
int count = 0;
while (mDeviceIdleController.getState() != state) {
// Stepping through each state ensures that the proper features are turned
@@ -925,7 +1145,8 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.stepIdleStateLocked("testing");
count++;
if (count > 10) {
fail(stateToString(mDeviceIdleController.getState()));
fail("Infinite loop. Check test configuration. Currently at " +
stateToString(mDeviceIdleController.getState()));
}
}
break;
@@ -954,7 +1175,8 @@ public class DeviceIdleControllerTest {
count++;
if (count > 10) {
fail(lightStateToString(mDeviceIdleController.getLightState()));
fail("Infinite loop. Check test configuration. Currently at " +
lightStateToString(mDeviceIdleController.getLightState()));
}
}
break;
@@ -979,6 +1201,14 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.updateInteractivityLocked();
}
private void setNetworkConnected(boolean connected) {
mInjector.connectivityService = mConnectivityService;
final NetworkInfo ani = mock(NetworkInfo.class);
doReturn(connected).when(ani).isConnected();
doReturn(ani).when(mConnectivityService).getActiveNetworkInfo();
mDeviceIdleController.updateConnectivityState(null);
}
private void verifyStateConditions(int expectedState) {
int curState = mDeviceIdleController.getState();
assertEquals(