Add data saver to settings
Bug: 22817899 Change-Id: Ic3055aa6a5baae1653db350313366f180c049cc7
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
-keep class com.android.settings.wifi.*Settings
|
-keep class com.android.settings.wifi.*Settings
|
||||||
-keep class com.android.settings.deviceinfo.*
|
-keep class com.android.settings.deviceinfo.*
|
||||||
-keep class com.android.settings.bluetooth.*
|
-keep class com.android.settings.bluetooth.*
|
||||||
|
-keep class com.android.settings.datausage.*
|
||||||
-keep class com.android.settings.applications.*
|
-keep class com.android.settings.applications.*
|
||||||
-keep class com.android.settings.inputmethod.*
|
-keep class com.android.settings.inputmethod.*
|
||||||
-keep class com.android.settings.ResetNetwork
|
-keep class com.android.settings.ResetNetwork
|
||||||
|
28
res/drawable/ic_data_saver.xml
Normal file
28
res/drawable/ic_data_saver.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24.0dp"
|
||||||
|
android:height="24.0dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="
|
||||||
|
M9.0,16.0l2.0,0.0L11.0,8.0L9.0,8.0l0.0,8.0z
|
||||||
|
m3.0,-14.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0z
|
||||||
|
m0.0,18.0c-4.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0z
|
||||||
|
m1.0,-4.0l2.0,0.0l0.0,-8.0l-2.0,0.0l0.0,8.0z"/>
|
||||||
|
</vector>
|
@@ -17,7 +17,7 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
@@ -4914,9 +4914,9 @@
|
|||||||
<!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
|
<!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_app_settings">App settings</string>
|
<string name="data_usage_app_settings">App settings</string>
|
||||||
<!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=40] -->
|
<!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=40] -->
|
||||||
<string name="data_usage_app_restrict_background">Restrict app background data</string>
|
<string name="data_usage_app_restrict_background">Background data</string>
|
||||||
<!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=64] -->
|
<!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=NONE] -->
|
||||||
<string name="data_usage_app_restrict_background_summary">Disable background data on cellular networks.</string>
|
<string name="data_usage_app_restrict_background_summary">Enable usage of cellular data in the background</string>
|
||||||
<!-- Summary message for checkbox that restricts background data usage of a specific application when no networks have been limited. [CHAR LIMIT=84] -->
|
<!-- Summary message for checkbox that restricts background data usage of a specific application when no networks have been limited. [CHAR LIMIT=84] -->
|
||||||
<string name="data_usage_app_restrict_background_summary_disabled">To restrict background data for this app, first set a cellular data limit.</string>
|
<string name="data_usage_app_restrict_background_summary_disabled">To restrict background data for this app, first set a cellular data limit.</string>
|
||||||
<!-- Title of dialog shown when user restricts background data usage of a specific application. [CHAR LIMIT=48] -->
|
<!-- Title of dialog shown when user restricts background data usage of a specific application. [CHAR LIMIT=48] -->
|
||||||
@@ -6870,7 +6870,7 @@
|
|||||||
<string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
|
<string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
|
||||||
|
|
||||||
<!-- Title of condition that background data is off [CHAR LIMIT=30] -->
|
<!-- Title of condition that background data is off [CHAR LIMIT=30] -->
|
||||||
<string name="condition_bg_data_title">Background data is off</string>
|
<string name="condition_bg_data_title">Data Saver is on</string>
|
||||||
|
|
||||||
<!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
|
<!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
|
||||||
<string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
|
<string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
|
||||||
@@ -6966,4 +6966,28 @@
|
|||||||
the code to do that -->
|
the code to do that -->
|
||||||
<string name="data_usage_other_apps" translatable="false">Other apps included in usage</string>
|
<string name="data_usage_other_apps" translatable="false">Other apps included in usage</string>
|
||||||
|
|
||||||
|
<!-- Description of number of apps allowed to ignore data saver [CHAR LIMIT=NONE] -->
|
||||||
|
<plurals name="data_saver_unrestricted_summary">
|
||||||
|
<item quantity="one">1 app allowed to use unrestricted data when Data Saver is on</item>
|
||||||
|
<item quantity="other"><xliff:g id="count" example="10">%1$d</xliff:g> apps allowed to use unrestricted data when Data Saver is on</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<!-- Name of Data Saver screens [CHAR LIMIT=30] -->
|
||||||
|
<string name="data_saver_title">Data Saver</string>
|
||||||
|
|
||||||
|
<!-- Button that leads to list of apps with unrestricted data access [CHAR LIMIT=60] -->
|
||||||
|
<string name="unrestricted_data_saver">Unrestricted data access</string>
|
||||||
|
|
||||||
|
<!-- Summary for the data saver feature being on [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="data_saver_on">On</string>
|
||||||
|
|
||||||
|
<!-- Summary for the data saver feature being off [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="data_saver_off">Off</string>
|
||||||
|
|
||||||
|
<!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
|
||||||
|
<string name="unrestricted_app_title">Unrestricted data usage</string>
|
||||||
|
|
||||||
|
<!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
|
||||||
|
<string name="unrestricted_app_summary">Allow unrestricted data access when Data Saver is on</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:title="@string/data_usage_summary_title">
|
android:title="@string/data_usage_summary_title">
|
||||||
|
|
||||||
|
<com.android.settings.datausage.SpinnerPreference
|
||||||
|
android:key="cycle" />
|
||||||
|
|
||||||
<com.android.settings.applications.SpacePreference
|
<com.android.settings.applications.SpacePreference
|
||||||
android:layout_height="8dp" />
|
android:layout_height="8dp" />
|
||||||
|
|
||||||
@@ -50,6 +53,11 @@
|
|||||||
android:title="@string/data_usage_app_restrict_background"
|
android:title="@string/data_usage_app_restrict_background"
|
||||||
android:summary="@string/data_usage_app_restrict_background_summary" />
|
android:summary="@string/data_usage_app_restrict_background_summary" />
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="unrestricted_data_saver"
|
||||||
|
android:title="@string/unrestricted_app_title"
|
||||||
|
android:summary="@string/unrestricted_app_summary" />
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="app_list"
|
android:key="app_list"
|
||||||
android:title="@string/data_usage_other_apps" />
|
android:title="@string/data_usage_other_apps" />
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
Copyright (C) 2016 The Android Open Source Project
|
<!-- Copyright (C) 2016 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,18 +14,12 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:title="@string/data_saver_title">
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<include layout="@layout/app_header" />
|
<Preference
|
||||||
|
android:key="unrestricted_access"
|
||||||
|
android:title="@string/unrestricted_data_saver"
|
||||||
|
android:fragment="com.android.settings.datausage.UnrestrictedDataAccess" />
|
||||||
|
|
||||||
<View
|
</PreferenceScreen>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height=".5dp"
|
|
||||||
android:background="@android:color/white" />
|
|
||||||
|
|
||||||
<include layout="@layout/apps_filter_spinner" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@@ -29,9 +29,10 @@
|
|||||||
android:key="limit_summary"
|
android:key="limit_summary"
|
||||||
android:selectable="false" />
|
android:selectable="false" />
|
||||||
|
|
||||||
<com.android.settings.datausage.RestrictBackgroundDataPreference
|
<com.android.settings.datausage.DataSaverPreference
|
||||||
android:key="restrict_background"
|
android:key="restrict_background"
|
||||||
android:title="@string/data_usage_menu_restrict_background" />
|
android:title="@string/data_saver_title"
|
||||||
|
android:fragment="com.android.settings.datausage.DataSaverSummary" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
@@ -41,6 +41,8 @@ public abstract class InstrumentedFragment extends PreferenceFragment {
|
|||||||
public static final int VIRTUAL_KEYBOARDS = UNDECLARED + 11;
|
public static final int VIRTUAL_KEYBOARDS = UNDECLARED + 11;
|
||||||
public static final int PHYSICAL_KEYBOARDS = UNDECLARED + 12;
|
public static final int PHYSICAL_KEYBOARDS = UNDECLARED + 12;
|
||||||
public static final int ENABLE_VIRTUAL_KEYBOARDS = UNDECLARED + 13;
|
public static final int ENABLE_VIRTUAL_KEYBOARDS = UNDECLARED + 13;
|
||||||
|
public static final int DATA_SAVER_SUMMARY = UNDECLARED + 14;
|
||||||
|
public static final int DATA_USAGE_UNRESTRICTED_ACCESS = UNDECLARED + 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare the view of this category.
|
* Declare the view of this category.
|
||||||
|
@@ -34,7 +34,7 @@ public class BackgroundDataCondition extends Condition {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Icon getIcon() {
|
public Icon getIcon() {
|
||||||
return Icon.createWithResource(mManager.getContext(), R.drawable.ic_cellular_off);
|
return Icon.createWithResource(mManager.getContext(), R.drawable.ic_data_saver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -14,14 +14,6 @@
|
|||||||
|
|
||||||
package com.android.settings.datausage;
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
import com.android.settings.AppHeader;
|
|
||||||
import com.android.settings.InstrumentedFragment;
|
|
||||||
import com.android.settings.R;
|
|
||||||
import com.android.settings.applications.AppInfoBase;
|
|
||||||
import com.android.settingslib.AppItem;
|
|
||||||
import com.android.settingslib.net.ChartData;
|
|
||||||
import com.android.settingslib.net.ChartDataLoader;
|
|
||||||
|
|
||||||
import android.app.LoaderManager;
|
import android.app.LoaderManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -43,10 +35,15 @@ import android.support.v7.preference.Preference;
|
|||||||
import android.support.v7.preference.PreferenceCategory;
|
import android.support.v7.preference.PreferenceCategory;
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.Spinner;
|
import com.android.settings.AppHeader;
|
||||||
|
import com.android.settings.InstrumentedFragment;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.applications.AppInfoBase;
|
||||||
|
import com.android.settingslib.AppItem;
|
||||||
|
import com.android.settingslib.net.ChartData;
|
||||||
|
import com.android.settingslib.net.ChartDataLoader;
|
||||||
|
|
||||||
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
||||||
@@ -62,6 +59,8 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
private static final String KEY_APP_SETTINGS = "app_settings";
|
private static final String KEY_APP_SETTINGS = "app_settings";
|
||||||
private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
|
private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
|
||||||
private static final String KEY_APP_LIST = "app_list";
|
private static final String KEY_APP_LIST = "app_list";
|
||||||
|
private static final String KEY_CYCLE = "cycle";
|
||||||
|
private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
|
||||||
|
|
||||||
private static final int LOADER_CHART_DATA = 2;
|
private static final int LOADER_CHART_DATA = 2;
|
||||||
|
|
||||||
@@ -76,7 +75,6 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
private Drawable mIcon;
|
private Drawable mIcon;
|
||||||
private CharSequence mLabel;
|
private CharSequence mLabel;
|
||||||
private INetworkStatsSession mStatsSession;
|
private INetworkStatsSession mStatsSession;
|
||||||
private Spinner mCycleSpinner;
|
|
||||||
private CycleAdapter mCycleAdapter;
|
private CycleAdapter mCycleAdapter;
|
||||||
|
|
||||||
private long mStart;
|
private long mStart;
|
||||||
@@ -86,6 +84,9 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
private NetworkPolicy mPolicy;
|
private NetworkPolicy mPolicy;
|
||||||
private AppItem mAppItem;
|
private AppItem mAppItem;
|
||||||
private Intent mAppSettingsIntent;
|
private Intent mAppSettingsIntent;
|
||||||
|
private SpinnerPreference mCycle;
|
||||||
|
private SwitchPreference mUnrestrictedData;
|
||||||
|
private DataSaverBackend mDataSaverBackend;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
@@ -137,9 +138,15 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
|
mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
|
||||||
mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
|
mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
|
||||||
|
|
||||||
|
mCycle = (SpinnerPreference) findPreference(KEY_CYCLE);
|
||||||
|
mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener, false);
|
||||||
|
|
||||||
if (UserHandle.isApp(mAppItem.key)) {
|
if (UserHandle.isApp(mAppItem.key)) {
|
||||||
mRestrictBackground = (SwitchPreference) findPreference(KEY_RESTRICT_BACKGROUND);
|
mRestrictBackground = (SwitchPreference) findPreference(KEY_RESTRICT_BACKGROUND);
|
||||||
mRestrictBackground.setOnPreferenceChangeListener(this);
|
mRestrictBackground.setOnPreferenceChangeListener(this);
|
||||||
|
mUnrestrictedData = (SwitchPreference) findPreference(KEY_UNRESTRICTED_DATA);
|
||||||
|
mUnrestrictedData.setOnPreferenceChangeListener(this);
|
||||||
|
mDataSaverBackend = new DataSaverBackend(getContext());
|
||||||
mAppSettings = findPreference(KEY_APP_SETTINGS);
|
mAppSettings = findPreference(KEY_APP_SETTINGS);
|
||||||
|
|
||||||
mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
|
mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
|
||||||
@@ -169,6 +176,7 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
removePreference(KEY_APP_LIST);
|
removePreference(KEY_APP_LIST);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
removePreference(KEY_UNRESTRICTED_DATA);
|
||||||
removePreference(KEY_APP_SETTINGS);
|
removePreference(KEY_APP_SETTINGS);
|
||||||
removePreference(KEY_RESTRICT_BACKGROUND);
|
removePreference(KEY_RESTRICT_BACKGROUND);
|
||||||
removePreference(KEY_APP_LIST);
|
removePreference(KEY_APP_LIST);
|
||||||
@@ -195,6 +203,9 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
if (preference == mRestrictBackground) {
|
if (preference == mRestrictBackground) {
|
||||||
setAppRestrictBackground((Boolean) newValue);
|
setAppRestrictBackground((Boolean) newValue);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (preference == mUnrestrictedData) {
|
||||||
|
mDataSaverBackend.setIsWhitelisted(mAppItem.key, (Boolean) newValue);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -214,6 +225,9 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
if (mRestrictBackground != null) {
|
if (mRestrictBackground != null) {
|
||||||
mRestrictBackground.setChecked(getAppRestrictBackground());
|
mRestrictBackground.setChecked(getAppRestrictBackground());
|
||||||
}
|
}
|
||||||
|
if (mUnrestrictedData != null) {
|
||||||
|
mUnrestrictedData.setChecked(mDataSaverBackend.isWhitelisted(mAppItem.key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addUid(int uid) {
|
private void addUid(int uid) {
|
||||||
@@ -260,7 +274,7 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
View header = setPinnedHeaderView(R.layout.data_usage_app_header);
|
View header = setPinnedHeaderView(R.layout.app_header);
|
||||||
String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
|
String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
|
||||||
int uid = 0;
|
int uid = 0;
|
||||||
try {
|
try {
|
||||||
@@ -269,9 +283,6 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
}
|
}
|
||||||
AppHeader.setupHeaderView(getActivity(), mIcon, mLabel,
|
AppHeader.setupHeaderView(getActivity(), mIcon, mLabel,
|
||||||
pkg, uid, AppHeader.includeAppInfo(this), 0, header);
|
pkg, uid, AppHeader.includeAppInfo(this), 0, header);
|
||||||
|
|
||||||
mCycleSpinner = (Spinner) header.findViewById(R.id.filter_spinner);
|
|
||||||
mCycleAdapter = new CycleAdapter(getContext(), mCycleSpinner, mCycleListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -283,8 +294,7 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
new AdapterView.OnItemSelectedListener() {
|
new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
final CycleAdapter.CycleItem cycle =
|
final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
|
||||||
(CycleAdapter.CycleItem) parent.getItemAtPosition(position);
|
|
||||||
|
|
||||||
mStart = cycle.start;
|
mStart = cycle.start;
|
||||||
mEnd = cycle.end;
|
mEnd = cycle.end;
|
||||||
|
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.settings.applications.AppStateBaseBridge;
|
||||||
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class AppStateDataUsageBridge extends AppStateBaseBridge {
|
||||||
|
|
||||||
|
private static final String TAG = "AppStateDataUsageBridge";
|
||||||
|
|
||||||
|
private final DataSaverBackend mDataSaverBackend;
|
||||||
|
|
||||||
|
public AppStateDataUsageBridge(ApplicationsState appState, Callback callback,
|
||||||
|
DataSaverBackend backend) {
|
||||||
|
super(appState, callback);
|
||||||
|
mDataSaverBackend = backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadAllExtraInfo() {
|
||||||
|
ArrayList<AppEntry> apps = mAppSession.getAllApps();
|
||||||
|
final int N = apps.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
AppEntry app = apps.get(i);
|
||||||
|
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(app.info.uid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
|
||||||
|
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DataUsageState {
|
||||||
|
public boolean isDataSaverWhitelisted;
|
||||||
|
|
||||||
|
public DataUsageState(boolean isDataSaverWhitelisted) {
|
||||||
|
this.isDataSaverWhitelisted = isDataSaverWhitelisted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -13,17 +13,15 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.datausage;
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
import com.android.settings.Utils;
|
|
||||||
import com.android.settingslib.net.ChartData;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.NetworkPolicy;
|
import android.net.NetworkPolicy;
|
||||||
import android.net.NetworkStatsHistory;
|
import android.net.NetworkStatsHistory;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Spinner;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settingslib.net.ChartData;
|
||||||
import libcore.util.Objects;
|
import libcore.util.Objects;
|
||||||
|
|
||||||
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
|
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
|
||||||
@@ -31,12 +29,13 @@ import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
|
|||||||
|
|
||||||
public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
|
public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
|
||||||
|
|
||||||
private final Spinner mSpinner;
|
private final SpinnerInterface mSpinner;
|
||||||
private final AdapterView.OnItemSelectedListener mListener;
|
private final AdapterView.OnItemSelectedListener mListener;
|
||||||
|
|
||||||
public CycleAdapter(Context context, Spinner spinner,
|
public CycleAdapter(Context context, SpinnerInterface spinner,
|
||||||
AdapterView.OnItemSelectedListener listener) {
|
AdapterView.OnItemSelectedListener listener, boolean isHeader) {
|
||||||
super(context, com.android.settings.R.layout.filter_spinner_item);
|
super(context, isHeader ? R.layout.filter_spinner_item
|
||||||
|
: R.layout.data_usage_cycle_item);
|
||||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
mSpinner = spinner;
|
mSpinner = spinner;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
@@ -72,7 +71,7 @@ public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
|
|||||||
mSpinner.getSelectedItem();
|
mSpinner.getSelectedItem();
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
final Context context = mSpinner.getContext();
|
final Context context = getContext();
|
||||||
NetworkStatsHistory.Entry entry = null;
|
NetworkStatsHistory.Entry entry = null;
|
||||||
|
|
||||||
long historyStart = Long.MAX_VALUE;
|
long historyStart = Long.MAX_VALUE;
|
||||||
@@ -141,7 +140,7 @@ public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
|
|||||||
// user-defined inspection region.
|
// user-defined inspection region.
|
||||||
final CycleAdapter.CycleItem selectedItem = getItem(position);
|
final CycleAdapter.CycleItem selectedItem = getItem(position);
|
||||||
if (!Objects.equal(selectedItem, previousItem)) {
|
if (!Objects.equal(selectedItem, previousItem)) {
|
||||||
mListener.onItemSelected(mSpinner, null, position, 0);
|
mListener.onItemSelected(null, null, position, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,4 +184,11 @@ public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
|
|||||||
return Long.compare(start, another.start);
|
return Long.compare(start, another.start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface SpinnerInterface {
|
||||||
|
void setAdapter(CycleAdapter cycleAdapter);
|
||||||
|
void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener);
|
||||||
|
Object getSelectedItem();
|
||||||
|
void setSelection(int position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
148
src/com/android/settings/datausage/DataSaverBackend.java
Normal file
148
src/com/android/settings/datausage/DataSaverBackend.java
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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.content.Context;
|
||||||
|
import android.net.INetworkPolicyListener;
|
||||||
|
import android.net.INetworkPolicyManager;
|
||||||
|
import android.net.NetworkPolicyManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.SparseBooleanArray;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class DataSaverBackend {
|
||||||
|
|
||||||
|
private static final String TAG = "DataSaverBackend";
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
private final Handler mHandler = new Handler();
|
||||||
|
private final NetworkPolicyManager mPolicyManager;
|
||||||
|
private final INetworkPolicyManager mIPolicyManager;
|
||||||
|
private final ArrayList<Listener> mListeners = new ArrayList<>();
|
||||||
|
private SparseBooleanArray mWhitelist;
|
||||||
|
|
||||||
|
// TODO: Staticize into only one.
|
||||||
|
public DataSaverBackend(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mIPolicyManager = INetworkPolicyManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
|
||||||
|
mPolicyManager = NetworkPolicyManager.from(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(Listener listener) {
|
||||||
|
mListeners.add(listener);
|
||||||
|
if (mListeners.size() == 1) {
|
||||||
|
mPolicyManager.registerListener(mPolicyListener);
|
||||||
|
}
|
||||||
|
listener.onDataSaverChanged(isDataSaverEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remListener(Listener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
if (mListeners.size() == 0) {
|
||||||
|
mPolicyManager.unregisterListener(mPolicyListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDataSaverEnabled() {
|
||||||
|
return mPolicyManager.getRestrictBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataSaverEnabled(boolean enabled) {
|
||||||
|
mPolicyManager.setRestrictBackground(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshWhitelist() {
|
||||||
|
loadWhitelist();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsWhitelisted(int uid, boolean whitelisted) {
|
||||||
|
mWhitelist.put(uid, whitelisted);
|
||||||
|
try {
|
||||||
|
if (whitelisted) {
|
||||||
|
mIPolicyManager.addRestrictBackgroundWhitelistedUid(uid);
|
||||||
|
} else {
|
||||||
|
mIPolicyManager.removeRestrictBackgroundWhitelistedUid(uid);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Can't reach policy manager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWhitelisted(int uid) {
|
||||||
|
if (mWhitelist == null) {
|
||||||
|
loadWhitelist();
|
||||||
|
}
|
||||||
|
return mWhitelist.get(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWhitelistedCount() {
|
||||||
|
int count = 0;
|
||||||
|
if (mWhitelist == null) {
|
||||||
|
loadWhitelist();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mWhitelist.size(); i++) {
|
||||||
|
if (mWhitelist.valueAt(i)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadWhitelist() {
|
||||||
|
mWhitelist = new SparseBooleanArray();
|
||||||
|
try {
|
||||||
|
for (int uid : mIPolicyManager.getRestrictBackgroundWhitelistedUids()) {
|
||||||
|
mWhitelist.put(uid, true);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRestrictBackgroundChanged(boolean isDataSaving) {
|
||||||
|
for (int i = 0; i < mListeners.size(); i++) {
|
||||||
|
mListeners.get(i).onDataSaverChanged(isDataSaving);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onUidRulesChanged(int i, int i1) throws RemoteException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
handleRestrictBackgroundChanged(isDataSaving);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
void onDataSaverChanged(boolean isDataSaving);
|
||||||
|
}
|
||||||
|
}
|
47
src/com/android/settings/datausage/DataSaverPreference.java
Normal file
47
src/com/android/settings/datausage/DataSaverPreference.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.content.Context;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
public class DataSaverPreference extends Preference implements DataSaverBackend.Listener {
|
||||||
|
|
||||||
|
private final DataSaverBackend mDataSaverBackend;
|
||||||
|
|
||||||
|
public DataSaverPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
mDataSaverBackend = new DataSaverBackend(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttached() {
|
||||||
|
super.onAttached();
|
||||||
|
mDataSaverBackend.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetached() {
|
||||||
|
super.onDetached();
|
||||||
|
mDataSaverBackend.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataSaverChanged(boolean isDataSaving) {
|
||||||
|
setSummary(isDataSaving ? R.string.data_saver_on : R.string.data_saver_off);
|
||||||
|
}
|
||||||
|
}
|
83
src/com/android/settings/datausage/DataSaverSummary.java
Normal file
83
src/com/android/settings/datausage/DataSaverSummary.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.os.Bundle;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Switch;
|
||||||
|
import com.android.settings.InstrumentedFragment;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.widget.SwitchBar;
|
||||||
|
|
||||||
|
public class DataSaverSummary extends SettingsPreferenceFragment
|
||||||
|
implements SwitchBar.OnSwitchChangeListener, DataSaverBackend.Listener {
|
||||||
|
|
||||||
|
private static final String KEY_UNRESTRICTED_ACCESS = "unrestricted_access";
|
||||||
|
|
||||||
|
private SwitchBar mSwitchBar;
|
||||||
|
private DataSaverBackend mDataSaverBackend;
|
||||||
|
private Preference mUnrestrictedAccess;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
addPreferencesFromResource(R.xml.data_saver);
|
||||||
|
mUnrestrictedAccess = findPreference(KEY_UNRESTRICTED_ACCESS);
|
||||||
|
mDataSaverBackend = new DataSaverBackend(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
|
||||||
|
mSwitchBar.show();
|
||||||
|
mSwitchBar.addOnSwitchChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
mDataSaverBackend.addListener(this);
|
||||||
|
mDataSaverBackend.refreshWhitelist();
|
||||||
|
int count = mDataSaverBackend.getWhitelistedCount();
|
||||||
|
mUnrestrictedAccess.setSummary(getResources().getQuantityString(
|
||||||
|
R.plurals.data_saver_unrestricted_summary, count, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
mDataSaverBackend.remListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||||
|
mDataSaverBackend.setDataSaverEnabled(isChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMetricsCategory() {
|
||||||
|
return InstrumentedFragment.DATA_SAVER_SUMMARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataSaverChanged(boolean isDataSaving) {
|
||||||
|
mSwitchBar.setChecked(isDataSaving);
|
||||||
|
}
|
||||||
|
}
|
@@ -147,7 +147,27 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
|
|
||||||
mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
|
mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
|
||||||
mCycleSpinner = (Spinner) mHeader.findViewById(R.id.filter_spinner);
|
mCycleSpinner = (Spinner) mHeader.findViewById(R.id.filter_spinner);
|
||||||
mCycleAdapter = new CycleAdapter(getContext(), mCycleSpinner, mCycleListener);
|
mCycleAdapter = new CycleAdapter(getContext(), new CycleAdapter.SpinnerInterface() {
|
||||||
|
@Override
|
||||||
|
public void setAdapter(CycleAdapter cycleAdapter) {
|
||||||
|
mCycleSpinner.setAdapter(cycleAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnItemSelectedListener(OnItemSelectedListener listener) {
|
||||||
|
mCycleSpinner.setOnItemSelectedListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSelectedItem() {
|
||||||
|
return mCycleSpinner.getSelectedItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelection(int position) {
|
||||||
|
mCycleSpinner.setSelection(position);
|
||||||
|
}
|
||||||
|
}, mCycleListener, true);
|
||||||
setLoading(true, false);
|
setLoading(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,7 +490,7 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
|
final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
|
||||||
parent.getItemAtPosition(position);
|
mCycleSpinner.getSelectedItem();
|
||||||
|
|
||||||
if (LOGD) {
|
if (LOGD) {
|
||||||
Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
|
Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
|
||||||
|
90
src/com/android/settings/datausage/SpinnerPreference.java
Normal file
90
src/com/android/settings/datausage/SpinnerPreference.java
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.content.Context;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface {
|
||||||
|
|
||||||
|
private CycleAdapter mAdapter;
|
||||||
|
private AdapterView.OnItemSelectedListener mListener;
|
||||||
|
private Object mCurrentObject;
|
||||||
|
private int mPosition;
|
||||||
|
|
||||||
|
public SpinnerPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setLayoutResource(R.layout.data_usage_cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAdapter(CycleAdapter cycleAdapter) {
|
||||||
|
mAdapter = cycleAdapter;
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSelectedItem() {
|
||||||
|
return mCurrentObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelection(int position) {
|
||||||
|
mPosition = position;
|
||||||
|
mCurrentObject = mAdapter.getItem(mPosition);
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||||
|
super.onBindViewHolder(holder);
|
||||||
|
Spinner spinner = (Spinner) holder.findViewById(R.id.cycles_spinner);
|
||||||
|
spinner.setAdapter(mAdapter);
|
||||||
|
spinner.setSelection(mPosition);
|
||||||
|
spinner.setOnItemSelectedListener(mOnSelectedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performClick(View view) {
|
||||||
|
view.findViewById(R.id.cycles_spinner).performClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AdapterView.OnItemSelectedListener mOnSelectedListener
|
||||||
|
= new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
if (mPosition == position) return;
|
||||||
|
mPosition = position;
|
||||||
|
mCurrentObject = mAdapter.getItem(position);
|
||||||
|
mListener.onItemSelected(parent, view, position, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
mListener.onNothingSelected(parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
184
src/com/android/settings/datausage/UnrestrictedDataAccess.java
Normal file
184
src/com/android/settings/datausage/UnrestrictedDataAccess.java
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* 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.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v14.preference.SwitchPreference;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
|
import android.view.View;
|
||||||
|
import com.android.settings.InstrumentedFragment;
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.applications.AppStateBaseBridge;
|
||||||
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class UnrestrictedDataAccess extends SettingsPreferenceFragment
|
||||||
|
implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback, Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
|
private ApplicationsState mApplicationsState;
|
||||||
|
private AppStateDataUsageBridge mDataUsageBridge;
|
||||||
|
private ApplicationsState.Session mSession;
|
||||||
|
private DataSaverBackend mDataSaverBackend;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
|
||||||
|
getPreferenceScreen().setOrderingAsAdded(false);
|
||||||
|
mApplicationsState = ApplicationsState.getInstance(
|
||||||
|
(Application) getContext().getApplicationContext());
|
||||||
|
mDataSaverBackend = new DataSaverBackend(getContext());
|
||||||
|
mDataUsageBridge = new AppStateDataUsageBridge(mApplicationsState, this, mDataSaverBackend);
|
||||||
|
mSession = mApplicationsState.newSession(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
setLoading(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
mSession.resume();
|
||||||
|
mDataUsageBridge.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
mDataUsageBridge.pause();
|
||||||
|
mSession.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
mSession.release();
|
||||||
|
mDataUsageBridge.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onExtraInfoUpdated() {
|
||||||
|
ArrayList<ApplicationsState.AppEntry> apps = mSession.getAllApps();
|
||||||
|
final int N = apps.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
ApplicationsState.AppEntry entry = apps.get(i);
|
||||||
|
String key = entry.info.packageName + "|" + entry.info.uid;
|
||||||
|
AccessPreference preference = (AccessPreference) findPreference(key);
|
||||||
|
if (preference == null) {
|
||||||
|
preference = new AccessPreference(getContext(), entry);
|
||||||
|
preference.setKey(key);
|
||||||
|
preference.setOnPreferenceChangeListener(this);
|
||||||
|
getPreferenceScreen().addPreference(preference);
|
||||||
|
}
|
||||||
|
AppStateDataUsageBridge.DataUsageState state =
|
||||||
|
(AppStateDataUsageBridge.DataUsageState) entry.extraInfo;
|
||||||
|
preference.setChecked(state.isDataSaverWhitelisted);
|
||||||
|
}
|
||||||
|
setLoading(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRunningStateChanged(boolean running) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPackageListChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPackageIconChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPackageSizeChanged(String packageName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAllSizesComputed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLauncherInfoChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadEntriesCompleted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMetricsCategory() {
|
||||||
|
return InstrumentedFragment.DATA_USAGE_UNRESTRICTED_ACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
if (preference instanceof AccessPreference) {
|
||||||
|
AccessPreference accessPreference = (AccessPreference) preference;
|
||||||
|
boolean whitelisted = newValue == Boolean.TRUE;
|
||||||
|
mDataSaverBackend.setIsWhitelisted(accessPreference.mEntry.info.uid, whitelisted);
|
||||||
|
((AppStateDataUsageBridge.DataUsageState) accessPreference.mEntry.extraInfo)
|
||||||
|
.isDataSaverWhitelisted = whitelisted;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AccessPreference extends SwitchPreference {
|
||||||
|
private final ApplicationsState.AppEntry mEntry;
|
||||||
|
|
||||||
|
public AccessPreference(Context context, ApplicationsState.AppEntry entry) {
|
||||||
|
super(context);
|
||||||
|
mEntry = entry;
|
||||||
|
mEntry.ensureLabel(getContext());
|
||||||
|
setTitle(entry.label);
|
||||||
|
setChecked(((AppStateDataUsageBridge.DataUsageState) entry.extraInfo)
|
||||||
|
.isDataSaverWhitelisted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||||
|
holder.itemView.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Ensure we have an icon before binding.
|
||||||
|
mApplicationsState.ensureIcon(mEntry);
|
||||||
|
// This might trigger us to bind again, but it gives an easy way to only load the icon
|
||||||
|
// once its needed, so its probably worth it.
|
||||||
|
setIcon(mEntry.icon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
super.onBindViewHolder(holder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user