diff --git a/AndroidManifest.xml b/AndroidManifest.xml index bf241d35db4..8c1ab5648b0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -90,6 +90,7 @@ + + + + + \ No newline at end of file diff --git a/res/layout/smart_battery_header.xml b/res/layout/smart_battery_header.xml new file mode 100644 index 00000000000..960f04ad380 --- /dev/null +++ b/res/layout/smart_battery_header.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/res/layout/two_action_buttons.xml b/res/layout/two_action_buttons.xml index 41bcfc36efd..23bb886c901 100644 --- a/res/layout/two_action_buttons.xml +++ b/res/layout/two_action_buttons.xml @@ -20,9 +20,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" - android:paddingTop="8dp" + android:paddingTop="24dp" android:paddingStart="68dp" - android:paddingEnd="8dp" + android:paddingEnd="24dp" android:orientation="horizontal"> + + + + + + + + + zen_mode_from_none + + Use network preference + Treat as metered + Treat as unmetered + + + + 0 + 1 + 2 + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 74737ad05c7..52bcdbfbee7 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? @@ -6811,10 +6824,10 @@ Add - TURN ON NOW + Turn on now - TURN OFF NOW + Turn off now Do Not Disturb is on until %s diff --git a/res/xml/data_usage_wifi.xml b/res/xml/data_usage_wifi.xml index 607cee1851b..905b15a04f4 100644 --- a/res/xml/data_usage_wifi.xml +++ b/res/xml/data_usage_wifi.xml @@ -27,11 +27,6 @@ android:key="wifi_data_usage" android:title="@string/wifi_data_usage" /> - - diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index 5d6c9e966ce..d7c3c3916da 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/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml index 8203bece42a..5e2745a6e51 100644 --- a/res/xml/wifi_network_details_fragment.xml +++ b/res/xml/wifi_network_details_fragment.xml @@ -49,6 +49,13 @@ android:icon="@drawable/ic_security_lock_24dp" android:title="@string/wifi_security" android:selectable="false"/> + + diff --git a/src/com/android/settings/datausage/DataUsageMeteredSettings.java b/src/com/android/settings/datausage/DataUsageMeteredSettings.java deleted file mode 100644 index 8bc7e04c3db..00000000000 --- a/src/com/android/settings/datausage/DataUsageMeteredSettings.java +++ /dev/null @@ -1,150 +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.datausage; - -import android.app.backup.BackupManager; -import android.content.Context; -import android.net.NetworkPolicyManager; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.provider.SearchIndexableResource; -import android.support.v7.preference.DropDownPreference; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceCategory; -import android.text.TextUtils; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.Indexable; -import com.android.settingslib.NetworkPolicyEditor; - -import java.util.Arrays; -import java.util.List; - -/** - * Panel to configure {@link WifiConfiguration#meteredOverride}. - */ -public class DataUsageMeteredSettings extends SettingsPreferenceFragment implements Indexable { - - private NetworkPolicyManager mPolicyManager; - private WifiManager mWifiManager; - - private NetworkPolicyEditor mPolicyEditor; - - private PreferenceCategory mMobileCategory; - private PreferenceCategory mWifiCategory; - private Preference mWifiDisabled; - - @Override - public int getMetricsCategory() { - return MetricsEvent.NET_DATA_USAGE_METERED; - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - final Context context = getActivity(); - - mPolicyManager = NetworkPolicyManager.from(context); - mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - - mPolicyEditor = new NetworkPolicyEditor(mPolicyManager); - mPolicyEditor.read(); - - addPreferencesFromResource(R.xml.data_usage_metered_prefs); - mMobileCategory = (PreferenceCategory) findPreference("mobile"); - mWifiCategory = (PreferenceCategory) findPreference("wifi"); - mWifiDisabled = findPreference("wifi_disabled"); - - updateNetworks(context); - } - - private void updateNetworks(Context context) { - getPreferenceScreen().removePreference(mMobileCategory); - - mWifiCategory.removeAll(); - if (DataUsageUtils.hasWifiRadio(context) && mWifiManager.isWifiEnabled()) { - for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { - final Preference pref = new MeteredPreference(getPrefContext(), config); - if (!TextUtils.isEmpty(pref.getTitle())) { - mWifiCategory.addPreference(pref); - } - } - } else { - mWifiCategory.addPreference(mWifiDisabled); - } - } - - private class MeteredPreference extends DropDownPreference { - private final WifiConfiguration mConfig; - - public MeteredPreference(Context context, WifiConfiguration config) { - super(context); - mConfig = config; - - setPersistent(false); - setEntries(new CharSequence[] { - getString(R.string.data_usage_metered_auto), - getString(R.string.data_usage_metered_yes), - getString(R.string.data_usage_metered_no), - }); - setEntryValues(new CharSequence[] { - Integer.toString(WifiConfiguration.METERED_OVERRIDE_NONE), - Integer.toString(WifiConfiguration.METERED_OVERRIDE_METERED), - Integer.toString(WifiConfiguration.METERED_OVERRIDE_NOT_METERED), - }); - setValue(Integer.toString(mConfig.meteredOverride)); - setTitle(NetworkPolicyManager.resolveNetworkId(mConfig)); - setSummary(getEntries()[mConfig.meteredOverride]); - - setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - mConfig.meteredOverride = Integer.parseInt((String) newValue); - setSummary(getEntries()[mConfig.meteredOverride]); - - mWifiManager.updateNetwork(mConfig); - // Stage the backup of the SettingsProvider package which backs this up - BackupManager.dataChanged("com.android.providers.settings"); - return true; - } - }); - } - } - - /** - * For search - */ - public static final Indexable.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.data_usage_metered_prefs; - return Arrays.asList(sir); - } - - @Override - public List getNonIndexableKeys(Context context) { - final List result = super.getNonIndexableKeys(context); - result.add("mobile"); - return result; - } - }; -} diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java index fe220221db5..b4d5f50ee04 100644 --- a/src/com/android/settings/datausage/DataUsageSummary.java +++ b/src/com/android/settings/datausage/DataUsageSummary.java @@ -77,8 +77,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs // Wifi keys public static final String KEY_WIFI_USAGE_TITLE = "wifi_category"; public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage"; - public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions"; - private DataUsageController mDataUsageController; private DataUsageInfoController mDataInfoController; @@ -86,8 +84,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs private Preference mLimitPreference; private NetworkTemplate mDefaultTemplate; private int mDataUsageTemplate; - private NetworkRestrictionsPreference mNetworkRestrictionPreference; - private WifiManager mWifiManager; private NetworkPolicyEditor mPolicyEditor; @Override @@ -101,7 +97,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs final Context context = getContext(); NetworkPolicyManager policyManager = NetworkPolicyManager.from(context); - mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mPolicyEditor = new NetworkPolicyEditor(policyManager); boolean hasMobileData = DataUsageUtils.hasMobileData(context); @@ -203,8 +198,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs TemplatePreferenceCategory category = (TemplatePreferenceCategory) inflatePreferences(R.xml.data_usage_wifi); category.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), 0, services); - mNetworkRestrictionPreference = - (NetworkRestrictionsPreference) category.findPreference(KEY_NETWORK_RESTRICTIONS); } private void addEthernetSection() { @@ -293,8 +286,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs mLimitPreference.setSummary(null); } - updateNetworkRestrictionSummary(mNetworkRestrictionPreference); - PreferenceScreen screen = getPreferenceScreen(); for (int i = 1; i < screen.getPreferenceCount(); i++) { ((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services); @@ -321,22 +312,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs updateState(); } - @VisibleForTesting - void updateNetworkRestrictionSummary(NetworkRestrictionsPreference preference) { - if (preference == null) { - return; - } - mPolicyEditor.read(); - int count = 0; - for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { - if (WifiConfiguration.isMetered(config, null)) { - count++; - } - } - preference.setSummary(getResources().getQuantityString( - R.plurals.network_restrictions_summary, count, count)); - } - private static class SummaryProvider implements SummaryLoader.SummaryProvider { @@ -409,7 +384,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs if (!DataUsageUtils.hasWifiRadio(context)) { keys.add(KEY_WIFI_DATA_USAGE); - keys.add(KEY_NETWORK_RESTRICTIONS); } // This title is named Wifi, and will confuse users. diff --git a/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java new file mode 100644 index 00000000000..7df0fb1b79a --- /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 00000000000..0002dac9db9 --- /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 00000000000..5faaef41f60 --- /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/notification/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/AbstractZenModePreferenceController.java index 33c027cd789..81ceca19c77 100644 --- a/src/com/android/settings/notification/AbstractZenModePreferenceController.java +++ b/src/com/android/settings/notification/AbstractZenModePreferenceController.java @@ -31,7 +31,6 @@ import android.service.notification.ScheduleCalendar; import android.service.notification.ZenModeConfig; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; -import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.core.PreferenceControllerMixin; @@ -54,6 +53,7 @@ abstract public class AbstractZenModePreferenceController extends final private NotificationManager mNotificationManager; protected static ZenModeConfigWrapper mZenModeConfigWrapper; protected MetricsFeatureProvider mMetricsFeatureProvider; + protected final ZenModeBackend mBackend; public AbstractZenModePreferenceController(Context context, String key, Lifecycle lifecycle) { @@ -68,6 +68,7 @@ abstract public class AbstractZenModePreferenceController extends final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext); mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); + mBackend = ZenModeBackend.getInstance(context); } @Override @@ -90,6 +91,14 @@ abstract public class AbstractZenModePreferenceController extends } } + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + mBackend.updatePolicy(); + mBackend.updateZenMode(); + } + protected NotificationManager.Policy getPolicy() { return mNotificationManager.getNotificationPolicy(); } @@ -99,8 +108,8 @@ abstract public class AbstractZenModePreferenceController extends } protected int getZenMode() { - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ZEN_MODE, 0); + return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE, + mBackend.mZenMode); } class SettingObserver extends ContentObserver { @@ -188,7 +197,6 @@ abstract public class AbstractZenModePreferenceController extends } } - return endTimeMs; } diff --git a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java index a15f7fca550..af5910760e3 100644 --- a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java @@ -30,11 +30,9 @@ public class ZenModeAlarmsPreferenceController extends AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_alarms"; - private final ZenModeBackend mBackend; public ZenModeAlarmsPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java index 945da0b9ca7..6cee28e26aa 100644 --- a/src/com/android/settings/notification/ZenModeBackend.java +++ b/src/com/android/settings/notification/ZenModeBackend.java @@ -82,7 +82,6 @@ public class ZenModeBackend { mZenMode = zenMode; } - /** gets last zen mode set by setZenMode or updateZenMode **/ protected int getZenMode() { mZenMode = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE, mZenMode); diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java index 1886dab1524..f5169f04500 100644 --- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java @@ -34,11 +34,9 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference protected static final String KEY = "zen_mode_settings_button_container"; private Button mZenButtonOn; private Button mZenButtonOff; - private ZenModeBackend mBackend; public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeCallsPreferenceController.java b/src/com/android/settings/notification/ZenModeCallsPreferenceController.java index d952c11c149..3e2f8022f58 100644 --- a/src/com/android/settings/notification/ZenModeCallsPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeCallsPreferenceController.java @@ -26,11 +26,9 @@ import com.android.settingslib.core.lifecycle.Lifecycle; public class ZenModeCallsPreferenceController extends AbstractZenModePreferenceController { protected static final String KEY = "zen_mode_calls"; - private final ZenModeBackend mBackend; public ZenModeCallsPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeEventsPreferenceController.java b/src/com/android/settings/notification/ZenModeEventsPreferenceController.java index be5e6d6e925..44234949a15 100644 --- a/src/com/android/settings/notification/ZenModeEventsPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeEventsPreferenceController.java @@ -31,11 +31,9 @@ public class ZenModeEventsPreferenceController extends AbstractZenModePreference implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_events"; - private final ZenModeBackend mBackend; public ZenModeEventsPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java index dad6cf13e5c..0ffc44d4b7f 100644 --- a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java @@ -10,11 +10,9 @@ import com.android.settingslib.core.lifecycle.Lifecycle; public class ZenModeMessagesPreferenceController extends AbstractZenModePreferenceController { protected static final String KEY = "zen_mode_messages"; - private final ZenModeBackend mBackend; public ZenModeMessagesPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeRemindersPreferenceController.java b/src/com/android/settings/notification/ZenModeRemindersPreferenceController.java index 99a4f0d7b64..b6c29223584 100644 --- a/src/com/android/settings/notification/ZenModeRemindersPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeRemindersPreferenceController.java @@ -30,11 +30,9 @@ public class ZenModeRemindersPreferenceController extends AbstractZenModePrefere implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_reminders"; - private final ZenModeBackend mBackend; public ZenModeRemindersPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeRepeatCallersPreferenceController.java b/src/com/android/settings/notification/ZenModeRepeatCallersPreferenceController.java index 82fe865885c..d5c0a007119 100644 --- a/src/com/android/settings/notification/ZenModeRepeatCallersPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeRepeatCallersPreferenceController.java @@ -30,11 +30,9 @@ public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePre implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_repeat_callers"; - private final ZenModeBackend mBackend; public ZenModeRepeatCallersPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java b/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java index 0ba24c07a9c..81c9b0d3f72 100644 --- a/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java @@ -29,11 +29,9 @@ public class ZenModeScreenOffPreferenceController extends AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_screen_off"; - private final ZenModeBackend mBackend; public ZenModeScreenOffPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java b/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java index bcb1af89a0b..bab4dd1abce 100644 --- a/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java @@ -29,11 +29,9 @@ public class ZenModeScreenOnPreferenceController extends AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener { protected static final String KEY = "zen_mode_screen_on"; - private final ZenModeBackend mBackend; public ZenModeScreenOnPreferenceController(Context context, Lifecycle lifecycle) { super(context, KEY, lifecycle); - mBackend = ZenModeBackend.getInstance(context); } @Override diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 0207c94ad95..f8125cbe1be 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -36,7 +36,6 @@ import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld; -import com.android.settings.datausage.DataUsageMeteredSettings; import com.android.settings.datausage.DataUsageSummary; import com.android.settings.deletionhelper.AutomaticStorageManagerSettings; import com.android.settings.development.DevelopmentSettingsDashboardFragment; @@ -50,6 +49,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; @@ -110,7 +110,6 @@ public final class SearchIndexableResources { addIndex(BluetoothSettings.class); addIndex(SimSettings.class); addIndex(DataUsageSummary.class); - addIndex(DataUsageMeteredSettings.class); addIndex(ScreenZoomSettings.class); addIndex(DisplaySettings.class); addIndex(AmbientDisplaySettings.class); @@ -174,6 +173,7 @@ public final class SearchIndexableResources { addIndex(ZenModeBehaviorSettings.class); addIndex(ZenModeAutomationSettings.class); addIndex(NightDisplaySettings.class); + addIndex(SmartBatterySettings.class); } private SearchIndexableResources() { diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index 4da7366696a..5e5d5ffaa00 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -146,11 +146,11 @@ public class WifiConfigController implements TextWatcher, private TextView mDns2View; private Spinner mProxySettingsSpinner; + private Spinner mMeteredSettingsSpinner; private TextView mProxyHostView; private TextView mProxyPortView; private TextView mProxyExclusionListView; private TextView mProxyPacView; - private CheckBox mSharedCheckBox; private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED; @@ -208,6 +208,7 @@ public class WifiConfigController implements TextWatcher, mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings); mProxySettingsSpinner.setOnItemSelectedListener(this); mSharedCheckBox = (CheckBox) mView.findViewById(R.id.shared); + mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings); if (mAccessPoint == null) { // new network mConfigUi.setTitle(R.string.wifi_add_network); @@ -237,6 +238,7 @@ public class WifiConfigController implements TextWatcher, boolean showAdvancedFields = false; if (mAccessPoint.isSaved()) { WifiConfiguration config = mAccessPoint.getConfig(); + mMeteredSettingsSpinner.setSelection(config.meteredOverride); if (config.getIpAssignment() == IpAssignment.STATIC) { mIpSettingsSpinner.setSelection(STATIC_IP); showAdvancedFields = true; @@ -671,6 +673,9 @@ public class WifiConfigController implements TextWatcher, config.setIpConfiguration( new IpConfiguration(mIpAssignment, mProxySettings, mStaticIpConfiguration, mHttpProxy)); + if (mMeteredSettingsSpinner != null) { + config.meteredOverride = mMeteredSettingsSpinner.getSelectedItemPosition(); + } return config; } diff --git a/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java b/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java new file mode 100644 index 00000000000..1a3d195a973 --- /dev/null +++ b/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java @@ -0,0 +1,83 @@ +/* + * 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.wifi.details; + +import android.app.backup.BackupManager; +import android.content.Context; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.provider.Settings; +import android.support.annotation.VisibleForTesting; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.DropDownPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.core.AbstractPreferenceController; + +/** + * {@link AbstractPreferenceController} that controls whether the wifi network is metered or not + */ +public class WifiMeteredPreferenceController extends BasePreferenceController implements + Preference.OnPreferenceChangeListener { + + private static final String KEY_WIFI_METERED = "metered"; + private WifiConfiguration mWifiConfiguration; + private WifiManager mWifiManager; + + public WifiMeteredPreferenceController(Context context, WifiConfiguration wifiConfiguration) { + super(context, KEY_WIFI_METERED); + mWifiConfiguration = wifiConfiguration; + mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + } + + @Override + public void updateState(Preference preference) { + final DropDownPreference dropDownPreference = (DropDownPreference) preference; + final int meteredOverride = getMeteredOverride(); + dropDownPreference.setValue(Integer.toString(meteredOverride)); + updateSummary(dropDownPreference, meteredOverride); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + mWifiConfiguration.meteredOverride = Integer.parseInt((String) newValue); + mWifiManager.updateNetwork(mWifiConfiguration); + // Stage the backup of the SettingsProvider package which backs this up + BackupManager.dataChanged("com.android.providers.settings"); + updateSummary((DropDownPreference) preference, getMeteredOverride()); + return true; + } + + @VisibleForTesting + int getMeteredOverride() { + // Wrap the meteredOverride since robolectric cannot recognize it + return mWifiConfiguration.meteredOverride; + } + + private void updateSummary(DropDownPreference preference, int meteredOverride) { + preference.setSummary(preference.getEntries()[meteredOverride]); + } +} diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java index ea30b562f3c..9a5430bcd8b 100644 --- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java +++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java @@ -20,10 +20,13 @@ import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID; import android.app.Dialog; import android.content.Context; import android.net.ConnectivityManager; +import android.net.NetworkPolicyManager; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.support.v7.preference.DropDownPreference; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -122,6 +125,7 @@ public class WifiNetworkDetailsFragment extends DashboardFragment { @Override protected List getPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance( mAccessPoint, @@ -133,6 +137,9 @@ public class WifiNetworkDetailsFragment extends DashboardFragment { context.getSystemService(WifiManager.class), mMetricsFeatureProvider); - return new ArrayList<>(Collections.singletonList(mWifiDetailPreferenceController)); + controllers.add(mWifiDetailPreferenceController); + controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig())); + + return controllers; } } diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java index dc53ca104ea..c1221054c43 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java @@ -68,23 +68,6 @@ public class DataUsageSummaryTest { when(mManager.isNetworkSupported(anyInt())).thenReturn(true); } - @Test - public void testUpdateNetworkRestrictionSummary_shouldSetSummary() { - final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary()); - final NetworkRestrictionsPreference preference = mock(NetworkRestrictionsPreference.class); - final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); - final WifiManager wifiManager = mock(WifiManager.class); - ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); - ReflectionHelpers.setField(dataUsageSummary, "mWifiManager", wifiManager); - when(wifiManager.getConfiguredNetworks()).thenReturn(new ArrayList()); - doReturn(mContext.getResources()).when(dataUsageSummary).getResources(); - - dataUsageSummary.updateNetworkRestrictionSummary(preference); - - verify(preference).setSummary(mContext.getResources().getQuantityString( - R.plurals.network_restrictions_summary, 0, 0)); - } - @Test @Config(shadows = { SettingsShadowResources.class, 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 00000000000..c9441487b32 --- /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"); + } + +} diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiMeteredPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiMeteredPreferenceControllerTest.java new file mode 100644 index 00000000000..f624bd57cdb --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiMeteredPreferenceControllerTest.java @@ -0,0 +1,89 @@ +/* + * 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.wifi.details; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.net.wifi.WifiConfiguration; +import android.support.v7.preference.DropDownPreference; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class WifiMeteredPreferenceControllerTest { + public static final int METERED_OVERRIDE_NONE = 0; + public static final int METERED_OVERRIDE_METERED = 1; + public static final int METERED_OVERRIDE_NOT_METERED = 2; + + @Mock + private WifiConfiguration mWifiConfiguration; + + private WifiMeteredPreferenceController mPreferenceController; + private Context mContext; + private DropDownPreference mDropDownPreference; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + + mPreferenceController = spy( + new WifiMeteredPreferenceController(mContext, mWifiConfiguration)); + mDropDownPreference = new DropDownPreference(mContext); + mDropDownPreference.setEntries(R.array.wifi_metered_entries); + mDropDownPreference.setEntryValues(R.array.wifi_metered_values); + } + + @Test + public void testUpdateState_wifiMetered_setCorrectValue() { + doReturn(METERED_OVERRIDE_METERED).when(mPreferenceController).getMeteredOverride(); + + mPreferenceController.updateState(mDropDownPreference); + + assertThat(mDropDownPreference.getEntry()).isEqualTo("Treat as metered"); + } + + @Test + public void testUpdateState_wifiNotMetered_setCorrectValue() { + doReturn(METERED_OVERRIDE_NOT_METERED).when(mPreferenceController).getMeteredOverride(); + + mPreferenceController.updateState(mDropDownPreference); + + assertThat(mDropDownPreference.getEntry()).isEqualTo("Treat as unmetered"); + } + + @Test + public void testUpdateState_wifiAuto_setCorrectValue() { + doReturn(METERED_OVERRIDE_NONE).when(mPreferenceController).getMeteredOverride(); + + mPreferenceController.updateState(mDropDownPreference); + + assertThat(mDropDownPreference.getEntry()).isEqualTo("Use network preference"); + } +}