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

Commit 29c82ab2 authored by jackqdyulei's avatar jackqdyulei
Browse files

Hook up data saver to battery saver.

1. Add globalBatterySaverEnabled in PowerSaveState, which stores
the real battery saver mode, not the one for specific service.
2. Add "mRestrictBackgroundChangedInBsm" and
"mRestrictBackgroundBeforeBsm" to restore the mRestrictBackground
if necessary.
3. If user toggles the data saver when battery saver is on, don't
restore the data saver when battery saver is off.

Bug: 34693888
Test: FrameworksServicesTests
Change-Id: Ic50c1cae3fb110a228e59e5d1fd04c164e4b7274
parent a9795ca6
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -24,7 +24,17 @@ package android.os;
 * @hide
 */
public class PowerSaveState implements Parcelable {
    /**
     * Whether we should enable battery saver for this service.
     *
     * @see com.android.server.power.BatterySaverPolicy.ServiceType
     */
    public final boolean batterySaverEnabled;
    /**
     * Whether the battery saver is enabled globally, which means the data we get from
     * {@link PowerManager#isPowerSaveMode()}
     */
    public final boolean globalBatterySaverEnabled;
    public final int gpsMode;
    public final float brightnessFactor;

@@ -32,10 +42,12 @@ public class PowerSaveState implements Parcelable {
        batterySaverEnabled = builder.mBatterySaverEnabled;
        gpsMode = builder.mGpsMode;
        brightnessFactor = builder.mBrightnessFactor;
        globalBatterySaverEnabled = builder.mGlobalBatterySaverEnabled;
    }

