OSDN Git Service

Making "Battery Saver" use MasterSwitchPreference.
authorjackqdyulei <jackqdyulei@google.com>
Tue, 24 Jan 2017 01:12:03 +0000 (17:12 -0800)
committerjackqdyulei <jackqdyulei@google.com>
Wed, 25 Jan 2017 01:34:14 +0000 (17:34 -0800)
By using MasterSwitchPreference, we make "battery saver" to have
two parts: left part is the clickable summary jumping to other
fragment while right part is a switch toggle.

Also remove the previous battery saver preference.

Bug: 34279051
Test: RunSettingsRoboTests

Change-Id: If36fa9741e413a9bbdd57fa67a2c15b6e457afd7

res/xml/power_usage_summary.xml
src/com/android/settings/fuelgauge/BatterySaverController.java [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatterySaverPreference.java [deleted file]
src/com/android/settings/fuelgauge/PowerUsageSummary.java
tests/robotests/src/com/android/settings/fuelgauge/BatterySaverControllerTest.java [new file with mode: 0644]

index 4607c48..b4ac7e2 100644 (file)
@@ -27,7 +27,8 @@
         android:key="power_management"
         android:title="@string/battery_power_management">
 
-        <com.android.settings.fuelgauge.BatterySaverPreference
+        <com.android.settings.widget.MasterSwitchPreference
+            android:key="battery_saver"
             android:title="@string/battery_saver"
             android:fragment="com.android.settings.fuelgauge.BatterySaverSettings"/>
 
diff --git a/src/com/android/settings/fuelgauge/BatterySaverController.java b/src/com/android/settings/fuelgauge/BatterySaverController.java
new file mode 100644 (file)
index 0000000..08d570a
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.Log;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnStart;
+import com.android.settings.core.lifecycle.events.OnStop;
+import com.android.settings.dashboard.conditional.BatterySaverCondition;
+import com.android.settings.dashboard.conditional.ConditionManager;
+import com.android.settings.widget.MasterSwitchPreference;
+
+import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGING;
+
+public class BatterySaverController extends PreferenceController implements
+        Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop {
+    private static final String KEY_BATTERY_SAVER = "battery_saver";
+    private static final String TAG = "BatterySaverController";
+    private static final boolean DEBUG = false;
+
+    private final BatteryStateChangeReceiver mBatteryStateChangeReceiver;
+    private final PowerManager mPowerManager;
+    private MasterSwitchPreference mBatterySaverPref;
+
+    public BatterySaverController(Context context, Lifecycle lifecycle) {
+        super(context);
+
+        lifecycle.addObserver(this);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mBatteryStateChangeReceiver = new BatteryStateChangeReceiver();
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BATTERY_SAVER;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mBatterySaverPref = (MasterSwitchPreference) screen.findPreference(KEY_BATTERY_SAVER);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        mBatterySaverPref.setChecked(mPowerManager.isPowerSaveMode());
+        updateSummary();
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean saverOn = (Boolean) newValue;
+        if (saverOn != mPowerManager.isPowerSaveMode()
+                && !mPowerManager.setPowerSaveMode(saverOn)) {
+            // Do nothing if power save mode doesn't set correctly
+            return false;
+        }
+
+        refreshConditionManager();
+        updateSummary();
+        return true;
+    }
+
+    @Override
+    public void onStart() {
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL)
+                , true, mObserver);
+
+        mBatteryStateChangeReceiver.setListening(true);
+    }
+
+    @Override
+    public void onStop() {
+        mContext.getContentResolver().unregisterContentObserver(mObserver);
+        mBatteryStateChangeReceiver.setListening(false);
+    }
+
+    @VisibleForTesting
+    void refreshConditionManager() {
+        ConditionManager.get(mContext).getCondition(BatterySaverCondition.class).refreshState();
+    }
+
+    private void updateSummary() {
+        final boolean mode = mPowerManager.isPowerSaveMode();
+        final int format = mode ? R.string.battery_saver_on_summary
+                : R.string.battery_saver_off_summary;
+        final int percent = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        final int percentFormat = percent > 0 ? R.string.battery_saver_desc_turn_on_auto_pct
+                : R.string.battery_saver_desc_turn_on_auto_never;
+
+        final String summary = mContext.getString(format, mContext.getString(percentFormat,
+                Utils.formatPercentage(percent)));
+
+        mBatterySaverPref.setSummary(summary);
+    }
+
+    private final ContentObserver mObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateSummary();
+        }
+    };
+
+    private final class BatteryStateChangeReceiver extends BroadcastReceiver {
+        private boolean mRegistered;
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) {
+                Log.d(TAG, "Received " + intent.getAction());
+            }
+            final String action = intent.getAction();
+            if (action.equals(ACTION_POWER_SAVE_MODE_CHANGING)) {
+                mBatterySaverPref.setChecked(mPowerManager.isPowerSaveMode());
+                updateSummary();
+            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+                final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+                // disable BSM switch if phone is plugged in or at 100% while plugged in
+                final boolean enabled = !(status == BatteryManager.BATTERY_STATUS_CHARGING
+                        || status == BatteryManager.BATTERY_STATUS_FULL);
+
+                mBatterySaverPref.setSwitchEnabled(enabled);
+            }
+        }
+
+        public void setListening(boolean listening) {
+            if (listening && !mRegistered) {
+                final IntentFilter ifilter = new IntentFilter();
+                ifilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+                ifilter.addAction(ACTION_POWER_SAVE_MODE_CHANGING);
+                mContext.registerReceiver(this, ifilter);
+                mRegistered = true;
+            } else if (!listening && mRegistered) {
+                mContext.unregisterReceiver(this);
+                mRegistered = false;
+            }
+        }
+
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatterySaverPreference.java b/src/com/android/settings/fuelgauge/BatterySaverPreference.java
deleted file mode 100644 (file)
index 9e0f39b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.fuelgauge;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.provider.Settings;
-import android.provider.Settings.Global;
-import android.support.v7.preference.Preference;
-import android.util.AttributeSet;
-import android.view.View;
-import com.android.settings.R;
-import com.android.settings.Utils;
-
-public class BatterySaverPreference extends Preference {
-
-    private PowerManager mPowerManager;
-
-    public BatterySaverPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void performClick(View view) {
-        Utils.startWithFragment(getContext(), getFragment(), null, null, 0, 0, getTitle());
-    }
-
-    @Override
-    public void onAttached() {
-        super.onAttached();
-        mPowerManager = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
-        mObserver.onChange(true);
-        getContext().getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Global.LOW_POWER_MODE_TRIGGER_LEVEL), true, mObserver);
-        getContext().getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Global.LOW_POWER_MODE), true, mObserver);
-    }
-
-    @Override
-    public void onDetached() {
-        super.onDetached();
-        getContext().getContentResolver().unregisterContentObserver(mObserver);
-    }
-
-    private void updateSwitch() {
-        final Context context = getContext();
-        final boolean mode = mPowerManager.isPowerSaveMode();
-        int format = mode ? R.string.battery_saver_on_summary
-                : R.string.battery_saver_off_summary;
-        int percent = Settings.Global.getInt(context.getContentResolver(),
-                Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
-        int percentFormat = percent > 0 ? R.string.battery_saver_desc_turn_on_auto_pct
-                : R.string.battery_saver_desc_turn_on_auto_never;
-        setSummary(context.getString(format, context.getString(percentFormat,
-                Utils.formatPercentage(percent))));
-    }
-
-    private final ContentObserver mObserver = new ContentObserver(new Handler()) {
-        @Override
-        public void onChange(boolean selfChange) {
-            updateSwitch();
-        }
-    };
-
-}
index 4a25e3e..24218b0 100644 (file)
@@ -158,6 +158,7 @@ public class PowerUsageSummary extends PowerUsageBase {
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new AutoBrightnessPreferenceController(context));
         controllers.add(new TimeoutPreferenceController(context));
