From 131d3b3c2f3c1bb7348564bbd311a66f38d7283c Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 5 Jan 2018 14:33:38 -0800 Subject: [PATCH] Add smart battery page for battery settings This page contains prefs for smart battery and app restriction. Bug: 71502850 Test: RunSettingsRoboTests Change-Id: I194af30cbc7b2496b10098fcb67f1116e0722310 --- res/layout/smart_battery_header.xml | 30 +++++++ res/values/strings.xml | 13 +++ res/xml/power_usage_summary.xml | 5 ++ res/xml/smart_battery_detail.xml | 38 +++++++++ .../fuelgauge/RestrictAppPreferenceController.java | 63 ++++++++++++++ .../SmartBatteryPreferenceController.java | 54 ++++++++++++ .../settings/fuelgauge/SmartBatterySettings.java | 98 ++++++++++++++++++++++ .../settings/search/SearchIndexableResources.java | 2 + .../RestrictAppPreferenceControllerTest.java | 88 +++++++++++++++++++ 9 files changed, 391 insertions(+) create mode 100644 res/layout/smart_battery_header.xml create mode 100644 res/xml/smart_battery_detail.xml create mode 100644 src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java create mode 100644 src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java create mode 100644 src/com/android/settings/fuelgauge/SmartBatterySettings.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java diff --git a/res/layout/smart_battery_header.xml b/res/layout/smart_battery_header.xml new file mode 100644 index 0000000000..960f04ad38 --- /dev/null +++ b/res/layout/smart_battery_header.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 74737ad05c..79faf9b013 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4773,6 +4773,19 @@ Low battery capacity Battery can\'t provide good battery life + + Smart battery manager + + Auto-manage battery + + Automatically adjust power usage by apps based on usage + + Restricted apps + + + %1$d app + %1$d apps + Stop app? diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index 5d6c9e966c..d7c3c3916d 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -38,6 +38,11 @@ android:key="battery_saver_summary" android:title="@string/battery_saver"/> + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java new file mode 100644 index 0000000000..7df0fb1b79 --- /dev/null +++ b/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 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.app.AppOpsManager; +import android.content.Context; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.applications.LayoutPreference; +import com.android.settings.core.BasePreferenceController; + +import java.util.List; + +/** + * Controller to change and update the smart battery toggle + */ +public class RestrictAppPreferenceController extends BasePreferenceController { + @VisibleForTesting + static final String KEY_RESTRICT_APP = "restricted_app"; + + private AppOpsManager mAppOpsManager; + private List mPackageOps; + + public RestrictAppPreferenceController(Context context) { + super(context, KEY_RESTRICT_APP); + mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + mPackageOps = mAppOpsManager.getPackagesForOps( + new int[]{AppOpsManager.OP_RUN_ANY_IN_BACKGROUND}); + final int num = mPackageOps != null ? mPackageOps.size() : 0; + + preference.setSummary( + mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num, + num)); + } + +} diff --git a/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java new file mode 100644 index 0000000000..0002dac9db --- /dev/null +++ b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 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.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.applications.LayoutPreference; +import com.android.settings.core.BasePreferenceController; + +/** + * Controller to change and update the smart battery toggle + */ +public class SmartBatteryPreferenceController extends BasePreferenceController implements + Preference.OnPreferenceChangeListener { + private static final String KEY_SMART_BATTERY = "smart_battery"; + + public SmartBatteryPreferenceController(Context context) { + super(context, KEY_SMART_BATTERY); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean smartBatteryOn = (Boolean) newValue; + //TODO(b/71502850): use smart battery API here to update the state + return true; + } +} diff --git a/src/com/android/settings/fuelgauge/SmartBatterySettings.java b/src/com/android/settings/fuelgauge/SmartBatterySettings.java new file mode 100644 index 0000000000..5faaef41f6 --- /dev/null +++ b/src/com/android/settings/fuelgauge/SmartBatterySettings.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2018 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.Bundle; +import android.provider.SearchIndexableResource; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.widget.FooterPreferenceMixin; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Fragment to show smart battery and restricted app controls + */ +public class SmartBatterySettings extends DashboardFragment { + public static final String TAG = "SmartBatterySettings"; + + private final FooterPreferenceMixin mFooterPreferenceMixin = + new FooterPreferenceMixin(this, getLifecycle()); + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mFooterPreferenceMixin.createFooterPreference().setTitle(R.string.battery_footer_summary); + } + + @Override + public int getMetricsCategory() { + return MetricsProto.MetricsEvent.FUELGAUGE_SMART_BATTERY; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.smart_battery_detail; + } + + @Override + protected List getPreferenceControllers(Context context) { + return buildPreferenceControllers(context); + } + + private static List buildPreferenceControllers( + Context context) { + final List controllers = new ArrayList<>(); + controllers.add(new SmartBatteryPreferenceController(context)); + controllers.add(new RestrictAppPreferenceController(context)); + return controllers; + } + + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.smart_battery_detail; + return Arrays.asList(sir); + } + + @Override + public List getNonIndexableKeys(Context context) { + return super.getNonIndexableKeys(context); + } + + @Override + public List getPreferenceControllers( + Context context) { + return buildPreferenceControllers(context); + } + }; +} diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 0207c94ad9..80ff032e1c 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -50,6 +50,7 @@ import com.android.settings.enterprise.EnterprisePrivacySettings; import com.android.settings.fuelgauge.BatterySaverSettings; import com.android.settings.fuelgauge.PowerUsageAdvanced; import com.android.settings.fuelgauge.PowerUsageSummary; +import com.android.settings.fuelgauge.SmartBatterySettings; import com.android.settings.gestures.AssistGestureSettings; import com.android.settings.gestures.DoubleTapPowerSettings; import com.android.settings.gestures.DoubleTapScreenSettings; @@ -174,6 +175,7 @@ public final class SearchIndexableResources { addIndex(ZenModeBehaviorSettings.class); addIndex(ZenModeAutomationSettings.class); addIndex(NightDisplaySettings.class); + addIndex(SmartBatterySettings.class); } private SearchIndexableResources() { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java new file mode 100644 index 0000000000..c9441487b3 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.app.AppOpsManager; +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class RestrictAppPreferenceControllerTest { + + @Mock + private AppOpsManager mAppOpsManager; + @Mock + private AppOpsManager.PackageOps mPackageOps; + private List mPackageOpsList; + private RestrictAppPreferenceController mRestrictAppPreferenceController; + private Preference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE); + mRestrictAppPreferenceController = new RestrictAppPreferenceController(mContext); + mPackageOpsList = new ArrayList<>(); + mPreference = new Preference(mContext); + } + + @Test + public void testUpdateState_oneApp_showCorrectSummary() { + mPackageOpsList.add(mPackageOps); + doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any()); + + mRestrictAppPreferenceController.updateState(mPreference); + + assertThat(mPreference.getSummary()).isEqualTo("1 app"); + } + + @Test + public void testUpdateState_twoApps_showCorrectSummary() { + mPackageOpsList.add(mPackageOps); + mPackageOpsList.add(mPackageOps); + doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any()); + + mRestrictAppPreferenceController.updateState(mPreference); + + assertThat(mPreference.getSummary()).isEqualTo("2 apps"); + } + +} -- 2.11.0