    public PowerSaveState(Parcel in) {
        batterySaverEnabled = in.readByte() != 0;
        globalBatterySaverEnabled = in.readByte() != 0;
        gpsMode = in.readInt();
        brightnessFactor = in.readFloat();
    }
@@ -48,12 +60,14 @@ public class PowerSaveState implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByte((byte) (batterySaverEnabled ? 1 : 0));
        dest.writeByte((byte) (globalBatterySaverEnabled ? 1 : 0));
        dest.writeInt(gpsMode);
        dest.writeFloat(brightnessFactor);
    }

    public static final class Builder {
        private boolean mBatterySaverEnabled = false;
        private boolean mGlobalBatterySaverEnabled = false;
        private int mGpsMode = 0;
        private float mBrightnessFactor = 0.5f;

@@ -64,6 +78,11 @@ public class PowerSaveState implements Parcelable {
            return this;
        }

        public Builder setGlobalBatterySaverEnabled(boolean enabled) {
            mGlobalBatterySaverEnabled = enabled;
            return this;
        }

        public Builder setGpsMode(int mode) {
            mGpsMode = mode;
            return this;
+71 −3
Original line number Diff line number Diff line
@@ -322,6 +322,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    private INotificationManager mNotifManager;
    private PowerManagerInternal mPowerManagerInternal;
    private IDeviceIdleController mDeviceIdleController;
    @GuardedBy("mUidRulesFirstLock")
    private PowerSaveState mRestrictBackgroundPowerState;

    // Store the status of restrict background before turning on battery saver.
    // Used to restore mRestrictBackground when battery saver is turned off.
    private boolean mRestrictBackgroundBeforeBsm;

    // See main javadoc for instructions on how to use these locks.
    final Object mUidRulesFirstLock = new Object();
@@ -332,6 +338,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
    @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
    @GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
    // Store whether user flipped restrict background in battery saver mode
    @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackgroundChangedInBsm;

    private final boolean mSuppressDefaultPolicy;

@@ -617,8 +625,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                                @Override
                                public void onLowPowerModeChanged(PowerSaveState result) {
                                    final boolean enabled = result.batterySaverEnabled;
                                    if (LOGD) Slog.d(TAG,
                                            "onLowPowerModeChanged(" + enabled + ")");
                                    if (LOGD) {
                                        Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
                                    }
                                    synchronized (mUidRulesFirstLock) {
                                        if (mRestrictPower != enabled) {
                                            mRestrictPower = enabled;
@@ -635,6 +644,32 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    // read policy from disk
                    readPolicyAL();

                    // Update the restrictBackground if battery saver is turned on
                    mRestrictBackgroundBeforeBsm = mRestrictBackground;
                    mRestrictBackgroundPowerState = mPowerManagerInternal
                            .getLowPowerState(ServiceType.DATA_SAVER);
                    final boolean localRestrictBackground =
                            mRestrictBackgroundPowerState.batterySaverEnabled;
                    if (localRestrictBackground && localRestrictBackground != mRestrictBackground) {
                        mRestrictBackground = localRestrictBackground;
                        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED,
                                mRestrictBackground ? 1 : 0, 0).sendToTarget();
                    }
                    mPowerManagerInternal.registerLowPowerModeObserver(
                            new PowerManagerInternal.LowPowerModeListener() {
                                @Override
                                public int getServiceType() {
                                    return ServiceType.DATA_SAVER;
                                }

                                @Override
                                public void onLowPowerModeChanged(PowerSaveState result) {
                                    synchronized (mUidRulesFirstLock) {
                                        updateRestrictBackgroundByLowPowerModeUL(result);
                                    }
                                }
                            });

                    if (addDefaultRestrictBackgroundWhitelistUidsUL()) {
                        writePolicyAL();
                    }
@@ -2159,6 +2194,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        } catch (RemoteException e) {
            // ignored; service lives in system_server
        }

        if (mRestrictBackgroundPowerState.globalBatterySaverEnabled) {
            mRestrictBackgroundChangedInBsm = true;
        }
        synchronized (mNetworkPoliciesSecondLock) {
            updateNotificationsNL();
            writePolicyAL();
@@ -3645,6 +3684,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        mHandler.getLooper().getQueue().addIdleHandler(handler);
    }

    @VisibleForTesting
    public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
        mRestrictBackgroundPowerState = result;

        boolean restrictBackground = result.batterySaverEnabled;
        boolean shouldInvokeRestrictBackground;
        // store the temporary mRestrictBackgroundChangedInBsm and update it at last
        boolean localRestrictBgChangedInBsm = mRestrictBackgroundChangedInBsm;

        if (result.globalBatterySaverEnabled) {
            // Try to turn on restrictBackground if (1) it is off and (2) batter saver need to
            // turn it on.
            shouldInvokeRestrictBackground = !mRestrictBackground && result.batterySaverEnabled;
            mRestrictBackgroundBeforeBsm = mRestrictBackground;
            localRestrictBgChangedInBsm = false;
        } else {
            // Try to restore the restrictBackground if it doesn't change in bsm
            shouldInvokeRestrictBackground = !mRestrictBackgroundChangedInBsm;
            restrictBackground = mRestrictBackgroundBeforeBsm;
        }

        if (shouldInvokeRestrictBackground) {
            setRestrictBackground(restrictBackground);
        }

        // Change it at last so setRestrictBackground() won't affect this variable
        mRestrictBackgroundChangedInBsm = localRestrictBgChangedInBsm;
    }

    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
        final int size = source.size();
        for (int i = 0; i < size; i++) {
+19 −2
Original line number Diff line number Diff line
@@ -43,7 +43,8 @@ public class BatterySaverPolicy extends ContentObserver {
            ServiceType.NETWORK_FIREWALL,
            ServiceType.SCREEN_BRIGHTNESS,
            ServiceType.SOUND,
            ServiceType.BATTERY_STATS})
            ServiceType.BATTERY_STATS,
            ServiceType.DATA_SAVER})
    public @interface ServiceType {
        int NULL = 0;
        int GPS = 1;
@@ -55,6 +56,7 @@ public class BatterySaverPolicy extends ContentObserver {
        int SCREEN_BRIGHTNESS = 7;
        int SOUND = 8;
        int BATTERY_STATS = 9;
        int DATA_SAVER = 10;
    }

    private static final String TAG = "BatterySaverPolicy";
@@ -73,6 +75,7 @@ public class BatterySaverPolicy extends ContentObserver {
    private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
    private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
    private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
    private static final String KEY_DATASAVER_DISABLED = "datasaver_disabled";
    private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
    private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
    private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
@@ -136,6 +139,14 @@ public class BatterySaverPolicy extends ContentObserver {
     */
    private boolean mAdjustBrightnessDisabled;

    /**
     * {@code true} if data saver is disabled in battery saver mode.
     *
     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
     * @see #KEY_DATASAVER_DISABLED
     */
    private boolean mDataSaverDisabled;

    /**
     * This is the flag to decide the gps mode in battery saver mode.
     *
@@ -191,6 +202,7 @@ public class BatterySaverPolicy extends ContentObserver {
            mFireWallDisabled = mParser.getBoolean(KEY_FIREWALL_DISABLED, false);
            mAdjustBrightnessDisabled = mParser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
            mAdjustBrightnessFactor = mParser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
            mDataSaverDisabled = mParser.getBoolean(KEY_DATASAVER_DISABLED, true);

            // Get default value from Settings.Secure
            final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
@@ -210,7 +222,8 @@ public class BatterySaverPolicy extends ContentObserver {
     */
    public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
        synchronized (BatterySaverPolicy.this) {
            final PowerSaveState.Builder builder = new PowerSaveState.Builder();
            final PowerSaveState.Builder builder = new PowerSaveState.Builder()
                    .setGlobalBatterySaverEnabled(realMode);
            if (!realMode) {
                return builder.setBatterySaverEnabled(realMode)
                        .build();
@@ -236,6 +249,9 @@ public class BatterySaverPolicy extends ContentObserver {
                    return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
                            .setBrightnessFactor(mAdjustBrightnessFactor)
                            .build();
                case ServiceType.DATA_SAVER:
                    return builder.setBatterySaverEnabled(!mDataSaverDisabled)
                            .build();
                case ServiceType.SOUND:
                    return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
                            .build();
@@ -262,6 +278,7 @@ public class BatterySaverPolicy extends ContentObserver {
        pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
        pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
        pw.println("  " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
        pw.println("  " + KEY_DATASAVER_DISABLED + "=" + mDataSaverDisabled);
        pw.println("  " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
        pw.println("  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
        pw.println("  " + KEY_GPS_MODE + "=" + mGpsMode);
+93 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static com.android.server.net.NetworkPolicyManagerService.ProcStateSeqHis
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -51,10 +52,15 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -89,6 +95,7 @@ import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.UserHandle;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
@@ -198,6 +205,7 @@ public class NetworkPolicyManagerServiceTest {

    private IUidObserver mUidObserver;
    private INetworkManagementEventObserver mNetworkObserver;
    private PowerManagerInternal mPowerManagerInternal;

    private NetworkPolicyListenerAnswer mPolicyListener;
    private NetworkPolicyManagerService mService;
@@ -227,12 +235,16 @@ public class NetworkPolicyManagerServiceTest {

    @BeforeClass
    public static void registerLocalServices() {
        addLocalServiceMock(PowerManagerInternal.class);
        addLocalServiceMock(DeviceIdleController.LocalService.class);
        final UsageStatsManagerInternal usageStats =
                addLocalServiceMock(UsageStatsManagerInternal.class);
        when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
        mActivityManagerInternal = addLocalServiceMock(ActivityManagerInternal.class);

        final PowerSaveState state = new PowerSaveState.Builder()
                .setBatterySaverEnabled(false).build();
        final PowerManagerInternal pmInternal = addLocalServiceMock(PowerManagerInternal.class);
        when(pmInternal.getLowPowerState(anyInt())).thenReturn(state);
    }

    @Before
@@ -401,6 +413,85 @@ public class NetworkPolicyManagerServiceTest {
        removeRestrictBackgroundWhitelist(false);
    }

    @Test
    public void testLowPowerModeObserver_ListenersRegistered()
            throws Exception {
        PowerManagerInternal pmInternal = LocalServices.getService(PowerManagerInternal.class);

        verify(pmInternal, atLeast(2)).registerLowPowerModeObserver(any());
    }

    @Test
    public void updateRestrictBackgroundByLowPowerMode_RestrictOnBeforeBsm_RestrictOnAfterBsm()
            throws Exception {
        setRestrictBackground(true);
        PowerSaveState stateOn = new PowerSaveState.Builder()
                .setGlobalBatterySaverEnabled(true)
                .setBatterySaverEnabled(false)
                .build();
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOn);

        // RestrictBackground should be on even though battery saver want to turn it off
        assertThat(mService.getRestrictBackground()).isTrue();

        PowerSaveState stateOff = new PowerSaveState.Builder()
                .setGlobalBatterySaverEnabled(false)
                .setBatterySaverEnabled(false)
                .build();
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);

        // RestrictBackground should be on, following its previous state
        assertThat(mService.getRestrictBackground()).isTrue();
    }

    @Test
    public void updateRestrictBackgroundByLowPowerMode_RestrictOffBeforeBsm_RestrictOffAfterBsm()
            throws Exception {
        setRestrictBackground(false);
        PowerSaveState stateOn = new PowerSaveState.Builder()
                .setGlobalBatterySaverEnabled(true)
                .setBatterySaverEnabled(true)
                .build();

        doReturn(true).when(mNetworkManager).setDataSaverModeEnabled(true);
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOn);

        // RestrictBackground should be turned on because of battery saver
        assertThat(mService.getRestrictBackground()).isTrue();

        PowerSaveState stateOff = new PowerSaveState.Builder()
                .setGlobalBatterySaverEnabled(false)
                .setBatterySaverEnabled(false)
                .build();
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);

        // RestrictBackground should be off, following its previous state
        assertThat(mService.getRestrictBackground()).isFalse();
    }

    @Test
    public void updateRestrictBackgroundByLowPowerMode_StatusChangedInBsm_DoNotRestore()
            throws Exception {
        setRestrictBackground(true);
        PowerSaveState stateOn = new PowerSaveState.Builder()
                .setGlobalBatterySaverEnabled(true)
                .setBatterySaverEnabled(true)
                .build();
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOn);

        // RestrictBackground should still be on
        assertThat(mService.getRestrictBackground()).isTrue();

        // User turns off RestrictBackground manually
        setRestrictBackground(false);
        PowerSaveState stateOff = new PowerSaveState.Builder().setBatterySaverEnabled(
                false).build();
        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);

        // RestrictBackground should be off because user changes it manually
        assertThat(mService.getRestrictBackground()).isFalse();
    }

    private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
        // Sanity checks.
        assertWhitelistUids(UID_A);
@@ -1231,7 +1322,7 @@ public class NetworkPolicyManagerServiceTest {

    private void setRestrictBackground(boolean flag) throws Exception {
        // Must set expectation, otherwise NMPS will reset value to previous one.
        when(mNetworkManager.setDataSaverModeEnabled(flag)).thenReturn(true);
        doReturn(true).when(mNetworkManager).setDataSaverModeEnabled(flag);
        mService.setRestrictBackground(flag);
        // Sanity check.
        assertEquals("restrictBackground not set", flag, mService.getRestrictBackground());
+21 −1
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ import android.os.PowerSaveState;
import android.os.Handler;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.server.power.BatterySaverPolicy.ServiceType;

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -40,6 +42,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
            + "animation_disabled=false,"
            + "soundtrigger_disabled=true,"
            + "firewall_disabled=false,"
            + "datasaver_disabled=false,"
            + "adjust_brightness_disabled=true,"
            + "adjust_brightness_factor=0.7,"
            + "fullbackup_deferred=true,"
@@ -98,6 +101,18 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
        testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
    }

    @SmallTest
    public void testGetBatterySaverPolicy_PolicyDataSaver_DefaultValueCorrect() {
        mBatterySaverPolicy.updateConstants("");
        final PowerSaveState batterySaverStateOn =
                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.DATA_SAVER, BATTERY_SAVER_ON);
        assertThat(batterySaverStateOn.batterySaverEnabled).isFalse();

        final PowerSaveState batterySaverStateOff = mBatterySaverPolicy.getBatterySaverPolicy(
                ServiceType.DATA_SAVER, BATTERY_SAVER_OFF);
        assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
    }

    @SmallTest
    public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
        testServiceDefaultValue(ServiceType.SCREEN_BRIGHTNESS);
@@ -137,7 +152,8 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
        assertThat(networkState.batterySaverEnabled).isTrue();

        final PowerSaveState screenState =
                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, BATTERY_SAVER_ON);
                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS,
                        BATTERY_SAVER_ON);
        assertThat(screenState.batterySaverEnabled).isFalse();
        assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);

@@ -149,6 +165,10 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
                ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
        assertThat(keyValueBackupState.batterySaverEnabled).isFalse();

        final PowerSaveState dataSaverState = mBatterySaverPolicy.getBatterySaverPolicy(
                ServiceType.DATA_SAVER, BATTERY_SAVER_ON);
        assertThat(dataSaverState.batterySaverEnabled).isTrue();

        final PowerSaveState gpsState =
                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
        assertThat(gpsState.batterySaverEnabled).isTrue();