1ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey/*
2ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey *
4ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * you may not use this file except in compliance with the License.
6ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * You may obtain a copy of the License at
7ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey *
8ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey *
10ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * See the License for the specific language governing permissions and
14ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * limitations under the License.
15ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey */
16ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
17ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypackage com.android.settings;
18ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
199549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_ETHERNET;
2029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport static android.net.ConnectivityManager.TYPE_MOBILE;
21bdf98e84ab1eeedf9662ed3c08dc917f5fa80f85Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIFI;
2229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIMAX;
2305cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkeyimport static android.net.NetworkPolicy.LIMIT_DISABLED;
24a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkeyimport static android.net.NetworkPolicy.WARNING_DISABLED;
25dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkeyimport static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
26f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE;
27f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
288a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeLastCycleBoundary;
298a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeNextCycleBoundary;
30a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
31a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_4G;
32a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
33a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport static android.net.NetworkTemplate.MATCH_WIFI;
349549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateEthernet;
359549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobile3gLower;
369549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobile4g;
379549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll;
38313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateWifiWildcard;
3977dae91726864c2c88ac317aff6bd086ca468e54Jeff Sharkeyimport static android.net.TrafficStats.GB_IN_BYTES;
4077dae91726864c2c88ac317aff6bd086ca468e54Jeff Sharkeyimport static android.net.TrafficStats.MB_IN_BYTES;
41a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkeyimport static android.net.TrafficStats.UID_REMOVED;
42a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING;
43313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkeyimport static android.telephony.TelephonyManager.SIM_STATE_READY;
44d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
45d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport static android.text.format.DateUtils.FORMAT_SHOW_DATE;
4629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
47b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
48b654cbb896a6e6db9ecec164476b0ac4a3e72774Jeff Sharkeyimport static com.android.settings.Utils.prepareCustomPreferencesList;
49ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
50f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport android.animation.LayoutTransition;
5138305fb1777147cbcb86774c466e88434daff141Jeff Sharkeyimport android.app.ActivityManager;
524c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkeyimport android.app.AlertDialog;
534c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkeyimport android.app.Dialog;
544c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkeyimport android.app.DialogFragment;
55ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.app.Fragment;
565ba0a0295fe940069697967be2f95203acca955dAmith Yamasaniimport android.app.FragmentManager;
57f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport android.app.FragmentTransaction;
58398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks;
599fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkeyimport android.content.ContentResolver;
60ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.content.Context;
614c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkeyimport android.content.DialogInterface;
624dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkeyimport android.content.Intent;
63398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkeyimport android.content.Loader;
6429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.content.SharedPreferences;
65ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.content.pm.PackageManager;
66518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkeyimport android.content.res.Resources;
6754d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkeyimport android.graphics.Color;
685d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkeyimport android.graphics.drawable.ColorDrawable;
69d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.graphics.drawable.Drawable;
7029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.net.ConnectivityManager;
718a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.net.INetworkPolicyManager;
72ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.net.INetworkStatsService;
7308ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkeyimport android.net.INetworkStatsSession;
748a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.net.NetworkPolicy;
75dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkeyimport android.net.NetworkPolicyManager;
76ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.net.NetworkStats;
77ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.net.NetworkStatsHistory;
78a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport android.net.NetworkTemplate;
7908ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkeyimport android.net.TrafficStats;
80b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasaniimport android.net.Uri;
81aa5260e40a162c8990830da7648f0c850350360cJeff Sharkeyimport android.os.AsyncTask;
82ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.os.Bundle;
831ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkeyimport android.os.INetworkManagementService;
84ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkeyimport android.os.Parcel;
85ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkeyimport android.os.Parcelable;
86ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.os.RemoteException;
87ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.os.ServiceManager;
889549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport android.os.SystemProperties;
89bb06a427eb471227cf42a8078a54ca0581309493Dianne Hackbornimport android.os.UserHandle;
908a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.preference.Preference;
91313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkeyimport android.preference.PreferenceActivity;
929fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkeyimport android.provider.Settings;
9305cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkeyimport android.telephony.TelephonyManager;
948e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkeyimport android.text.TextUtils;
95ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.text.format.DateUtils;
96ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.text.format.Formatter;
97e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkeyimport android.text.format.Time;
98ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.util.Log;
9954d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkeyimport android.util.SparseArray;
100ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkeyimport android.util.SparseBooleanArray;
101ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.LayoutInflater;
1028a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.view.Menu;
1038a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.view.MenuInflater;
1048a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.view.MenuItem;
105ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.View;
106f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport android.view.View.OnClickListener;
107ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.ViewGroup;
1088a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.AdapterView;
1098a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.AdapterView.OnItemClickListener;
1108a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.AdapterView.OnItemSelectedListener;
1118a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.ArrayAdapter;
112ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.widget.BaseAdapter;
113f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkeyimport android.widget.Button;
11429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.widget.CheckBox;
11529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.widget.CompoundButton;
11629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.widget.CompoundButton.OnCheckedChangeListener;
117d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.widget.ImageView;
1188a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.LinearLayout;
119ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.widget.ListView;
1204c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkeyimport android.widget.NumberPicker;
1212412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkeyimport android.widget.ProgressBar;
1228a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.Spinner;
12329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkeyimport android.widget.Switch;
1248a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.TabHost;
1258a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.TabHost.OnTabChangeListener;
1268a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.TabHost.TabContentFactory;
1278a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.TabHost.TabSpec;
1288a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport android.widget.TabWidget;
129ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.widget.TextView;
130ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1315543404ae0ec9635b59d37fa01074ea598d539ebWink Savilleimport com.android.internal.telephony.PhoneConstants;
1325d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkeyimport com.android.settings.drawable.InsetBoundsDrawable;
133b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport com.android.settings.net.ChartData;
134b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport com.android.settings.net.ChartDataLoader;
135313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkeyimport com.android.settings.net.DataUsageMeteredSettings;
136a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkeyimport com.android.settings.net.NetworkPolicyEditor;
137398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkeyimport com.android.settings.net.SummaryForAllUidLoader;
138b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport com.android.settings.net.UidDetail;
139b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport com.android.settings.net.UidDetailProvider;
14055d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkeyimport com.android.settings.widget.ChartDataUsageView;
14155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkeyimport com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
14254d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkeyimport com.android.settings.widget.PieChartView;
143ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport com.google.android.collect.Lists;
144ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
145ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport java.util.ArrayList;
146ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport java.util.Collections;
147a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkeyimport java.util.List;
1488a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkeyimport java.util.Locale;
149ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1509549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkeyimport libcore.util.Objects;
1519549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
15229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey/**
153313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey * Panel showing data usage history across various networks, including options
154313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey * to inspect based on usage cycle and control through {@link NetworkPolicy}.
15529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey */
156ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypublic class DataUsageSummary extends Fragment {
157ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    private static final String TAG = "DataUsage";
158bdf98e84ab1eeedf9662ed3c08dc917f5fa80f85Jeff Sharkey    private static final boolean LOGD = false;
159ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1609549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    // TODO: remove this testing code
161d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private static final boolean TEST_ANIM = false;
1629549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    private static final boolean TEST_RADIOS = false;
163f3871fb2b232cd22469ccc66415f82de4995894eJeff Sharkey
1649549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    private static final String TEST_RADIOS_PROP = "test.radios";
165f3871fb2b232cd22469ccc66415f82de4995894eJeff Sharkey    private static final String TEST_SUBSCRIBER_PROP = "test.subscriberid";
1669549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
1678a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private static final String TAB_3G = "3g";
1688a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private static final String TAB_4G = "4g";
1698a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private static final String TAB_MOBILE = "mobile";
1708a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private static final String TAB_WIFI = "wifi";
1719549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    private static final String TAB_ETHERNET = "ethernet";
172ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
17328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    private static final String TAG_CONFIRM_DATA_DISABLE = "confirmDataDisable";
17428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    private static final String TAG_CONFIRM_DATA_ROAMING = "confirmDataRoaming";
1754c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
1764c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    private static final String TAG_CYCLE_EDITOR = "cycleEditor";
177a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private static final String TAG_WARNING_EDITOR = "warningEditor";
178a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private static final String TAG_LIMIT_EDITOR = "limitEditor";
179f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
180a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private static final String TAG_DENIED_RESTRICT = "deniedRestrict";
1819fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private static final String TAG_CONFIRM_APP_RESTRICT = "confirmAppRestrict";
182d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    private static final String TAG_CONFIRM_AUTO_SYNC_CHANGE = "confirmAutoSyncChange";
183f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private static final String TAG_APP_DETAILS = "appDetails";
1844c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
185b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private static final int LOADER_CHART_DATA = 2;
186b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private static final int LOADER_SUMMARY = 3;
187398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey
1881ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey    private INetworkManagementService mNetworkService;
189ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    private INetworkStatsService mStatsService;
190313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    private NetworkPolicyManager mPolicyManager;
19129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private ConnectivityManager mConnService;
19229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
19308ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey    private INetworkStatsSession mStatsSession;
19408ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey
19529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private static final String PREF_FILE = "data_usage";
19629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private static final String PREF_SHOW_WIFI = "show_wifi";
1979549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    private static final String PREF_SHOW_ETHERNET = "show_ethernet";
19829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
19929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private SharedPreferences mPrefs;
200ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
2018a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private TabHost mTabHost;
2022af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey    private ViewGroup mTabsContainer;
2038a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private TabWidget mTabWidget;
2048a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private ListView mListView;
2058a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private DataUsageAdapter mAdapter;
206ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
207b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    /** Distance to inset content from sides, when needed. */
208b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private int mInsetSide = 0;
209b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
210f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private ViewGroup mHeader;
211ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
2122af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey    private ViewGroup mNetworkSwitchesContainer;
213f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private LinearLayout mNetworkSwitches;
21429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private Switch mDataEnabled;
2158a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private View mDataEnabledView;
216f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private CheckBox mDisableAtLimit;
2178a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private View mDisableAtLimitView;
218ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
219d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private View mCycleView;
2208a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private Spinner mCycleSpinner;
2218a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private CycleAdapter mCycleAdapter;
222ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
22355d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey    private ChartDataUsageView mChart;
224d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private TextView mUsageSummary;
225e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey    private TextView mEmpty;
226f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
227f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private View mAppDetail;
228d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey    private ImageView mAppIcon;
229d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey    private ViewGroup mAppTitles;
23054d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey    private PieChartView mAppPieChart;
23154d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey    private TextView mAppForeground;
23254d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey    private TextView mAppBackground;
233f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private Button mAppSettings;
234f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
235f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private LinearLayout mAppSwitches;
236f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private CheckBox mAppRestrict;
237f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private View mAppRestrictView;
238f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
2398a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private boolean mShowWifi = false;
2409549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    private boolean mShowEthernet = false;
241ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
242b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private NetworkTemplate mTemplate;
243b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private ChartData mChartData;
244ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
245ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey    private AppItem mCurrentApp = null;
246f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
247f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private Intent mAppSettingsIntent;
248f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
249a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey    private NetworkPolicyEditor mPolicyEditor;
250f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
2512af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey    private String mCurrentTab = null;
252dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey    private String mIntentTab = null;
253dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey
2549fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private MenuItem mMenuDataRoaming;
2559fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private MenuItem mMenuRestrictBackground;
256d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    private MenuItem mMenuAutoSync;
2579fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
25829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /** Flag used to ignore listeners during binding. */
25929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private boolean mBinding;
26029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
261b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private UidDetailProvider mUidDetailProvider;
262b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
2638a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    @Override
2648a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public void onCreate(Bundle savedInstanceState) {
2658a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        super.onCreate(savedInstanceState);
266313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final Context context = getActivity();
267ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
2681ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        mNetworkService = INetworkManagementService.Stub.asInterface(
2691ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
270ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        mStatsService = INetworkStatsService.Stub.asInterface(
271ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
272313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mPolicyManager = NetworkPolicyManager.from(context);
273313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mConnService = ConnectivityManager.from(context);
2749fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
27529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        mPrefs = getActivity().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
27605cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
277313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mPolicyEditor = new NetworkPolicyEditor(mPolicyManager);
278a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey        mPolicyEditor.read();
27905cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
28029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        mShowWifi = mPrefs.getBoolean(PREF_SHOW_WIFI, false);
2819549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        mShowEthernet = mPrefs.getBoolean(PREF_SHOW_ETHERNET, false);
28229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
2830bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey        // override preferences when no mobile radio
2840bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey        if (!hasReadyMobileRadio(context)) {
2850bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey            mShowWifi = hasWifiRadio(context);
2860bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey            mShowEthernet = hasEthernet(context);
2870bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey        }
2880bc5b93fe22b5e3c18b2edace37f3bb01d09934eJeff Sharkey
28905cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey        setHasOptionsMenu(true);
2908a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
291ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
2928a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    @Override
2938a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public View onCreateView(LayoutInflater inflater, ViewGroup container,
2948a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            Bundle savedInstanceState) {
295ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
2968a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        final Context context = inflater.getContext();
2978a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        final View view = inflater.inflate(R.layout.data_usage_summary, container, false);
298ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
299b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mUidDetailProvider = new UidDetailProvider(context);
300b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
30108ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey        try {
30208ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey            mStatsSession = mStatsService.openSession();
30308ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey        } catch (RemoteException e) {
30408ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey            throw new RuntimeException(e);
30508ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey        }
30608ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey
3078a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
3082af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey        mTabsContainer = (ViewGroup) view.findViewById(R.id.tabs_container);
3098a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mTabWidget = (TabWidget) view.findViewById(android.R.id.tabs);
3108a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mListView = (ListView) view.findViewById(android.R.id.list);
311ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
312b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // decide if we need to manually inset our content, or if we should rely
313b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // on parent container for inset.
314b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final boolean shouldInset = mListView.getScrollBarStyle()
315b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                == View.SCROLLBARS_OUTSIDE_OVERLAY;
316b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (shouldInset) {
317b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mInsetSide = view.getResources().getDimensionPixelOffset(
318b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    com.android.internal.R.dimen.preference_fragment_padding_side);
319b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        } else {
320b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mInsetSide = 0;
321b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
322b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
323b654cbb896a6e6db9ecec164476b0ac4a3e72774Jeff Sharkey        // adjust padding around tabwidget as needed
3245d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        prepareCustomPreferencesList(container, view, mListView, true);
3255d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey
3268a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mTabHost.setup();
3278a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mTabHost.setOnTabChangedListener(mTabListener);
328ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
329f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        mHeader = (ViewGroup) inflater.inflate(R.layout.data_usage_header, mListView, false);
330a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        mHeader.setClickable(true);
331a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
332a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        mListView.addHeaderView(mHeader, null, true);
333a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        mListView.setItemsCanFocus(true);
334ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
335b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (mInsetSide > 0) {
336b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            // inset selector and divider drawables
337b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            insetListViewDrawables(mListView, mInsetSide);
338b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mHeader.setPadding(mInsetSide, 0, mInsetSide, 0);
339b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
340b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
341f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        {
342f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            // bind network switches
3432af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey            mNetworkSwitchesContainer = (ViewGroup) mHeader.findViewById(
3442af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey                    R.id.network_switches_container);
345f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mNetworkSwitches = (LinearLayout) mHeader.findViewById(R.id.network_switches);
346ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
347f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDataEnabled = new Switch(inflater.getContext());
348f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDataEnabledView = inflatePreference(inflater, mNetworkSwitches, mDataEnabled);
349f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDataEnabled.setOnCheckedChangeListener(mDataEnabledListener);
350f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mNetworkSwitches.addView(mDataEnabledView);
351ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
352f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDisableAtLimit = new CheckBox(inflater.getContext());
353f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDisableAtLimit.setClickable(false);
354a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mDisableAtLimit.setFocusable(false);
355f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDisableAtLimitView = inflatePreference(inflater, mNetworkSwitches, mDisableAtLimit);
356a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mDisableAtLimitView.setClickable(true);
357a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mDisableAtLimitView.setFocusable(true);
358f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
359f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mNetworkSwitches.addView(mDisableAtLimitView);
360f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
3618a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
362f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        // bind cycle dropdown
363d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        mCycleView = mHeader.findViewById(R.id.cycles);
364d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
3658a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mCycleAdapter = new CycleAdapter(context);
3668a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mCycleSpinner.setAdapter(mCycleAdapter);
3678a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mCycleSpinner.setOnItemSelectedListener(mCycleListener);
368ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
36955d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        mChart = (ChartDataUsageView) mHeader.findViewById(R.id.chart);
3708a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mChart.setListener(mChartListener);
371bdf98e84ab1eeedf9662ed3c08dc917f5fa80f85Jeff Sharkey        mChart.bindNetworkPolicy(null);
372f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
373f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        {
374f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            // bind app detail controls
375d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            mAppDetail = mHeader.findViewById(R.id.app_detail);
376d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            mAppIcon = (ImageView) mAppDetail.findViewById(R.id.app_icon);
377d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            mAppTitles = (ViewGroup) mAppDetail.findViewById(R.id.app_titles);
37854d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart = (PieChartView) mAppDetail.findViewById(R.id.app_pie_chart);
37954d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppForeground = (TextView) mAppDetail.findViewById(R.id.app_foreground);
38054d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppBackground = (TextView) mAppDetail.findViewById(R.id.app_background);
381d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
382f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
383d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
384f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSettings.setOnClickListener(mAppSettingsListener);
385f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
386f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppRestrict = new CheckBox(inflater.getContext());
387f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppRestrict.setClickable(false);
388a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mAppRestrict.setFocusable(false);
389f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict);
390a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mAppRestrictView.setClickable(true);
391a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mAppRestrictView.setFocusable(true);
392f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppRestrictView.setOnClickListener(mAppRestrictListener);
393f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSwitches.addView(mAppRestrictView);
394f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
395f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
396d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        mUsageSummary = (TextView) mHeader.findViewById(R.id.usage_summary);
397e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey        mEmpty = (TextView) mHeader.findViewById(android.R.id.empty);
398d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
399b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mAdapter = new DataUsageAdapter(mUidDetailProvider, mInsetSide);
4008a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mListView.setOnItemClickListener(mListListener);
4018a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mListView.setAdapter(mAdapter);
402ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
403ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        return view;
404ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
405ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
406ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    @Override
407ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    public void onResume() {
408ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        super.onResume();
409ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
410dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey        // pick default tab based on incoming intent
411dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey        final Intent intent = getActivity().getIntent();
412dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey        mIntentTab = computeTabFromIntent(intent);
413dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey
4148a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        // this kicks off chain reaction which creates tabs, binds the body to
4158a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        // selected network, and binds chart, cycles and detail list.
4168a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        updateTabs();
417dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey
418398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        // kick off background task to update stats
419398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        new AsyncTask<Void, Void, Void>() {
420398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            @Override
421398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            protected Void doInBackground(Void... params) {
422398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey                try {
423b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    // wait a few seconds before kicking off
424b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
425398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey                    mStatsService.forceUpdate();
426b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                } catch (InterruptedException e) {
427398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey                } catch (RemoteException e) {
428398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey                }
429398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey                return null;
430398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            }
431398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey
432398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            @Override
433398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            protected void onPostExecute(Void result) {
4349549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                if (isAdded()) {
4359549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                    updateBody();
4369549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                }
437398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            }
438b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
4398a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
440ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
4418a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    @Override
4428a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
4438a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        inflater.inflate(R.menu.data_usage, menu);
444ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
445ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
4468a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    @Override
44705cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    public void onPrepareOptionsMenu(Menu menu) {
44829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final Context context = getActivity();
449b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final boolean appDetailMode = isAppDetailMode();
45038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
45129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
4529fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming);
453313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
4549fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        mMenuDataRoaming.setChecked(getDataRoaming());
4559fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
4569fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
457313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mMenuRestrictBackground.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
458313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground());
45938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        mMenuRestrictBackground.setVisible(isOwner);
4609fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
461d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        mMenuAutoSync = menu.findItem(R.id.data_usage_menu_auto_sync);
462d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        mMenuAutoSync.setChecked(ContentResolver.getMasterSyncAutomatically());
463fda48e39d36dae29a5ab962f232ed26f54abb44fJeff Sharkey        mMenuAutoSync.setVisible(!appDetailMode);
464d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
4659fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g);
46638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        split4g.setVisible(hasReadyMobile4gRadio(context) && isOwner && !appDetailMode);
467a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey        split4g.setChecked(isMobilePolicySplit());
46829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
4699fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
470313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (hasWifiRadio(context) && hasReadyMobileRadio(context)) {
471b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            showWifi.setVisible(!appDetailMode);
4729549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            showWifi.setChecked(mShowWifi);
4739549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        } else {
4749549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            showWifi.setVisible(false);
4759549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
47629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
4779549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        final MenuItem showEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet);
478313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (hasEthernet(context) && hasReadyMobileRadio(context)) {
479b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            showEthernet.setVisible(!appDetailMode);
4809549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            showEthernet.setChecked(mShowEthernet);
4819549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        } else {
4829549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            showEthernet.setVisible(false);
4839549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
484313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey
485313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
486313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
4879627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            metered.setVisible(!appDetailMode);
488313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        } else {
489313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            metered.setVisible(false);
490313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        }
491b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani
492b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani        final MenuItem help = menu.findItem(R.id.data_usage_menu_help);
493b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani        String helpUrl;
494b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani        if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_data_usage))) {
495aeb57edaef1abdcdcd21eb443047386940ffb755Amith Yamasani            HelpUtils.prepareHelpMenuItem(context, help, helpUrl);
496b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani        } else {
497b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani            help.setVisible(false);
498b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani        }
49905cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    }
5008a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
50105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    @Override
50205cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    public boolean onOptionsItemSelected(MenuItem item) {
5038a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        switch (item.getItemId()) {
5049fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            case R.id.data_usage_menu_roaming: {
5059fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                final boolean dataRoaming = !item.isChecked();
5069fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                if (dataRoaming) {
5079fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    ConfirmDataRoamingFragment.show(this);
5089fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                } else {
5099fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    // no confirmation to disable roaming
5109fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    setDataRoaming(false);
5119fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                }
5129fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                return true;
5139fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            }
5149fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            case R.id.data_usage_menu_restrict_background: {
5159fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                final boolean restrictBackground = !item.isChecked();
5169fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                if (restrictBackground) {
5173038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                    ConfirmRestrictFragment.show(this);
5189fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                } else {
5199fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    // no confirmation to drop restriction
5209fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    setRestrictBackground(false);
5219fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                }
5229fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                return true;
5239fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            }
5249fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            case R.id.data_usage_menu_split_4g: {
52505cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                final boolean mobileSplit = !item.isChecked();
526a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey                setMobilePolicySplit(mobileSplit);
527a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey                item.setChecked(isMobilePolicySplit());
5288a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                updateTabs();
5298a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                return true;
5308a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            }
5319fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            case R.id.data_usage_menu_show_wifi: {
5328a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                mShowWifi = !item.isChecked();
53329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey                mPrefs.edit().putBoolean(PREF_SHOW_WIFI, mShowWifi).apply();
5348a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                item.setChecked(mShowWifi);
5358a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                updateTabs();
5368a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                return true;
5378a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            }
5389549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            case R.id.data_usage_menu_show_ethernet: {
5399549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                mShowEthernet = !item.isChecked();
5409549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                mPrefs.edit().putBoolean(PREF_SHOW_ETHERNET, mShowEthernet).apply();
5419549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                item.setChecked(mShowEthernet);
5429549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                updateTabs();
5439549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                return true;
5449549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            }
545313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            case R.id.data_usage_menu_metered: {
546313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                final PreferenceActivity activity = (PreferenceActivity) getActivity();
547313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                activity.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
548313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                        R.string.data_usage_metered_title, null, this, 0);
549313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                return true;
550313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            }
551d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            case R.id.data_usage_menu_auto_sync: {
552167ba2af93e25500e8d9499b3433f7b2c67fad58Guang Zhu                if (ActivityManager.isUserAMonkey()) {
553167ba2af93e25500e8d9499b3433f7b2c67fad58Guang Zhu                    Log.d("SyncState", "ignoring monkey's attempt to flip global sync state");
554167ba2af93e25500e8d9499b3433f7b2c67fad58Guang Zhu                } else {
555167ba2af93e25500e8d9499b3433f7b2c67fad58Guang Zhu                    ConfirmAutoSyncChangeFragment.show(this, !item.isChecked());
556167ba2af93e25500e8d9499b3433f7b2c67fad58Guang Zhu                }
557d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                return true;
558d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            }
559ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
5608a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        return false;
561ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
562ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
56394a9095eac680acdd0f1833232b69c7efd0fa7a0Jeff Sharkey    @Override
56402b327e7f28bc24771f644ab2d98cf0ad4f2e650Jeff Sharkey    public void onDestroy() {
56594a9095eac680acdd0f1833232b69c7efd0fa7a0Jeff Sharkey        mDataEnabledView = null;
56694a9095eac680acdd0f1833232b69c7efd0fa7a0Jeff Sharkey        mDisableAtLimitView = null;
567b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
568b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mUidDetailProvider.clearCache();
569b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mUidDetailProvider = null;
57008ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey
57108ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey        TrafficStats.closeQuietly(mStatsSession);
57294a9095eac680acdd0f1833232b69c7efd0fa7a0Jeff Sharkey
5735ba0a0295fe940069697967be2f95203acca955dAmith Yamasani        if (this.isRemoving()) {
5745ba0a0295fe940069697967be2f95203acca955dAmith Yamasani            getFragmentManager()
5755ba0a0295fe940069697967be2f95203acca955dAmith Yamasani                    .popBackStack(TAG_APP_DETAILS, FragmentManager.POP_BACK_STACK_INCLUSIVE);
5765ba0a0295fe940069697967be2f95203acca955dAmith Yamasani        }
57702b327e7f28bc24771f644ab2d98cf0ad4f2e650Jeff Sharkey
5785ba0a0295fe940069697967be2f95203acca955dAmith Yamasani        super.onDestroy();
5795ba0a0295fe940069697967be2f95203acca955dAmith Yamasani    }
5805ba0a0295fe940069697967be2f95203acca955dAmith Yamasani
5818a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
58292811829b3658288208470b386cf32b12e3b89eeJeff Sharkey     * Build and assign {@link LayoutTransition} to various containers. Should
58392811829b3658288208470b386cf32b12e3b89eeJeff Sharkey     * only be assigned after initial layout is complete.
5842af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey     */
58592811829b3658288208470b386cf32b12e3b89eeJeff Sharkey    private void ensureLayoutTransitions() {
58692811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        // skip when already setup
58792811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        if (mChart.getLayoutTransition() != null) return;
58892811829b3658288208470b386cf32b12e3b89eeJeff Sharkey
58992811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        mTabsContainer.setLayoutTransition(buildLayoutTransition());
59092811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        mHeader.setLayoutTransition(buildLayoutTransition());
59192811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        mNetworkSwitchesContainer.setLayoutTransition(buildLayoutTransition());
59292811829b3658288208470b386cf32b12e3b89eeJeff Sharkey
59392811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        final LayoutTransition chartTransition = buildLayoutTransition();
59492811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        chartTransition.disableTransitionType(LayoutTransition.APPEARING);
59592811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        chartTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
59692811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        mChart.setLayoutTransition(chartTransition);
59792811829b3658288208470b386cf32b12e3b89eeJeff Sharkey    }
5982af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey
599d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private static LayoutTransition buildLayoutTransition() {
600d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        final LayoutTransition transition = new LayoutTransition();
601d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        if (TEST_ANIM) {
602d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            transition.setDuration(1500);
603d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        }
604d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        transition.setAnimateParentHierarchy(false);
605d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        return transition;
606d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    }
607d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
6082af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey    /**
609a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey     * Rebuild all tabs based on {@link NetworkPolicyEditor} and
61005cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey     * {@link #mShowWifi}, hiding the tabs entirely when applicable. Selects
61105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey     * first tab, and kicks off a full rebind of body contents.
6128a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
6138a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private void updateTabs() {
61429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final Context context = getActivity();
6158a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mTabHost.clearAllTabs();
616ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
61729d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final boolean mobileSplit = isMobilePolicySplit();
618ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey        if (mobileSplit && hasReadyMobile4gRadio(context)) {
6198a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            mTabHost.addTab(buildTabSpec(TAB_3G, R.string.data_usage_tab_3g));
6208a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            mTabHost.addTab(buildTabSpec(TAB_4G, R.string.data_usage_tab_4g));
621313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        } else if (hasReadyMobileRadio(context)) {
6229549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mTabHost.addTab(buildTabSpec(TAB_MOBILE, R.string.data_usage_tab_mobile));
623ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
6249549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (mShowWifi && hasWifiRadio(context)) {
6258a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            mTabHost.addTab(buildTabSpec(TAB_WIFI, R.string.data_usage_tab_wifi));
626ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
6279549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (mShowEthernet && hasEthernet(context)) {
6289549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mTabHost.addTab(buildTabSpec(TAB_ETHERNET, R.string.data_usage_tab_ethernet));
6299549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
630ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
631ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey        final boolean noTabs = mTabWidget.getTabCount() == 0;
6329549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        final boolean multipleTabs = mTabWidget.getTabCount() > 1;
6339549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        mTabWidget.setVisibility(multipleTabs ? View.VISIBLE : View.GONE);
6349549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (mIntentTab != null) {
6359549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            if (Objects.equal(mIntentTab, mTabHost.getCurrentTabTag())) {
636b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                // already hit updateBody() when added; ignore
6379549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey                updateBody();
6389549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            } else {
639dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                mTabHost.setCurrentTabByTag(mIntentTab);
6409549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            }
6419549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mIntentTab = null;
642ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey        } else if (noTabs) {
643ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey            // no usable tabs, so hide body
644ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey            updateBody();
6459549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        } else {
646b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            // already hit updateBody() when added; ignore
6478a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
6488a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
649ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
650ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    /**
6518a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Factory that provide empty {@link View} to make {@link TabHost} happy.
652ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey     */
6538a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private TabContentFactory mEmptyTabContent = new TabContentFactory() {
65476c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
6558a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public View createTabContent(String tag) {
6568a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            return new View(mTabHost.getContext());
6578a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
6588a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
659ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
6608a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
6618a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Build {@link TabSpec} with thin indicator, and empty content.
6628a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
6638a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private TabSpec buildTabSpec(String tag, int titleRes) {
66454d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey        return mTabHost.newTabSpec(tag).setIndicator(getText(titleRes)).setContent(
66554d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey                mEmptyTabContent);
6668a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
667ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
6688a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private OnTabChangeListener mTabListener = new OnTabChangeListener() {
66976c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
6708a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onTabChanged(String tabId) {
6718a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            // user changed tab; update body
6728a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            updateBody();
673ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
6748a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
675ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
6768a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
6778a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Update body content based on current tab. Loads
6788a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and
6798a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * binds them to visible controls.
6808a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
6818a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private void updateBody() {
68229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        mBinding = true;
683b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (!isAdded()) return;
6848a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
685a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey        final Context context = getActivity();
6869549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        final String currentTab = mTabHost.getCurrentTabTag();
68738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
68829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
6899549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (currentTab == null) {
6909549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            Log.w(TAG, "no tab selected; hiding body");
6919549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mListView.setVisibility(View.GONE);
6929549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return;
69329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        } else {
6949549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mListView.setVisibility(View.VISIBLE);
69529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        }
696a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey
6972af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey        final boolean tabChanged = !currentTab.equals(mCurrentTab);
6982af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey        mCurrentTab = currentTab;
6992af35fb44d385d7a04ea1b421c426a0350f0e896Jeff Sharkey
7008a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
7018a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
70238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        mDataEnabledView.setVisibility(isOwner ? View.VISIBLE : View.GONE);
703ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
704313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        // TODO: remove mobile tabs when SIM isn't ready
705313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
706313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey
7078a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        if (TAB_MOBILE.equals(currentTab)) {
70829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDataEnabledView, R.string.data_usage_enable_mobile);
70929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDisableAtLimitView, R.string.data_usage_disable_mobile_limit);
7109549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mTemplate = buildTemplateMobileAll(getActiveSubscriberId(context));
7118a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
7128a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        } else if (TAB_3G.equals(currentTab)) {
71329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDataEnabledView, R.string.data_usage_enable_3g);
71429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDisableAtLimitView, R.string.data_usage_disable_3g_limit);
71529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            // TODO: bind mDataEnabled to 3G radio state
7169549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mTemplate = buildTemplateMobile3gLower(getActiveSubscriberId(context));
7178a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
7188a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        } else if (TAB_4G.equals(currentTab)) {
71929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDataEnabledView, R.string.data_usage_enable_4g);
72029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            setPreferenceTitle(mDisableAtLimitView, R.string.data_usage_disable_4g_limit);
72129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            // TODO: bind mDataEnabled to 4G radio state
7229549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            mTemplate = buildTemplateMobile4g(getActiveSubscriberId(context));
723131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey
724131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey        } else if (TAB_WIFI.equals(currentTab)) {
72555d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            // wifi doesn't have any controls
726131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            mDataEnabledView.setVisibility(View.GONE);
72755d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            mDisableAtLimitView.setVisibility(View.GONE);
728313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            mTemplate = buildTemplateWifiWildcard();
729131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey
730131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey        } else if (TAB_ETHERNET.equals(currentTab)) {
731131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            // ethernet doesn't have any controls
732131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            mDataEnabledView.setVisibility(View.GONE);
733131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            mDisableAtLimitView.setVisibility(View.GONE);
734131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            mTemplate = buildTemplateEthernet();
735131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey
736131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey        } else {
737131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            throw new IllegalStateException("unknown tab: " + currentTab);
738ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
739ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
740b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // kick off loader for network history
741b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // TODO: consider chaining two loaders together instead of reloading
742b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // network history when showing app detail.
743b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        getLoaderManager().restartLoader(LOADER_CHART_DATA,
744ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey                ChartDataLoader.buildArgs(mTemplate, mCurrentApp), mChartDataCallbacks);
7458a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
746b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // detail mode can change visible menus, invalidate
747b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        getActivity().invalidateOptionsMenu();
7488a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
74929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        mBinding = false;
7508a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
7518a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
752f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private boolean isAppDetailMode() {
753ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        return mCurrentApp != null;
754f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    }
755f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
756f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    /**
757ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey     * Update UID details panels to match {@link #mCurrentApp}, showing or
75855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey     * hiding them depending on {@link #isAppDetailMode()}.
759f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     */
760f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private void updateAppDetail() {
761d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        final Context context = getActivity();
762d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        final PackageManager pm = context.getPackageManager();
763d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        final LayoutInflater inflater = getActivity().getLayoutInflater();
764d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey
765f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        if (isAppDetailMode()) {
766f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppDetail.setVisibility(View.VISIBLE);
7679fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mCycleAdapter.setChangeVisible(false);
768f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        } else {
769f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppDetail.setVisibility(View.GONE);
7709fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mCycleAdapter.setChangeVisible(true);
771f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
772f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            // hide detail stats when not in detail mode
773f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mChart.bindDetailNetworkStats(null);
774f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            return;
775f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
776f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
777f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        // remove warning/limit sweeps while in detail mode
778f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        mChart.bindNetworkPolicy(null);
779f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
780d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        // show icon and all labels appearing under this app
78138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final int uid = mCurrentApp.key;
78238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final UidDetail detail = mUidDetailProvider.getUidDetail(uid, true);
783d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        mAppIcon.setImageDrawable(detail.icon);
784d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey
785d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        mAppTitles.removeAllViews();
786d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        if (detail.detailLabels != null) {
787d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            for (CharSequence label : detail.detailLabels) {
788d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey                mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, label));
789d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            }
790d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        } else {
791d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, detail.label));
792d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        }
793f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
794f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        // enable settings button when package provides it
79538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final String[] packageNames = pm.getPackagesForUid(uid);
796f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        if (packageNames != null && packageNames.length > 0) {
797f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
798f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
799f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
80038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            // Search for match across all packages
80138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            boolean matchFound = false;
80238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            for (String packageName : packageNames) {
80338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                mAppSettingsIntent.setPackage(packageName);
80438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                if (pm.resolveActivity(mAppSettingsIntent, 0) != null) {
80538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    matchFound = true;
80638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    break;
80738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                }
80838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            }
80938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey
810f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSettings.setEnabled(matchFound);
811d92e0419b10d378c1f480be7088c469e1d1dd5f8Jeff Sharkey            mAppSettings.setVisibility(View.VISIBLE);
812f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
813f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        } else {
814f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mAppSettingsIntent = null;
81534e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey            mAppSettings.setVisibility(View.GONE);
816f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
817f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
81855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        updateDetailData();
81955d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
82038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        if (UserHandle.isApp(uid) && !mPolicyManager.getRestrictBackground()
821313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                && isBandwidthControlEnabled() && hasReadyMobileRadio(context)) {
82255d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
8233038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey            setPreferenceSummary(mAppRestrictView,
8243038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                    getString(R.string.data_usage_app_restrict_background_summary));
82555d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
82655d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            mAppRestrictView.setVisibility(View.VISIBLE);
82755d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            mAppRestrict.setChecked(getAppRestrictBackground());
82855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
82955d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        } else {
83055d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            mAppRestrictView.setVisibility(View.GONE);
83155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        }
83255d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey    }
83355d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
8344c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    private void setPolicyWarningBytes(long warningBytes) {
8354c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        if (LOGD) Log.d(TAG, "setPolicyWarningBytes()");
836a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey        mPolicyEditor.setPolicyWarningBytes(mTemplate, warningBytes);
8374c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        updatePolicy(false);
8384c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    }
8394c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
8404c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    private void setPolicyLimitBytes(long limitBytes) {
8414c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        if (LOGD) Log.d(TAG, "setPolicyLimitBytes()");
842a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey        mPolicyEditor.setPolicyLimitBytes(mTemplate, limitBytes);
8434c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        updatePolicy(false);
8444c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    }
8454c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
84628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    /**
84728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey     * Local cache of value, used to work around delay when
84828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey     * {@link ConnectivityManager#setMobileDataEnabled(boolean)} is async.
84928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey     */
85028130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    private Boolean mMobileDataEnabled;
85128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
85228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    private boolean isMobileDataEnabled() {
85328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        if (mMobileDataEnabled != null) {
85428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            // TODO: deprecate and remove this once enabled flag is on policy
85528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            return mMobileDataEnabled;
85628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        } else {
85728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            return mConnService.getMobileDataEnabled();
85828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        }
85928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    }
86028130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
86128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    private void setMobileDataEnabled(boolean enabled) {
86228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        if (LOGD) Log.d(TAG, "setMobileDataEnabled()");
86328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        mConnService.setMobileDataEnabled(enabled);
86428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        mMobileDataEnabled = enabled;
86528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        updatePolicy(false);
86628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    }
86728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
86855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey    private boolean isNetworkPolicyModifiable(NetworkPolicy policy) {
86938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        return policy != null && isBandwidthControlEnabled() && mDataEnabled.isChecked()
87038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                && ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
8711ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey    }
8721ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey
8731ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey    private boolean isBandwidthControlEnabled() {
8741ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        try {
8751ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            return mNetworkService.isBandwidthControlEnabled();
8761ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        } catch (RemoteException e) {
8771ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            Log.w(TAG, "problem talking with INetworkManagementService: " + e);
8781ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            return false;
8791ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        }
8801ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey    }
8811ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey
8829fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private boolean getDataRoaming() {
8839fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        final ContentResolver resolver = getActivity().getContentResolver();
8845a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate        return Settings.Global.getInt(resolver, Settings.Global.DATA_ROAMING, 0) != 0;
8859fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
8869fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
8879fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private void setDataRoaming(boolean enabled) {
8889fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        // TODO: teach telephony DataConnectionTracker to watch and apply
8899fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        // updates when changed.
8909fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        final ContentResolver resolver = getActivity().getContentResolver();
8915a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate        Settings.Global.putInt(resolver, Settings.Global.DATA_ROAMING, enabled ? 1 : 0);
8929fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        mMenuDataRoaming.setChecked(enabled);
8939fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
8949fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
895313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    public void setRestrictBackground(boolean restrictBackground) {
896313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mPolicyManager.setRestrictBackground(restrictBackground);
897313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        mMenuRestrictBackground.setChecked(restrictBackground);
8989fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
8999fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
9009fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    private boolean getAppRestrictBackground() {
90138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final int uid = mCurrentApp.key;
90238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final int uidPolicy = mPolicyManager.getUidPolicy(uid);
9039fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
9049fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
9059fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
906f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private void setAppRestrictBackground(boolean restrictBackground) {
907d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
90838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        final int uid = mCurrentApp.key;
90938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        mPolicyManager.setUidPolicy(
91038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                uid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
911f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        mAppRestrict.setChecked(restrictBackground);
912f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    }
913f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
9148a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
91505cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey     * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
91605cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey     * current {@link #mTemplate}.
91705cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey     */
9184dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey    private void updatePolicy(boolean refreshCycle) {
919f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        if (isAppDetailMode()) {
920f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mNetworkSwitches.setVisibility(View.GONE);
921f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        } else {
922f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            mNetworkSwitches.setVisibility(View.VISIBLE);
923f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
924f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
92528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        // TODO: move enabled state directly into policy
92628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        if (TAB_MOBILE.equals(mCurrentTab)) {
92728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            mBinding = true;
92828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            mDataEnabled.setChecked(isMobileDataEnabled());
92928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            mBinding = false;
93028130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        }
93128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
93255d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
93355d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        if (isNetworkPolicyModifiable(policy)) {
9341ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            mDisableAtLimitView.setVisibility(View.VISIBLE);
9351ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
936d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            if (!isAppDetailMode()) {
937d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey                mChart.bindNetworkPolicy(policy);
938d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            }
93905cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
9401ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        } else {
9411ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            // controls are disabled; don't bind warning/limit sweeps
9421ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            mDisableAtLimitView.setVisibility(View.GONE);
9431ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey            mChart.bindNetworkPolicy(null);
9441ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey        }
94505cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
9464dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey        if (refreshCycle) {
9474dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey            // generate cycle list based on policy and available history
9484dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey            updateCycleList(policy);
9494dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey        }
95005cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    }
95105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
95205cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    /**
9538a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Rebuild {@link #mCycleAdapter} based on {@link NetworkPolicy#cycleDay}
9548a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * and available {@link NetworkStatsHistory} data. Always selects the newest
9558a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * item, updating the inspection range on {@link #mChart}.
9568a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
95705cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    private void updateCycleList(NetworkPolicy policy) {
958a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        // stash away currently selected cycle to try restoring below
959a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        final CycleItem previousItem = (CycleItem) mCycleSpinner.getSelectedItem();
9608a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        mCycleAdapter.clear();
961ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
9628a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        final Context context = mCycleSpinner.getContext();
963ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
964b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        long historyStart = Long.MAX_VALUE;
965b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        long historyEnd = Long.MIN_VALUE;
966b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (mChartData != null) {
967b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            historyStart = mChartData.network.getStart();
968b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            historyEnd = mChartData.network.getEnd();
969518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        }
970ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
971461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey        final long now = System.currentTimeMillis();
972461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey        if (historyStart == Long.MAX_VALUE) historyStart = now;
973461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey        if (historyEnd == Long.MIN_VALUE) historyEnd = now + 1;
974b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
975518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        boolean hasCycles = false;
97605cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey        if (policy != null) {
97705cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            // find the next cycle boundary
97805cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            long cycleEnd = computeNextCycleBoundary(historyEnd, policy);
97905cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
98005cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            // walk backwards, generating all valid cycle ranges
98105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            while (cycleEnd > historyStart) {
98205cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                final long cycleStart = computeLastCycleBoundary(cycleEnd, policy);
98305cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                Log.d(TAG, "generating cs=" + cycleStart + " to ce=" + cycleEnd + " waiting for hs="
98405cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                        + historyStart);
98505cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                mCycleAdapter.add(new CycleItem(context, cycleStart, cycleEnd));
98605cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey                cycleEnd = cycleStart;
987518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey                hasCycles = true;
98805cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            }
9898a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
99005cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey            // one last cycle entry to modify policy cycle day
99155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            mCycleAdapter.setChangePossible(isNetworkPolicyModifiable(policy));
992518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        }
9938a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
994518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        if (!hasCycles) {
99555d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            // no policy defined cycles; show entry for each four-week period
99655d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            long cycleEnd = historyEnd;
99755d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            while (cycleEnd > historyStart) {
99855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey                final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
99955d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey                mCycleAdapter.add(new CycleItem(context, cycleStart, cycleEnd));
100055d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey                cycleEnd = cycleStart;
100155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            }
100255d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
10039fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mCycleAdapter.setChangePossible(false);
1004ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1005ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
10068a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        // force pick the current cycle (first item)
100755d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        if (mCycleAdapter.getCount() > 0) {
1008a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final int position = mCycleAdapter.findNearestPosition(previousItem);
1009a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            mCycleSpinner.setSelection(position);
1010a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1011a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            // only force-update cycle when changed; skipping preserves any
1012a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            // user-defined inspection region.
1013a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final CycleItem selectedItem = mCycleAdapter.getItem(position);
1014a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            if (!Objects.equal(selectedItem, previousItem)) {
1015a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                mCycleListener.onItemSelected(mCycleSpinner, null, position, 0);
1016a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            } else {
1017a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                // but still kick off loader for detailed list
1018a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                updateDetailData();
1019a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            }
102055d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        } else {
102155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            updateDetailData();
102255d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        }
1023ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
1024ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
102529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private OnCheckedChangeListener mDataEnabledListener = new OnCheckedChangeListener() {
102676c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
102729d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
102829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            if (mBinding) return;
1029ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
103029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            final boolean dataEnabled = isChecked;
10319549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            final String currentTab = mCurrentTab;
10329549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            if (TAB_MOBILE.equals(currentTab)) {
103328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                if (dataEnabled) {
103428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    setMobileDataEnabled(true);
103528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                } else {
103628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    // disabling data; show confirmation dialog which eventually
103728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    // calls setMobileDataEnabled() once user confirms.
103828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    ConfirmDataDisableFragment.show(DataUsageSummary.this);
103928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                }
104029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey            }
10411ae43f922a68f38d5b82bd789cac16032d05fc11Jeff Sharkey
104228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            updatePolicy(false);
10438a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
10448a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
1045ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
104629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private View.OnClickListener mDisableAtLimitListener = new View.OnClickListener() {
104776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
10488a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onClick(View v) {
10498a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            final boolean disableAtLimit = !mDisableAtLimit.isChecked();
10504c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            if (disableAtLimit) {
10514c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                // enabling limit; show confirmation dialog which eventually
10524c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                // calls setPolicyLimitBytes() once user confirms.
10534c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                ConfirmLimitFragment.show(DataUsageSummary.this);
10544c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            } else {
10554c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                setPolicyLimitBytes(LIMIT_DISABLED);
10564c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            }
1057ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
10588a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
1059ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1060f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private View.OnClickListener mAppRestrictListener = new View.OnClickListener() {
106176c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1062f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public void onClick(View v) {
1063f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final boolean restrictBackground = !mAppRestrict.isChecked();
1064f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1065f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            if (restrictBackground) {
10663038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                // enabling restriction; show confirmation dialog which
10673038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                // eventually calls setRestrictBackground() once user
10683038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                // confirms.
10693038c52de43b73d02b501e0ea8d396bedbb5600eJeff Sharkey                ConfirmAppRestrictFragment.show(DataUsageSummary.this);
1070f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            } else {
1071f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                setAppRestrictBackground(false);
1072f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            }
1073f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1074f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    };
1075f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1076f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    private OnClickListener mAppSettingsListener = new OnClickListener() {
107776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1078f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public void onClick(View v) {
1079d92e0419b10d378c1f480be7088c469e1d1dd5f8Jeff Sharkey            if (!isAdded()) return;
1080d92e0419b10d378c1f480be7088c469e1d1dd5f8Jeff Sharkey
1081f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            // TODO: target torwards entire UID instead of just first package
1082f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            startActivity(mAppSettingsIntent);
1083f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1084f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    };
1085f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
10868a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private OnItemClickListener mListListener = new OnItemClickListener() {
108776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
10888a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
108955d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            final Context context = view.getContext();
1090ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            final AppItem app = (AppItem) parent.getItemAtPosition(position);
10913da415f19b2b114a94580e8f7c149a23485b0c27Jeff Sharkey
10923da415f19b2b114a94580e8f7c149a23485b0c27Jeff Sharkey            // TODO: sigh, remove this hack once we understand 6450986
10933da415f19b2b114a94580e8f7c149a23485b0c27Jeff Sharkey            if (mUidDetailProvider == null || app == null) return;
10943da415f19b2b114a94580e8f7c149a23485b0c27Jeff Sharkey
109538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final UidDetail detail = mUidDetailProvider.getUidDetail(app.key, true);
1096ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            AppDetailsFragment.show(DataUsageSummary.this, app, detail.label);
1097ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
10988a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
1099ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
11008a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
110176c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
11028a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
11038a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            final CycleItem cycle = (CycleItem) parent.getItemAtPosition(position);
11048a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            if (cycle instanceof CycleChangeItem) {
11054c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                // show cycle editor; will eventually call setPolicyCycleDay()
11064c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                // when user finishes editing.
11074c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                CycleEditorFragment.show(DataUsageSummary.this);
11084c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
11094c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                // reset spinner to something other than "change cycle..."
11104c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                mCycleSpinner.setSelection(0);
11118a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
11128a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            } else {
11138e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey                if (LOGD) {
11148e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey                    Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
11158e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey                            + cycle.end + "]");
11168e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey                }
11178a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
11188a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                // update chart to show selected cycle, and update detail data
11198a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                // to match updated sweep bounds.
1120d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey                mChart.setVisibleRange(cycle.start, cycle.end);
11218a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
11228a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                updateDetailData();
11238a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            }
1124ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1125ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
112676c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
11278a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onNothingSelected(AdapterView<?> parent) {
11288a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            // ignored
1129ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
11308a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    };
11318a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
11328a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
1133f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * Update details based on {@link #mChart} inspection range depending on
1134f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * current mode. In network mode, updates {@link #mAdapter} with sorted list
1135f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * of applications data usage, and when {@link #isAppDetailMode()} update
1136f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * app details.
11378a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
11388a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private void updateDetailData() {
11398a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        if (LOGD) Log.d(TAG, "updateDetailData()");
1140ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1141518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        final long start = mChart.getInspectStart();
1142518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        final long end = mChart.getInspectEnd();
1143d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        final long now = System.currentTimeMillis();
1144d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1145d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        final Context context = getActivity();
1146518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey
114754d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey        NetworkStatsHistory.Entry entry = null;
1148b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (isAppDetailMode() && mChartData != null && mChartData.detail != null) {
114954d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            // bind foreground/background to piechart and labels
1150b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            entry = mChartData.detailDefault.getValues(start, end, now, entry);
115154d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            final long defaultBytes = entry.rxBytes + entry.txBytes;
1152b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            entry = mChartData.detailForeground.getValues(start, end, now, entry);
115354d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            final long foregroundBytes = entry.rxBytes + entry.txBytes;
115454d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
115554d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart.setOriginAngle(175);
115654d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
115754d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart.removeAllSlices();
115854d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart.addSlice(foregroundBytes, Color.parseColor("#d88d3a"));
115954d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart.addSlice(defaultBytes, Color.parseColor("#666666"));
116054d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
116154d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppPieChart.generatePath();
116254d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
116354d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppBackground.setText(Formatter.formatFileSize(context, defaultBytes));
116454d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            mAppForeground.setText(Formatter.formatFileSize(context, foregroundBytes));
116554d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
116654d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            // and finally leave with summary data for label below
1167b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            entry = mChartData.detail.getValues(start, end, now, null);
1168f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1169398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            getLoaderManager().destroyLoader(LOADER_SUMMARY);
1170398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey
1171398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        } else {
1172b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (mChartData != null) {
1173b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                entry = mChartData.network.getValues(start, end, now, null);
1174b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            }
1175d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1176398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            // kick off loader for detailed stats
1177398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            getLoaderManager().restartLoader(LOADER_SUMMARY,
1178b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryCallbacks);
1179f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1180d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1181d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
1182d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
1183e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey        final String rangePhrase = formatDateRange(context, start, end);
1184d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1185e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        final int summaryRes;
1186e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        if (TAB_MOBILE.equals(mCurrentTab) || TAB_3G.equals(mCurrentApp)
1187e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                || TAB_4G.equals(mCurrentApp)) {
1188e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            summaryRes = R.string.data_usage_total_during_range_mobile;
1189e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        } else {
1190e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            summaryRes = R.string.data_usage_total_during_range;
1191e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        }
1192e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey
1193e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        mUsageSummary.setText(getString(summaryRes, totalPhrase, rangePhrase));
119492811829b3658288208470b386cf32b12e3b89eeJeff Sharkey
119592811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        // initial layout is finished above, ensure we have transitions
119692811829b3658288208470b386cf32b12e3b89eeJeff Sharkey        ensureLayoutTransitions();
1197398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey    }
1198f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1199b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
1200b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            ChartData>() {
120176c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1202b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
120308ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey            return new ChartDataLoader(getActivity(), mStatsSession, args);
1204b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
1205b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
120676c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1207b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
1208b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChartData = data;
1209b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChart.bindNetworkStats(mChartData.network);
1210b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChart.bindDetailNetworkStats(mChartData.detail);
1211b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1212b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            // calcuate policy cycles based on available data
1213b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            updatePolicy(true);
1214b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            updateAppDetail();
1215b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1216b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            // force scroll to top of body when showing detail
1217b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (mChartData.detail != null) {
1218b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                mListView.smoothScrollToPosition(0);
1219b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            }
1220b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
1221b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
122276c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1223b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        public void onLoaderReset(Loader<ChartData> loader) {
1224b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChartData = null;
1225b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChart.bindNetworkStats(null);
1226b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mChart.bindDetailNetworkStats(null);
1227b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
1228b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    };
1229b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1230b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private final LoaderCallbacks<NetworkStats> mSummaryCallbacks = new LoaderCallbacks<
1231398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey            NetworkStats>() {
123276c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1233398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
123408ce99e224145759904bbd6ae36e0b2bf4b0e4e6Jeff Sharkey            return new SummaryForAllUidLoader(getActivity(), mStatsSession, args);
1235398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        }
1236aa5260e40a162c8990830da7648f0c850350360cJeff Sharkey
123776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1238398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
123938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final int[] restrictedUids = mPolicyManager.getUidsWithPolicy(
1240e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                    POLICY_REJECT_METERED_BACKGROUND);
124138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            mAdapter.bindStats(data, restrictedUids);
1242e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey            updateEmptyVisible();
1243398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        }
1244398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey
124576c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1246398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        public void onLoaderReset(Loader<NetworkStats> loader) {
1247e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            mAdapter.bindStats(null, new int[0]);
1248e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey            updateEmptyVisible();
1249e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey        }
1250e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey
1251e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey        private void updateEmptyVisible() {
1252e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey            final boolean isEmpty = mAdapter.isEmpty() && !isAppDetailMode();
1253e2afc0f283f58ce60c107643978bfff25ec5d5c1Jeff Sharkey            mEmpty.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
1254398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey        }
1255398b18fca74ec45b9293bf1e1c39ca073018cb27Jeff Sharkey    };
12568a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
125776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey    @Deprecated
1258a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey    private boolean isMobilePolicySplit() {
12599549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        final Context context = getActivity();
1260313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (hasReadyMobileRadio(context)) {
1261313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            final TelephonyManager tele = TelephonyManager.from(context);
1262313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            return mPolicyEditor.isMobilePolicySplit(getActiveSubscriberId(context));
12639549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        } else {
12649549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return false;
12659549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
1266a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey    }
1267a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey
126876c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey    @Deprecated
1269a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey    private void setMobilePolicySplit(boolean split) {
1270313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final Context context = getActivity();
1271313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (hasReadyMobileRadio(context)) {
1272313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            final TelephonyManager tele = TelephonyManager.from(context);
1273313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            mPolicyEditor.setMobilePolicySplit(getActiveSubscriberId(context), split);
1274313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        }
1275a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey    }
1276a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey
127705cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    private static String getActiveSubscriberId(Context context) {
1278313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
1279313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final String actualSubscriberId = tele.getSubscriberId();
1280f3871fb2b232cd22469ccc66415f82de4995894eJeff Sharkey        return SystemProperties.get(TEST_SUBSCRIBER_PROP, actualSubscriberId);
128105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey    }
128205cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey
12838a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    private DataUsageChartListener mChartListener = new DataUsageChartListener() {
128476c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
12858a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public void onInspectRangeChanged() {
12868a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
12878a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            updateDetailData();
1288ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1289ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
129076c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
129105cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey        public void onWarningChanged() {
12924c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            setPolicyWarningBytes(mChart.getWarningBytes());
129305cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey        }
12948a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
129576c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
129605cc0cc4a620009a9ec7bdcc2ccb3878f59c8697Jeff Sharkey        public void onLimitChanged() {
12974c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            setPolicyLimitBytes(mChart.getLimitBytes());
12988a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
12998a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
130076c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1301a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public void requestWarningEdit() {
1302a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            WarningEditorFragment.show(DataUsageSummary.this);
1303a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1304a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
130576c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1306a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public void requestLimitEdit() {
1307a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            LimitEditorFragment.show(DataUsageSummary.this);
1308a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1309a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    };
13108a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
13118a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
13128a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * List item that reflects a specific data usage cycle.
13138a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
1314a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    public static class CycleItem implements Comparable<CycleItem> {
13158a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public CharSequence label;
13168a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public long start;
13178a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public long end;
13188a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
13198a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        CycleItem(CharSequence label) {
13208a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            this.label = label;
13218a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
13228a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
13238a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public CycleItem(Context context, long start, long end) {
1324e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey            this.label = formatDateRange(context, start, end);
13258a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            this.start = start;
13268a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            this.end = end;
13278a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
13288a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
13298a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        @Override
13308a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public String toString() {
13318a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            return label.toString();
13328a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
1333a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1334a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        @Override
1335a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public boolean equals(Object o) {
1336a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            if (o instanceof CycleItem) {
1337a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                final CycleItem another = (CycleItem) o;
1338a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                return start == another.start && end == another.end;
1339a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            }
1340a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return false;
1341a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1342a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
134376c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey        @Override
1344a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public int compareTo(CycleItem another) {
1345a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return Long.compare(start, another.start);
1346a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
13478a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
13488a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
1349d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private static final StringBuilder sBuilder = new StringBuilder(50);
1350d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    private static final java.util.Formatter sFormatter = new java.util.Formatter(
1351d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            sBuilder, Locale.getDefault());
1352d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1353e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey    public static String formatDateRange(Context context, long start, long end) {
1354d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        final int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
1355d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
1356d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        synchronized (sBuilder) {
1357d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey            sBuilder.setLength(0);
1358e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey            return DateUtils.formatDateRange(context, sFormatter, start, end, flags, null)
1359e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey                    .toString();
1360d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey        }
1361d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey    }
1362d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey
13638a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
13648a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Special-case data usage cycle that triggers dialog to change
13658a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * {@link NetworkPolicy#cycleDay}.
13668a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
13678a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public static class CycleChangeItem extends CycleItem {
13688a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public CycleChangeItem(Context context) {
13698a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            super(context.getString(R.string.data_usage_change_cycle));
13708a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
1371ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
1372ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
13738a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public static class CycleAdapter extends ArrayAdapter<CycleItem> {
13749fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        private boolean mChangePossible = false;
13759fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        private boolean mChangeVisible = false;
13769fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
13779fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        private final CycleChangeItem mChangeItem;
13789fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
13798a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public CycleAdapter(Context context) {
13808a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            super(context, android.R.layout.simple_spinner_item);
13818a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
13829fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mChangeItem = new CycleChangeItem(context);
13839fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
13849fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
13859fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public void setChangePossible(boolean possible) {
13869fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mChangePossible = possible;
13879fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            updateChange();
13889fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
13899fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
13909fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public void setChangeVisible(boolean visible) {
13919fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            mChangeVisible = visible;
13929fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            updateChange();
13939fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
13949fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
13959fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        private void updateChange() {
13969fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            remove(mChangeItem);
13979fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            if (mChangePossible && mChangeVisible) {
13989fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                add(mChangeItem);
13999fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            }
14008a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        }
1401a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1402a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        /**
1403a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey         * Find position of {@link CycleItem} in this adapter which is nearest
1404a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey         * the given {@link CycleItem}.
1405a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey         */
1406a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public int findNearestPosition(CycleItem target) {
1407a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            if (target != null) {
1408a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                final int count = getCount();
1409a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                for (int i = count - 1; i >= 0; i--) {
1410a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    final CycleItem item = getItem(i);
1411a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    if (item instanceof CycleChangeItem) {
1412a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        continue;
1413a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    } else if (item.compareTo(target) >= 0) {
1414a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        return i;
1415a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    }
1416a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                }
1417a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            }
1418a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return 0;
1419a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
14208a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    }
1421ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
1422ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey    public static class AppItem implements Comparable<AppItem>, Parcelable {
142338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        public final int key;
1424e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey        public boolean restricted;
1425ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public SparseBooleanArray uids = new SparseBooleanArray();
14264dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey        public long total;
14274dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey
142838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        public AppItem(int key) {
142938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            this.key = key;
1430ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        }
1431ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey
1432ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public AppItem(Parcel parcel) {
143338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            key = parcel.readInt();
1434ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            uids = parcel.readSparseBooleanArray();
1435ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            total = parcel.readLong();
143655d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        }
143755d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
143855d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        public void addUid(int uid) {
1439ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            uids.put(uid, true);
144055d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey        }
144155d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey
1442ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        @Override
1443ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public void writeToParcel(Parcel dest, int flags) {
144438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            dest.writeInt(key);
1445ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            dest.writeSparseBooleanArray(uids);
1446ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            dest.writeLong(total);
1447ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        }
1448ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey
1449ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        @Override
1450ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public int describeContents() {
1451ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            return 0;
1452ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        }
1453ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey
1454ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        @Override
1455ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public int compareTo(AppItem another) {
14564dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey            return Long.compare(another.total, total);
14574dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey        }
1458ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey
1459ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public static final Creator<AppItem> CREATOR = new Creator<AppItem>() {
1460ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            @Override
1461ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            public AppItem createFromParcel(Parcel in) {
1462ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey                return new AppItem(in);
1463ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            }
1464ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey
1465ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            @Override
1466ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            public AppItem[] newArray(int size) {
1467ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey                return new AppItem[size];
1468ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            }
1469ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        };
14704dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey    }
14714dfa66001d20d1b461ef15f94887aa050d9295cfJeff Sharkey
14728a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    /**
14738a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     * Adapter of applications, sorted by total usage descending.
14748a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey     */
14758a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey    public static class DataUsageAdapter extends BaseAdapter {
1476b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        private final UidDetailProvider mProvider;
1477b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        private final int mInsetSide;
1478b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1479ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        private ArrayList<AppItem> mItems = Lists.newArrayList();
14802412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey        private long mLargest;
14818a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
1482b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        public DataUsageAdapter(UidDetailProvider provider, int insetSide) {
1483b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mProvider = checkNotNull(provider);
1484b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mInsetSide = insetSide;
1485b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
1486b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1487f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        /**
1488f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey         * Bind the given {@link NetworkStats}, or {@code null} to clear list.
1489f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey         */
149038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        public void bindStats(NetworkStats stats, int[] restrictedUids) {
14918a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            mItems.clear();
14928a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
149338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final int currentUserId = ActivityManager.getCurrentUser();
149438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
149554d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
149654d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            NetworkStats.Entry entry = null;
149754d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            final int size = stats != null ? stats.size() : 0;
149854d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey            for (int i = 0; i < size; i++) {
149954d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey                entry = stats.getValues(i, entry);
150054d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey
150138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                // Decide how to collapse items together
150238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                final int uid = entry.uid;
150338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                final int collapseKey;
150438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                if (UserHandle.isApp(uid)) {
150538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    if (UserHandle.getUserId(uid) == currentUserId) {
150638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                        collapseKey = uid;
150738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    } else {
150838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                        collapseKey = UidDetailProvider.buildKeyForUser(UserHandle.getUserId(uid));
1509518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey                    }
151038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                } else if (uid == UID_REMOVED || uid == UID_TETHERING) {
151138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    collapseKey = uid;
151254d0af57fd2dca14f0c7c34a48942aa6ecdc3f06Jeff Sharkey                } else {
151338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    collapseKey = android.os.Process.SYSTEM_UID;
1514f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                }
151538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey
151638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                AppItem item = knownItems.get(collapseKey);
151738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                if (item == null) {
151838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    item = new AppItem(collapseKey);
151938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    mItems.add(item);
152038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    knownItems.put(item.key, item);
152138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                }
152238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                item.addUid(uid);
152338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                item.total += entry.rxBytes + entry.txBytes;
15248a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            }
15258a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
152638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            for (int uid : restrictedUids) {
152738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                // Only splice in restricted state for current user
152838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                if (UserHandle.getUserId(uid) != currentUserId) continue;
152938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey
153038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                AppItem item = knownItems.get(uid);
1531e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                if (item == null) {
153238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    item = new AppItem(uid);
1533e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                    item.total = -1;
1534e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                    mItems.add(item);
153538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                    knownItems.put(item.key, item);
1536e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                }
1537e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                item.restricted = true;
1538e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            }
1539e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey
15408a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            Collections.sort(mItems);
15412412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey            mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0;
15428a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            notifyDataSetChanged();
1543ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1544ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
15458a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        @Override
15468a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public int getCount() {
15478a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            return mItems.size();
1548ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1549ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
15508a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        @Override
15518a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public Object getItem(int position) {
15528a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            return mItems.get(position);
1553ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1554ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
15558a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        @Override
15568a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public long getItemId(int position) {
155738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            return mItems.get(position).key;
1558ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1559ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
15608a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        @Override
15618a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
15628a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            if (convertView == null) {
15638a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext()).inflate(
15645d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey                        R.layout.data_usage_item, parent, false);
1565b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1566b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                if (mInsetSide > 0) {
1567b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    convertView.setPadding(mInsetSide, 0, mInsetSide, 0);
1568b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                }
1569ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey            }
15708a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
15718a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            final Context context = parent.getContext();
15728a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
157328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
15742412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey            final ProgressBar progress = (ProgressBar) convertView.findViewById(
15752412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey                    android.R.id.progress);
15768a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
1577b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            // kick off async load of app details
1578ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            final AppItem item = mItems.get(position);
1579b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            UidDetailTask.bindView(mProvider, item, convertView);
1580d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey
1581e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            if (item.restricted && item.total <= 0) {
1582e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                text1.setText(R.string.data_usage_app_restricted);
1583e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                progress.setVisibility(View.GONE);
1584e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            } else {
1585e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                text1.setText(Formatter.formatFileSize(context, item.total));
1586e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                progress.setVisibility(View.VISIBLE);
1587e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey            }
15882412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey
15892412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey            final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
15902412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey            progress.setProgress(percentTotal);
15918a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey
15928a50364a71e7c261b54840210f8bacff5abecb34Jeff Sharkey            return convertView;
1593ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey        }
1594ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey    }
1595ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
15964c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    /**
1597f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * Empty {@link Fragment} that controls display of UID details in
1598f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * {@link DataUsageSummary}.
1599f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     */
1600f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    public static class AppDetailsFragment extends Fragment {
1601ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        private static final String EXTRA_APP = "app";
1602f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1603ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        public static void show(DataUsageSummary parent, AppItem app, CharSequence label) {
1604461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1605461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
1606f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final Bundle args = new Bundle();
1607ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            args.putParcelable(EXTRA_APP, app);
1608f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1609f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final AppDetailsFragment fragment = new AppDetailsFragment();
1610f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            fragment.setArguments(args);
1611f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            fragment.setTargetFragment(parent, 0);
1612f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
1613f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            ft.add(fragment, TAG_APP_DETAILS);
1614f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            ft.addToBackStack(TAG_APP_DETAILS);
161555d18a57e45e11f657346cbaa7fd454f92775229Jeff Sharkey            ft.setBreadCrumbTitle(label);
16163235ddb7aaeab63b837ea1e4f9ebfd81447fd120Jeff Sharkey            ft.commitAllowingStateLoss();
1617f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1618f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1619f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        @Override
1620f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public void onStart() {
1621f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            super.onStart();
1622f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
1623ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            target.mCurrentApp = getArguments().getParcelable(EXTRA_APP);
1624f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            target.updateBody();
1625f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1626f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1627f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        @Override
1628f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public void onStop() {
1629f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            super.onStop();
1630f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
1631ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey            target.mCurrentApp = null;
1632f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            target.updateBody();
1633f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1634f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    }
1635f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1636f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    /**
16374c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey     * Dialog to request user confirmation before setting
16384c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey     * {@link NetworkPolicy#limitBytes}.
16394c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey     */
16404c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    public static class ConfirmLimitFragment extends DialogFragment {
1641131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey        private static final String EXTRA_MESSAGE = "message";
16422412b0f2489d5fde811d802b39a0a00d861b5ddfJeff Sharkey        private static final String EXTRA_LIMIT_BYTES = "limitBytes";
16434c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16444c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        public static void show(DataUsageSummary parent) {
1645461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1646131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey
1647461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            final Resources res = parent.getResources();
1648131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            final CharSequence message;
164934e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey            final long minLimitBytes = (long) (
165034e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey                    parent.mPolicyEditor.getPolicy(parent.mTemplate).warningBytes * 1.2f);
1651131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            final long limitBytes;
16524c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16534c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            // TODO: customize default limits based on network template
16549549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            final String currentTab = parent.mCurrentTab;
16559549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            if (TAB_3G.equals(currentTab)) {
1656e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                message = res.getString(R.string.data_usage_limit_dialog_mobile);
165734e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey                limitBytes = Math.max(5 * GB_IN_BYTES, minLimitBytes);
16589549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            } else if (TAB_4G.equals(currentTab)) {
1659e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                message = res.getString(R.string.data_usage_limit_dialog_mobile);
166034e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey                limitBytes = Math.max(5 * GB_IN_BYTES, minLimitBytes);
16619549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            } else if (TAB_MOBILE.equals(currentTab)) {
1662e557c3349ee781162434ec4746fb71d45606f97cJeff Sharkey                message = res.getString(R.string.data_usage_limit_dialog_mobile);
166334e964dcff0f669af4c911a8c179e1982d84bc14Jeff Sharkey                limitBytes = Math.max(5 * GB_IN_BYTES, minLimitBytes);
1664131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            } else {
1665131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey                throw new IllegalArgumentException("unknown current tab: " + currentTab);
16664c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            }
16674c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
1668131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            final Bundle args = new Bundle();
1669131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            args.putCharSequence(EXTRA_MESSAGE, message);
1670131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            args.putLong(EXTRA_LIMIT_BYTES, limitBytes);
1671131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey
16724c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final ConfirmLimitFragment dialog = new ConfirmLimitFragment();
16734c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.setArguments(args);
16744c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.setTargetFragment(parent, 0);
16754c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_LIMIT);
16764c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        }
16774c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16784c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        @Override
16794c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
16804c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final Context context = getActivity();
16814c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
1682131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            final CharSequence message = getArguments().getCharSequence(EXTRA_MESSAGE);
16834c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final long limitBytes = getArguments().getLong(EXTRA_LIMIT_BYTES);
16844c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16854c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
16864c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            builder.setTitle(R.string.data_usage_limit_dialog_title);
1687131f9d6e0f82017ceca8777bff00f7b65bcfd3a9Jeff Sharkey            builder.setMessage(message);
16884c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16894c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
169076c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                @Override
16914c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                public void onClick(DialogInterface dialog, int which) {
16924c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                    final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
16934c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                    if (target != null) {
16944c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                        target.setPolicyLimitBytes(limitBytes);
16954c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                    }
16964c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                }
16974c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            });
16984c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
16994c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            return builder.create();
17004c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        }
17014c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    }
17024c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17034c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    /**
17044c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey     * Dialog to edit {@link NetworkPolicy#cycleDay}.
17054c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey     */
17064c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    public static class CycleEditorFragment extends DialogFragment {
1707a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        private static final String EXTRA_TEMPLATE = "template";
17084c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17094c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        public static void show(DataUsageSummary parent) {
1710461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1711461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
17124c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final Bundle args = new Bundle();
1713a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate);
17144c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17154c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final CycleEditorFragment dialog = new CycleEditorFragment();
17164c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.setArguments(args);
17174c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.setTargetFragment(parent, 0);
17184c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CYCLE_EDITOR);
17194c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        }
17204c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17214c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        @Override
17224c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
17234c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final Context context = getActivity();
1724a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
1725a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkPolicyEditor editor = target.mPolicyEditor;
17264c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17274c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
17284c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
17294c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17304c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final View view = dialogInflater.inflate(R.layout.data_usage_cycle_editor, null, false);
17314c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            final NumberPicker cycleDayPicker = (NumberPicker) view.findViewById(R.id.cycle_day);
17324c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
1733a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
1734a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final int cycleDay = editor.getPolicyCycleDay(template);
17354c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17364c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            cycleDayPicker.setMinValue(1);
17374c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            cycleDayPicker.setMaxValue(31);
1738a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            cycleDayPicker.setValue(cycleDay);
17394c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            cycleDayPicker.setWrapSelectorWheel(true);
17404c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17414c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            builder.setTitle(R.string.data_usage_cycle_editor_title);
17424c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            builder.setView(view);
17434c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
17444c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            builder.setPositiveButton(R.string.data_usage_cycle_editor_positive,
17454c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                    new DialogInterface.OnClickListener() {
174676c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                        @Override
17474c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                        public void onClick(DialogInterface dialog, int which) {
17484c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                            final int cycleDay = cycleDayPicker.getValue();
1749e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey                            final String cycleTimezone = new Time().timezone;
1750e5223a0577727b7a524b7e74ad4f95d132cdc2f0Jeff Sharkey                            editor.setPolicyCycleDay(template, cycleDay, cycleTimezone);
1751a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            target.updatePolicy(true);
1752a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        }
1753a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    });
1754a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1755a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return builder.create();
1756a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1757a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    }
1758a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1759a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    /**
1760a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * Dialog to edit {@link NetworkPolicy#warningBytes}.
1761a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     */
1762a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    public static class WarningEditorFragment extends DialogFragment {
1763a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        private static final String EXTRA_TEMPLATE = "template";
1764a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1765a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public static void show(DataUsageSummary parent) {
1766461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1767461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
1768a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final Bundle args = new Bundle();
1769a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate);
1770a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1771a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final WarningEditorFragment dialog = new WarningEditorFragment();
1772a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.setArguments(args);
1773a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.setTargetFragment(parent, 0);
1774a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_WARNING_EDITOR);
1775a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1776a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1777a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        @Override
1778a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
1779a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final Context context = getActivity();
1780a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
1781a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkPolicyEditor editor = target.mPolicyEditor;
1782a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1783a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
1784a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
1785a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1786a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final View view = dialogInflater.inflate(R.layout.data_usage_bytes_editor, null, false);
1787a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NumberPicker bytesPicker = (NumberPicker) view.findViewById(R.id.bytes);
1788a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1789a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
1790a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final long warningBytes = editor.getPolicyWarningBytes(template);
1791a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final long limitBytes = editor.getPolicyLimitBytes(template);
1792a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1793a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setMinValue(0);
1794a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            if (limitBytes != LIMIT_DISABLED) {
1795a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                bytesPicker.setMaxValue((int) (limitBytes / MB_IN_BYTES) - 1);
1796a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            } else {
1797a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                bytesPicker.setMaxValue(Integer.MAX_VALUE);
1798a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            }
1799a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setValue((int) (warningBytes / MB_IN_BYTES));
1800a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setWrapSelectorWheel(false);
1801a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1802a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setTitle(R.string.data_usage_warning_editor_title);
1803a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setView(view);
1804a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1805a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setPositiveButton(R.string.data_usage_cycle_editor_positive,
1806a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    new DialogInterface.OnClickListener() {
180776c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                        @Override
1808a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        public void onClick(DialogInterface dialog, int which) {
1809a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            // clear focus to finish pending text edits
1810a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            bytesPicker.clearFocus();
1811a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1812a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            final long bytes = bytesPicker.getValue() * MB_IN_BYTES;
1813a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            editor.setPolicyWarningBytes(template, bytes);
1814a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            target.updatePolicy(false);
18154c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                        }
18164c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey                    });
18174c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey
18184c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey            return builder.create();
18194c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey        }
18204c72ae5e3d172f883e5957509c5c7bf92c6cc8d4Jeff Sharkey    }
1821ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey
18228e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey    /**
1823a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * Dialog to edit {@link NetworkPolicy#limitBytes}.
1824a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     */
1825a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    public static class LimitEditorFragment extends DialogFragment {
1826a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        private static final String EXTRA_TEMPLATE = "template";
1827a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1828a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public static void show(DataUsageSummary parent) {
1829461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1830461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
1831a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final Bundle args = new Bundle();
1832a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate);
1833a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1834a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final LimitEditorFragment dialog = new LimitEditorFragment();
1835a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.setArguments(args);
1836a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.setTargetFragment(parent, 0);
1837a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_LIMIT_EDITOR);
1838a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1839a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1840a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        @Override
1841a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
1842a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final Context context = getActivity();
1843a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
1844a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkPolicyEditor editor = target.mPolicyEditor;
1845a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1846a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
1847a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
1848a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1849a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final View view = dialogInflater.inflate(R.layout.data_usage_bytes_editor, null, false);
1850a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NumberPicker bytesPicker = (NumberPicker) view.findViewById(R.id.bytes);
1851a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1852a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
1853a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final long warningBytes = editor.getPolicyWarningBytes(template);
1854a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final long limitBytes = editor.getPolicyLimitBytes(template);
1855a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1856a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setMaxValue(Integer.MAX_VALUE);
1857f9237f6e3ca32afdb79d4bcc8f13af0cd9309e84Shuhrat Dehkanov            if (warningBytes != WARNING_DISABLED && limitBytes > 0) {
1858a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                bytesPicker.setMinValue((int) (warningBytes / MB_IN_BYTES) + 1);
1859a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            } else {
1860a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                bytesPicker.setMinValue(0);
1861a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            }
1862a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setValue((int) (limitBytes / MB_IN_BYTES));
1863a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            bytesPicker.setWrapSelectorWheel(false);
1864a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1865a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setTitle(R.string.data_usage_limit_editor_title);
1866a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setView(view);
1867a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1868a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setPositiveButton(R.string.data_usage_cycle_editor_positive,
1869a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    new DialogInterface.OnClickListener() {
187076c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                        @Override
1871a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        public void onClick(DialogInterface dialog, int which) {
1872a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            // clear focus to finish pending text edits
1873a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            bytesPicker.clearFocus();
1874a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1875a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            final long bytes = bytesPicker.getValue() * MB_IN_BYTES;
1876a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            editor.setPolicyLimitBytes(template, bytes);
1877a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                            target.updatePolicy(false);
1878a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                        }
1879a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey                    });
1880a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
1881a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return builder.create();
1882a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
1883a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    }
1884a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    /**
188528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey     * Dialog to request user confirmation before disabling data.
188628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey     */
188728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    public static class ConfirmDataDisableFragment extends DialogFragment {
188828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        public static void show(DataUsageSummary parent) {
1889461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1890461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
189128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            final ConfirmDataDisableFragment dialog = new ConfirmDataDisableFragment();
189228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            dialog.setTargetFragment(parent, 0);
189328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_DISABLE);
189428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        }
189528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
189628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        @Override
189728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
189828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            final Context context = getActivity();
189928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
190028130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
190128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            builder.setMessage(R.string.data_usage_disable_mobile);
190228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
190328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
190476c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                @Override
190528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                public void onClick(DialogInterface dialog, int which) {
190628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
190728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    if (target != null) {
190828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                        // TODO: extend to modify policy enabled flag.
190928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                        target.setMobileDataEnabled(false);
191028130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                    }
191128130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey                }
191228130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            });
191328130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            builder.setNegativeButton(android.R.string.cancel, null);
191428130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
191528130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            return builder.create();
191628130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey        }
191728130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    }
191828130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey
191928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey    /**
1920f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * Dialog to request user confirmation before setting
19215a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate     * {@link android.provider.Settings.Global#DATA_ROAMING}.
19229fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey     */
19239fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    public static class ConfirmDataRoamingFragment extends DialogFragment {
19249fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public static void show(DataUsageSummary parent) {
1925461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1926461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
19279fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final ConfirmDataRoamingFragment dialog = new ConfirmDataRoamingFragment();
19289fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            dialog.setTargetFragment(parent, 0);
192928130d96385d7d7b17992b45fb5d124836d85880Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_ROAMING);
19309fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
19319fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19329fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        @Override
19339fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
19349fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final Context context = getActivity();
19359fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19369fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
19379fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setTitle(R.string.roaming_reenable_title);
19389627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            if (Utils.hasMultipleUsers(context)) {
19399627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani                builder.setMessage(R.string.roaming_warning_multiuser);
19409627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            } else {
19419627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani                builder.setMessage(R.string.roaming_warning);
19429627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            }
19439fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19449fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
194576c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                @Override
19469fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                public void onClick(DialogInterface dialog, int which) {
19479fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
19489fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    if (target != null) {
19499fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                        target.setDataRoaming(true);
19509fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    }
19519fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                }
19529fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            });
19539fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setNegativeButton(android.R.string.cancel, null);
19549fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19559fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            return builder.create();
19569fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
19579fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
19589fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19599fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    /**
19609fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey     * Dialog to request user confirmation before setting
1961d360e5efaaf4ea5f487a84787210a6c5d26337a8Jeff Sharkey     * {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
1962f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     */
1963f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    public static class ConfirmRestrictFragment extends DialogFragment {
1964f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public static void show(DataUsageSummary parent) {
1965461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
1966461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
1967f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment();
1968f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            dialog.setTargetFragment(parent, 0);
1969f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT);
1970f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
1971f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1972f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        @Override
1973f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
1974f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final Context context = getActivity();
1975f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
1976f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
19779fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setTitle(R.string.data_usage_restrict_background_title);
19789627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            if (Utils.hasMultipleUsers(context)) {
19799627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani                builder.setMessage(R.string.data_usage_restrict_background_multiuser);
19809627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            } else {
19819627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani                builder.setMessage(R.string.data_usage_restrict_background);
19829627a8ea151c1f27e5e9f34592c7b34fea3101c3Amith Yamasani            }
19839fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19849fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
198576c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                @Override
19869fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                public void onClick(DialogInterface dialog, int which) {
19879fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
19889fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    if (target != null) {
19899fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                        target.setRestrictBackground(true);
19909fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                    }
19919fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey                }
19929fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            });
19939fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            builder.setNegativeButton(android.R.string.cancel, null);
19949fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19959fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            return builder.create();
19969fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
19979fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    }
19989fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
19999fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    /**
2000a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * Dialog to inform user that {@link #POLICY_REJECT_METERED_BACKGROUND}
2001a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * change has been denied, usually based on
2002a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * {@link DataUsageSummary#hasLimitedNetworks()}.
2003a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     */
2004a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    public static class DeniedRestrictFragment extends DialogFragment {
2005a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public static void show(DataUsageSummary parent) {
2006461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
2007461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
2008a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final DeniedRestrictFragment dialog = new DeniedRestrictFragment();
2009a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.setTargetFragment(parent, 0);
2010a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_DENIED_RESTRICT);
2011a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
2012a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2013a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        @Override
2014a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
2015a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final Context context = getActivity();
2016a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2017a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
2018a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setTitle(R.string.data_usage_app_restrict_background);
2019a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setMessage(R.string.data_usage_restrict_denied_dialog);
2020a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            builder.setPositiveButton(android.R.string.ok, null);
2021a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2022a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            return builder.create();
2023a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
2024a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    }
2025a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2026a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    /**
20279fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey     * Dialog to request user confirmation before setting
20289fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey     * {@link #POLICY_REJECT_METERED_BACKGROUND}.
20299fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey     */
20309fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey    public static class ConfirmAppRestrictFragment extends DialogFragment {
20319fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public static void show(DataUsageSummary parent) {
2032461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey            if (!parent.isAdded()) return;
2033461842a8c0000ebc1351ec7fe30b0f820b769ccfJeff Sharkey
20349fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final ConfirmAppRestrictFragment dialog = new ConfirmAppRestrictFragment();
20359fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            dialog.setTargetFragment(parent, 0);
20369fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_APP_RESTRICT);
20379fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        }
20389fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
20399fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        @Override
20409fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey        public Dialog onCreateDialog(Bundle savedInstanceState) {
20419fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final Context context = getActivity();
20429fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey
20439fab0da184b07f7a355909d84429a8ea41985e74Jeff Sharkey            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
2044f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            builder.setTitle(R.string.data_usage_app_restrict_dialog_title);
2045f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            builder.setMessage(R.string.data_usage_app_restrict_dialog);
2046f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
2047f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
204876c5ed4f35e0d824d1b36dc2f371762b1e2b9abeJeff Sharkey                @Override
2049f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                public void onClick(DialogInterface dialog, int which) {
2050f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                    final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
2051f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                    if (target != null) {
2052f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                        target.setAppRestrictBackground(true);
2053f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                    }
2054f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey                }
2055f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            });
2056f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            builder.setNegativeButton(android.R.string.cancel, null);
2057f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
2058f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey            return builder.create();
2059f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        }
2060f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    }
2061f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey
2062f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    /**
2063d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani     * Dialog to inform user about changing auto-sync setting
2064d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani     */
2065d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    public static class ConfirmAutoSyncChangeFragment extends DialogFragment {
2066665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani        private static final String SAVE_ENABLING = "enabling";
2067d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        private boolean mEnabling;
2068d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2069d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        public static void show(DataUsageSummary parent, boolean enabling) {
2070d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            if (!parent.isAdded()) return;
2071d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2072d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            final ConfirmAutoSyncChangeFragment dialog = new ConfirmAutoSyncChangeFragment();
2073d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            dialog.mEnabling = enabling;
2074d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            dialog.setTargetFragment(parent, 0);
2075d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            dialog.show(parent.getFragmentManager(), TAG_CONFIRM_AUTO_SYNC_CHANGE);
2076d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        }
2077d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2078d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        @Override
2079d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        public Dialog onCreateDialog(Bundle savedInstanceState) {
2080d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            final Context context = getActivity();
2081665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani            if (savedInstanceState != null) {
2082665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani                mEnabling = savedInstanceState.getBoolean(SAVE_ENABLING);
2083665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani            }
2084d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2085d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
2086d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            if (!mEnabling) {
2087d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                builder.setTitle(R.string.data_usage_auto_sync_off_dialog_title);
2088d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                builder.setMessage(R.string.data_usage_auto_sync_off_dialog);
2089d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            } else {
2090d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                builder.setTitle(R.string.data_usage_auto_sync_on_dialog_title);
2091d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                builder.setMessage(R.string.data_usage_auto_sync_on_dialog);
2092d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            }
2093d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2094d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
2095d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                @Override
2096d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                public void onClick(DialogInterface dialog, int which) {
2097d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                    ContentResolver.setMasterSyncAutomatically(mEnabling);
2098d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                }
2099d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            });
2100d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            builder.setNegativeButton(android.R.string.cancel, null);
2101d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2102d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            return builder.create();
2103d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        }
2104665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani
2105665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani        @Override
2106665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani        public void onSaveInstanceState(Bundle outState) {
2107665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani            super.onSaveInstanceState(outState);
2108665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani            outState.putBoolean(SAVE_ENABLING, mEnabling);
2109665235f6ef5cf5739485a4076be332b0b2cb4431Amith Yamasani        }
2110d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    }
2111d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
2112d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    /**
2113dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey     * Compute default tab that should be selected, based on
2114dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey     * {@link NetworkPolicyManager#EXTRA_NETWORK_TEMPLATE} extra.
2115dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey     */
2116dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey    private static String computeTabFromIntent(Intent intent) {
2117271ec8a8f81ab714e45cc8c7814ea3c5dfb3f36aJeff Sharkey        final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
2118271ec8a8f81ab714e45cc8c7814ea3c5dfb3f36aJeff Sharkey        if (template == null) return null;
2119271ec8a8f81ab714e45cc8c7814ea3c5dfb3f36aJeff Sharkey
2120271ec8a8f81ab714e45cc8c7814ea3c5dfb3f36aJeff Sharkey        switch (template.getMatchRule()) {
2121a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey            case MATCH_MOBILE_3G_LOWER:
2122dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                return TAB_3G;
2123a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey            case MATCH_MOBILE_4G:
2124dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                return TAB_4G;
2125a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey            case MATCH_MOBILE_ALL:
2126dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                return TAB_MOBILE;
2127a662e4975b5c17d91822d6bd23a96a2532c4940dJeff Sharkey            case MATCH_WIFI:
2128dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                return TAB_WIFI;
2129dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey            default:
2130dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey                return null;
2131dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey        }
2132dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey    }
2133dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey
2134dd6efe17e0f2e34dfc0d7bea9e2382a3d48fb775Jeff Sharkey    /**
2135b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey     * Background task that loads {@link UidDetail}, binding to
2136b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey     * {@link DataUsageAdapter} row item when finished.
21378e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey     */
2138b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private static class UidDetailTask extends AsyncTask<Void, Void, UidDetail> {
2139b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        private final UidDetailProvider mProvider;
2140ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        private final AppItem mItem;
2141b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        private final View mTarget;
2142b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
2143ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey        private UidDetailTask(UidDetailProvider provider, AppItem item, View target) {
2144b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mProvider = checkNotNull(provider);
2145b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mItem = checkNotNull(item);
2146b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            mTarget = checkNotNull(target);
2147b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
2148b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
2149b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        public static void bindView(
2150ef6e1ff728bdf67e222d4d3452f5f354f519556fJeff Sharkey                UidDetailProvider provider, AppItem item, View target) {
2151b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            final UidDetailTask existing = (UidDetailTask) target.getTag();
2152b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (existing != null) {
2153b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                existing.cancel(false);
2154b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            }
2155d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey
215638305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final UidDetail cachedDetail = provider.getUidDetail(item.key, false);
2157b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (cachedDetail != null) {
2158b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                bindView(cachedDetail, target);
2159b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            } else {
2160b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                target.setTag(new UidDetailTask(provider, item, target).executeOnExecutor(
2161b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                        AsyncTask.THREAD_POOL_EXECUTOR));
2162b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            }
2163518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey        }
2164518bc9df8b02fb5d16674f17b1fce18e79e1b38aJeff Sharkey
2165b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        private static void bindView(UidDetail detail, View target) {
2166b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            final ImageView icon = (ImageView) target.findViewById(android.R.id.icon);
2167b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            final TextView title = (TextView) target.findViewById(android.R.id.title);
21688e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey
2169b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (detail != null) {
2170b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                icon.setImageDrawable(detail.icon);
2171b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                title.setText(detail.label);
2172b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            } else {
2173b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                icon.setImageDrawable(null);
2174b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                title.setText(null);
21758e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey            }
21768e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey        }
21778e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey
2178b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        @Override
2179b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        protected void onPreExecute() {
2180b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            bindView(null, mTarget);
2181b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
2182b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
2183b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        @Override
2184b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        protected UidDetail doInBackground(Void... params) {
218538305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            return mProvider.getUidDetail(mItem.key, true);
2186b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
2187b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
2188b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        @Override
2189b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        protected void onPostExecute(UidDetail result) {
2190b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            bindView(result, mTarget);
21918e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey        }
21928e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey    }
21938e911d7b1a6817f67480b7677f8d36ab3bfb00f2Jeff Sharkey
219429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /**
2195313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey     * Test if device has a mobile data radio with SIM in ready state.
219629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     */
2197313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    public static boolean hasReadyMobileRadio(Context context) {
21989549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (TEST_RADIOS) {
21999549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return SystemProperties.get(TEST_RADIOS_PROP).contains("mobile");
22009549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
22019549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
2202313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final ConnectivityManager conn = ConnectivityManager.from(context);
2203313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
2204313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey
2205313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        // require both supported network and ready SIM
2206313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        return conn.isNetworkSupported(TYPE_MOBILE) && tele.getSimState() == SIM_STATE_READY;
220729d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    }
220829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
220929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /**
221029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     * Test if device has a mobile 4G data radio.
221129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     */
2212ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey    public static boolean hasReadyMobile4gRadio(Context context) {
2213b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (!NetworkPolicyEditor.ENABLE_SPLIT_POLICIES) {
2214b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            return false;
2215b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
22169549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (TEST_RADIOS) {
22179549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return SystemProperties.get(TEST_RADIOS_PROP).contains("4g");
22189549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
22199549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
2220313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final ConnectivityManager conn = ConnectivityManager.from(context);
2221313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
222229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
2223bdf98e84ab1eeedf9662ed3c08dc917f5fa80f85Jeff Sharkey        final boolean hasWimax = conn.isNetworkSupported(TYPE_WIMAX);
22245543404ae0ec9635b59d37fa01074ea598d539ebWink Saville        final boolean hasLte = (tele.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE)
2225ad17de32bc7b5408cb3324cca36d704f8b32a20fJeff Sharkey                && hasReadyMobileRadio(context);
222629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        return hasWimax || hasLte;
222729d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    }
222829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
222929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /**
223029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     * Test if device has a Wi-Fi data radio.
223129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     */
2232313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    public static boolean hasWifiRadio(Context context) {
22339549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (TEST_RADIOS) {
22349549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi");
22359549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
22369549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
2237313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final ConnectivityManager conn = ConnectivityManager.from(context);
2238bdf98e84ab1eeedf9662ed3c08dc917f5fa80f85Jeff Sharkey        return conn.isNetworkSupported(TYPE_WIFI);
223929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    }
224029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
224129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /**
22429549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey     * Test if device has an ethernet network connection.
22439549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey     */
2244b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey    public boolean hasEthernet(Context context) {
22459549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        if (TEST_RADIOS) {
22469549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey            return SystemProperties.get(TEST_RADIOS_PROP).contains("ethernet");
22479549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey        }
22489549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
2249313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final ConnectivityManager conn = ConnectivityManager.from(context);
2250b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey        final boolean hasEthernet = conn.isNetworkSupported(TYPE_ETHERNET);
2251b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey
2252b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey        final long ethernetBytes;
2253d8789099806a169309071d68cea5f8b82380044eJeff Sharkey        if (mStatsSession != null) {
2254d8789099806a169309071d68cea5f8b82380044eJeff Sharkey            try {
2255d8789099806a169309071d68cea5f8b82380044eJeff Sharkey                ethernetBytes = mStatsSession.getSummaryForNetwork(
2256d8789099806a169309071d68cea5f8b82380044eJeff Sharkey                        NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
2257d8789099806a169309071d68cea5f8b82380044eJeff Sharkey                        .getTotalBytes();
2258d8789099806a169309071d68cea5f8b82380044eJeff Sharkey            } catch (RemoteException e) {
2259d8789099806a169309071d68cea5f8b82380044eJeff Sharkey                throw new RuntimeException(e);
2260d8789099806a169309071d68cea5f8b82380044eJeff Sharkey            }
2261d8789099806a169309071d68cea5f8b82380044eJeff Sharkey        } else {
2262d8789099806a169309071d68cea5f8b82380044eJeff Sharkey            ethernetBytes = 0;
2263b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey        }
2264b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey
2265d8789099806a169309071d68cea5f8b82380044eJeff Sharkey        // only show ethernet when both hardware present and traffic has occurred
2266b67c4a8e732157b041cb67f220706f07bc53ef15Jeff Sharkey        return hasEthernet && ethernetBytes > 0;
22679549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    }
22689549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey
22699549e9f377b597313175cb5d273bedd7a1a8e463Jeff Sharkey    /**
227029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     * Inflate a {@link Preference} style layout, adding the given {@link View}
227129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     * widget into {@link android.R.id#widget_frame}.
227229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     */
227329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private static View inflatePreference(LayoutInflater inflater, ViewGroup root, View widget) {
227429d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final View view = inflater.inflate(R.layout.preference, root, false);
227529d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final LinearLayout widgetFrame = (LinearLayout) view.findViewById(
227629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey                android.R.id.widget_frame);
227729d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        widgetFrame.addView(widget, new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
227829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        return view;
227929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    }
228029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
2281d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey    private static View inflateAppTitle(
2282d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey            LayoutInflater inflater, ViewGroup root, CharSequence label) {
2283d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        final TextView view = (TextView) inflater.inflate(
2284d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey                R.layout.data_usage_app_title, root, false);
2285d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        view.setText(label);
2286d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey        return view;
2287d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey    }
2288d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey
228929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    /**
2290a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * Test if any networks are currently limited.
2291a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     */
2292a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private boolean hasLimitedNetworks() {
2293a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        return !buildLimitedNetworksList().isEmpty();
2294a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    }
2295a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2296a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    /**
229730dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey     * Build string describing currently limited networks, which defines when
229830dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey     * background data is restricted.
229930dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey     */
2300313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    @Deprecated
2301a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private CharSequence buildLimitedNetworksString() {
2302a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        final List<CharSequence> limited = buildLimitedNetworksList();
2303a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2304a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        // handle case where no networks limited
2305a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        if (limited.isEmpty()) {
2306a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey            limited.add(getText(R.string.data_usage_list_none));
2307a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        }
2308a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2309a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        return TextUtils.join(limited);
2310a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    }
2311a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey
2312a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    /**
2313a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * Build list of currently limited networks, which defines when background
2314a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     * data is restricted.
2315a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey     */
2316313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey    @Deprecated
2317a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey    private List<CharSequence> buildLimitedNetworksList() {
231830dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        final Context context = getActivity();
231930dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey
232030dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        // build combined list of all limited networks
232130dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        final ArrayList<CharSequence> limited = Lists.newArrayList();
2322313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey
2323313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
2324313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (tele.getSimState() == SIM_STATE_READY) {
2325313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            final String subscriberId = getActiveSubscriberId(context);
2326313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobileAll(subscriberId))) {
2327313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                limited.add(getText(R.string.data_usage_list_mobile));
2328313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            }
2329313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile3gLower(subscriberId))) {
2330313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                limited.add(getText(R.string.data_usage_tab_3g));
2331313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            }
2332313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile4g(subscriberId))) {
2333313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey                limited.add(getText(R.string.data_usage_tab_4g));
2334313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey            }
233530dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        }
2336313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey
2337313f7d8c5759fd29a98c710ceb9339d27b8e62faJeff Sharkey        if (mPolicyEditor.hasLimitedPolicy(buildTemplateWifiWildcard())) {
233830dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey            limited.add(getText(R.string.data_usage_tab_wifi));
233930dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        }
234030dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        if (mPolicyEditor.hasLimitedPolicy(buildTemplateEthernet())) {
234130dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey            limited.add(getText(R.string.data_usage_tab_ethernet));
234230dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        }
234330dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey
2344a53188fe5aa09918dd7b5a9ff79ba050a2bfc4c2Jeff Sharkey        return limited;
234530dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey    }
234630dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey
234730dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey    /**
23485d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey     * Inset both selector and divider {@link Drawable} on the given
23495d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey     * {@link ListView} by the requested dimensions.
23505d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey     */
23515d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey    private static void insetListViewDrawables(ListView view, int insetSide) {
23525d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        final Drawable selector = view.getSelector();
23535d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        final Drawable divider = view.getDivider();
23545d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey
23555d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        // fully unregister these drawables so callbacks can be maintained after
23565d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        // wrapping below.
23575d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        final Drawable stub = new ColorDrawable(Color.TRANSPARENT);
23585d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        view.setSelector(stub);
23595d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        view.setDivider(stub);
23605d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey
23615d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        view.setSelector(new InsetBoundsDrawable(selector, insetSide));
23625d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey        view.setDivider(new InsetBoundsDrawable(divider, insetSide));
23635d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey    }
23645d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey
23655d70679c02a57416eac46581d7242e2382e4b973Jeff Sharkey    /**
236629d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     * Set {@link android.R.id#title} for a preference view inflated with
236752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey     * {@link #inflatePreference(LayoutInflater, ViewGroup, View)}.
236829d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey     */
236929d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    private static void setPreferenceTitle(View parent, int resId) {
237029d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        final TextView title = (TextView) parent.findViewById(android.R.id.title);
237129d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey        title.setText(resId);
237229d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey    }
237329d56b303f39012c0fb83a2b138e227b5413f4ceJeff Sharkey
2374f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    /**
2375f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * Set {@link android.R.id#summary} for a preference view inflated with
2376f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     * {@link #inflatePreference(LayoutInflater, ViewGroup, View)}.
2377f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey     */
237830dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey    private static void setPreferenceSummary(View parent, CharSequence string) {
2379f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        final TextView summary = (TextView) parent.findViewById(android.R.id.summary);
2380f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey        summary.setVisibility(View.VISIBLE);
238130dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey        summary.setText(string);
2382f54f435f1f3215b39798c671fc64344d1867de4eJeff Sharkey    }
2383ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey}
2384