+        controllers.add(new BatterySaverController(context, getLifecycle()));
         return controllers;
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatterySaverControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatterySaverControllerTest.java
new file mode 100644 (file)
index 0000000..9656381
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.os.PowerManager;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.widget.MasterSwitchPreference;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatterySaverControllerTest {
+    @Mock
+    private MasterSwitchPreference mBatterySaverPref;
+    @Mock
+    private PowerManager mPowerManager;
+    @Mock
+    private Context mContext;
+    @Mock
+    private Lifecycle mLifecycle;
+    private BatterySaverController mBatterySaverController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mBatterySaverController = spy(new BatterySaverController(mContext, mLifecycle));
+        ReflectionHelpers.setField(mBatterySaverController, "mPowerManager", mPowerManager);
+        ReflectionHelpers.setField(mBatterySaverController, "mBatterySaverPref", mBatterySaverPref);
+        doNothing().when(mBatterySaverController).refreshConditionManager();
+    }
+
+    @Test
+    public void testOnPreferenceChange_TurnOnBatterySaver_BatterySaverOn() {
+        testOnPreferenceChangeInner(true);
+    }
+
+    @Test
+    public void testOnPreferenceChange_TurnOffBatterySaver_BatterySaverOff() {
+        testOnPreferenceChangeInner(false);
+    }
+
+    @Test
+    public void testUpdateState_SaverModeOn_PreferenceChecked() {
+        testUpdateStateInner(true);
+    }
+
+    @Test
+    public void testUpdateState_SaverModeOff_PreferenceUnChecked() {
+        testUpdateStateInner(false);
+    }
+
+    private void testOnPreferenceChangeInner(final boolean saverOn) {
+        when(mPowerManager.setPowerSaveMode(saverOn)).thenReturn(true);
+        when(mPowerManager.isPowerSaveMode()).thenReturn(!saverOn);
+
+        mBatterySaverController.onPreferenceChange(mBatterySaverPref, saverOn);
+        verify(mPowerManager).setPowerSaveMode(saverOn);
+    }
+
+    private void testUpdateStateInner(final boolean saverOn) {
+        when(mPowerManager.isPowerSaveMode()).thenReturn(saverOn);
+
+        mBatterySaverController.updateState(mBatterySaverPref);
+        verify(mBatterySaverPref).setChecked(saverOn);
+    }
+}