Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 799858bc authored by Kweku Adams's avatar Kweku Adams
Browse files

DeviceIdleController light state transition tests.

This adds tests for normal transitions for light idling.

Bug: 116512267
Test: atest com.android.server.DeviceIdleControllerTest
Change-Id: I916fee8e07f23f07e86d4360a64feb245a797bdb
parent fa66c22c
Loading
Loading
Loading
Loading
+41 −25
Original line number Diff line number Diff line
@@ -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,14 +2288,18 @@ public class DeviceIdleController extends SystemService
    /** Must only be used in tests. */
    @VisibleForTesting
    void setDeepEnabledForTest(boolean enabled) {
        synchronized (this) {
            mDeepEnabled = enabled;
        }
    }

    /** Must only be used in tests. */
    @VisibleForTesting
    void setLightEnabledForTest(boolean enabled) {
        synchronized (this) {
            mLightEnabled = enabled;
        }
    }

    void becomeInactiveIfAppropriateLocked() {
        if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
@@ -2338,8 +2354,10 @@ public class DeviceIdleController extends SystemService
     */
    @VisibleForTesting
    void setLightStateForTest(int lightState) {
        synchronized (this) {
            mLightState = lightState;
        }
    }

    @VisibleForTesting
    int getLightState() {
@@ -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,8 +2588,10 @@ public class DeviceIdleController extends SystemService
    /** Must only be used in tests. */
    @VisibleForTesting
    void setActiveIdleOpsForTest(int count) {
        synchronized (this) {
            mActiveIdleOpCount = count;
        }
    }

    void setJobsActive(boolean active) {
        synchronized (this) {
@@ -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;
        }
    }
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+239 −9
Original line number Diff line number Diff line
@@ -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(