OSDN Git Service

Hook up data saver to battery saver.
authorjackqdyulei <jackqdyulei@google.com>
Fri, 10 Mar 2017 22:09:16 +0000 (14:09 -0800)
committerjackqdyulei <jackqdyulei@google.com>
Wed, 22 Mar 2017 22:55:21 +0000 (15:55 -0700)
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

core/java/android/os/PowerSaveState.java
services/core/java/com/android/server/net/NetworkPolicyManagerService.java
services/core/java/com/android/server/power/BatterySaverPolicy.java
services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java

index 9269e76..7058a1d 100644 (file)
@@ -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;
index 8a4f3f7..fc45344 100644 (file)
@@ -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;
@@ -626,7 +635,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                                         }
                                     }
                                 }
-                    });
+                            });
                     mRestrictPower = mPowerManagerInternal.getLowPowerState(
                             ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
 
@@ -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++) {
index 8d20531..1781d8c 100644 (file)
@@ -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";
@@ -137,6 +140,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.
      *
      * @see Settings.Global#BATTERY_SAVER_CONSTANTS
@@ -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);
index f8d105e..29c6f89 100644 (file)
@@ -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());
index 7282b3e..69589e7 100644 (file)
@@ -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,"
@@ -99,6 +102,18 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
     }
 
     @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();