1b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock/*
24cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk * Copyright (C) 2015 The Android Open Source Project
3b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock *
4b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * you may not use this file except in compliance with the License.
6b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * You may obtain a copy of the License at
7b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock *
8b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock *
10b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * See the License for the specific language governing permissions and
14b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock * limitations under the License.
15b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock */
16b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
174cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkpackage com.android.settingslib.net;
18b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
19b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.content.Context;
20b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.net.ConnectivityManager;
21b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.net.INetworkStatsService;
22b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.net.INetworkStatsSession;
235e9049a362016c9f00823346d619303674f9df0eJohn Spurlockimport android.net.NetworkPolicy;
245e9049a362016c9f00823346d619303674f9df0eJohn Spurlockimport android.net.NetworkPolicyManager;
25b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.net.NetworkStatsHistory;
26b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.net.NetworkTemplate;
27b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.os.RemoteException;
28b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.os.ServiceManager;
29b574627ebc383d35cf8212ee241b191b26518a0dJason Monkimport android.telephony.SubscriptionManager;
30b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.telephony.TelephonyManager;
31b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.text.format.DateUtils;
32d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlockimport android.text.format.Time;
33b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport android.util.Log;
34b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
357aeb3f54408a7bd0c1ca3020bca32900b2091b1dAndrew Sappersteinimport com.android.internal.R;
3670196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang
37b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlockimport java.util.Date;
38d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlockimport java.util.Locale;
39b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
404cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.net.ConnectivityManager.TYPE_MOBILE;
414cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
424cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
434cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.telephony.TelephonyManager.SIM_STATE_READY;
444cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
454cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport static android.text.format.DateUtils.FORMAT_SHOW_DATE;
4670196d84a640ed4781e3d79a4dfe2015126238ffFan Zhangimport static android.net.TrafficStats.MB_IN_BYTES;
474cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk
48f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monkpublic class DataUsageController {
4970196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang
50f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    private static final String TAG = "DataUsageController";
51d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
52b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES;
53d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
54d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
55d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            PERIOD_BUILDER, Locale.getDefault());
56b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
57b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private final Context mContext;
58b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private final TelephonyManager mTelephonyManager;
59b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private final ConnectivityManager mConnectivityManager;
60b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private final INetworkStatsService mStatsService;
615e9049a362016c9f00823346d619303674f9df0eJohn Spurlock    private final NetworkPolicyManager mPolicyManager;
62b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
63b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private INetworkStatsSession mSession;
64b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private Callback mCallback;
654cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    private NetworkNameProvider mNetworkController;
66b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
67f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    public DataUsageController(Context context) {
68b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mContext = context;
69b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mTelephonyManager = TelephonyManager.from(context);
70b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mConnectivityManager = ConnectivityManager.from(context);
71b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mStatsService = INetworkStatsService.Stub.asInterface(
72b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
735e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        mPolicyManager = NetworkPolicyManager.from(mContext);
74cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock    }
755e9049a362016c9f00823346d619303674f9df0eJohn Spurlock
764cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    public void setNetworkController(NetworkNameProvider networkController) {
77d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk        mNetworkController = networkController;
78d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk    }
79d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk
8070196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang    /**
8170196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang     * Returns the default warning level in bytes.
8270196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang     */
8370196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang    public long getDefaultWarningLevel() {
8470196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang        return MB_IN_BYTES
8570196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang                * mContext.getResources().getInteger(R.integer.default_data_warning_level_mb);
8670196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang    }
8770196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang
88cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock    private INetworkStatsSession getSession() {
89cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock        if (mSession == null) {
90cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock            try {
91cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock                mSession = mStatsService.openSession();
92cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock            } catch (RemoteException e) {
93cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock                Log.w(TAG, "Failed to open stats session", e);
94cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock            } catch (RuntimeException e) {
95cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock                Log.w(TAG, "Failed to open stats session", e);
96cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock            }
97b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        }
98cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock        return mSession;
99b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
100b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
101b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public void setCallback(Callback callback) {
102b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mCallback = callback;
103b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
104b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
105b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private DataUsageInfo warn(String msg) {
106b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        Log.w(TAG, "Failed to get data usage, " + msg);
107b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        return null;
108b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
109b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
110d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    private static Time addMonth(Time t, int months) {
111d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        final Time rt = new Time(t);
112d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        rt.set(t.monthDay, t.month + months, t.year);
113d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        rt.normalize(false);
114d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        return rt;
115d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    }
116d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock
117b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public DataUsageInfo getDataUsageInfo() {
118b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        final String subscriberId = getActiveSubscriberId(mContext);
119b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        if (subscriberId == null) {
120b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            return warn("no subscriber id");
121b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        }
122f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
123f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        template = NetworkTemplate.normalize(template, mTelephonyManager.getMergedSubscriberIds());
124f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk
125f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        return getDataUsageInfo(template);
126f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    }
127f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk
128f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    public DataUsageInfo getWifiDataUsageInfo() {
129f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard();
130f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        return getDataUsageInfo(template);
131f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    }
132f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk
133f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk    public DataUsageInfo getDataUsageInfo(NetworkTemplate template) {
134cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock        final INetworkStatsSession session = getSession();
135cfa39d269bf404f6121889ebc431fbf20a79eb2aJohn Spurlock        if (session == null) {
136b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            return warn("no stats session");
137b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        }
1385e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        final NetworkPolicy policy = findNetworkPolicy(template);
139b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        try {
140f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk            final NetworkStatsHistory history = session.getHistoryForNetwork(template, FIELDS);
141b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final long now = System.currentTimeMillis();
142d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            final long start, end;
143d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            if (policy != null && policy.cycleDay > 0) {
144d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                // period = determined from cycleDay
145d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                if (DEBUG) Log.d(TAG, "Cycle day=" + policy.cycleDay + " tz="
146d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                        + policy.cycleTimezone);
147d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                final Time nowTime = new Time(policy.cycleTimezone);
148d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                nowTime.setToNow();
149d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                final Time policyTime = new Time(nowTime);
150d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                policyTime.set(policy.cycleDay, policyTime.month, policyTime.year);
151d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                policyTime.normalize(false);
152d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                if (nowTime.after(policyTime)) {
153d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                    start = policyTime.toMillis(false);
154d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                    end = addMonth(policyTime, 1).toMillis(false);
155d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                } else {
156d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                    start = addMonth(policyTime, -1).toMillis(false);
157d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                    end = policyTime.toMillis(false);
158d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                }
159d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            } else {
160d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                // period = last 4 wks
161d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                end = now;
162d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                start = now - DateUtils.WEEK_IN_MILLIS * 4;
163d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            }
164b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final long callStart = System.currentTimeMillis();
165b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
166b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final long callEnd = System.currentTimeMillis();
167b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            if (DEBUG) Log.d(TAG, String.format("history call from %s to %s now=%s took %sms: %s",
168b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                    new Date(start), new Date(end), new Date(now), callEnd - callStart,
169b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                    historyEntryToString(entry)));
170b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            if (entry == null) {
171b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                return warn("no entry data");
172b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            }
173b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final long totalBytes = entry.rxBytes + entry.txBytes;
174b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            final DataUsageInfo usage = new DataUsageInfo();
175f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk            usage.startDate = start;
176b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            usage.usageLevel = totalBytes;
177d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            usage.period = formatDateRange(start, end);
1785e9049a362016c9f00823346d619303674f9df0eJohn Spurlock            if (policy != null) {
1795e9049a362016c9f00823346d619303674f9df0eJohn Spurlock                usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0;
1805e9049a362016c9f00823346d619303674f9df0eJohn Spurlock                usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0;
181d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            } else {
18270196d84a640ed4781e3d79a4dfe2015126238ffFan Zhang                usage.warningLevel = getDefaultWarningLevel();
1835e9049a362016c9f00823346d619303674f9df0eJohn Spurlock            }
1844cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk            if (usage != null && mNetworkController != null) {
1855504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                usage.carrier = mNetworkController.getMobileDataNetworkName();
186d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk            }
187b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            return usage;
188b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        } catch (RemoteException e) {
189b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            return warn("remote call failed");
190b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        }
191b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
192b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
1935e9049a362016c9f00823346d619303674f9df0eJohn Spurlock    private NetworkPolicy findNetworkPolicy(NetworkTemplate template) {
1945e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        if (mPolicyManager == null || template == null) return null;
1955e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies();
1965e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        if (policies == null) return null;
1975e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        final int N = policies.length;
1985e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        for (int i = 0; i < N; i++) {
1995e9049a362016c9f00823346d619303674f9df0eJohn Spurlock            final NetworkPolicy policy = policies[i];
2005e9049a362016c9f00823346d619303674f9df0eJohn Spurlock            if (policy != null && template.equals(policy.template)) {
2015e9049a362016c9f00823346d619303674f9df0eJohn Spurlock                return policy;
2025e9049a362016c9f00823346d619303674f9df0eJohn Spurlock            }
2035e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        }
2045e9049a362016c9f00823346d619303674f9df0eJohn Spurlock        return null;
2055e9049a362016c9f00823346d619303674f9df0eJohn Spurlock    }
2065e9049a362016c9f00823346d619303674f9df0eJohn Spurlock
207b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private static String historyEntryToString(NetworkStatsHistory.Entry entry) {
208b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        return entry == null ? null : new StringBuilder("Entry[")
209b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append("bucketDuration=").append(entry.bucketDuration)
210b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",bucketStart=").append(entry.bucketStart)
211b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",activeTime=").append(entry.activeTime)
212b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",rxBytes=").append(entry.rxBytes)
213b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",rxPackets=").append(entry.rxPackets)
214b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",txBytes=").append(entry.txBytes)
215b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",txPackets=").append(entry.txPackets)
216b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(",operations=").append(entry.operations)
217b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                .append(']').toString();
218b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
219b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
220b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public void setMobileDataEnabled(boolean enabled) {
22136ffb0494dd1045c164b7479b68165e206f8c759Wink Saville        Log.d(TAG, "setMobileDataEnabled: enabled=" + enabled);
222b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        mTelephonyManager.setDataEnabled(enabled);
223b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        if (mCallback != null) {
224b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock            mCallback.onMobileDataEnabled(enabled);
225b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        }
226b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
227b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
228b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public boolean isMobileDataSupported() {
229b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        // require both supported network and ready SIM
230b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        return mConnectivityManager.isNetworkSupported(TYPE_MOBILE)
231b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock                && mTelephonyManager.getSimState() == SIM_STATE_READY;
232b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
233b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
234b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public boolean isMobileDataEnabled() {
235b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        return mTelephonyManager.getDataEnabled();
236b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
237b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
238b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    private static String getActiveSubscriberId(Context context) {
239b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        final TelephonyManager tele = TelephonyManager.from(context);
240b574627ebc383d35cf8212ee241b191b26518a0dJason Monk        final String actualSubscriberId = tele.getSubscriberId(
2417ea3e8bf8954343d7b243b6a23bcb8339921f3c8Shishir Agrawal                SubscriptionManager.getDefaultDataSubscriptionId());
242b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        return actualSubscriberId;
243b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
244b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock
245d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    private String formatDateRange(long start, long end) {
246d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        final int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
247d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        synchronized (PERIOD_BUILDER) {
248d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            PERIOD_BUILDER.setLength(0);
249d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock            return DateUtils.formatDateRange(mContext, PERIOD_FORMATTER, start, end, flags, null)
250d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock                    .toString();
251d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock        }
252d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock    }
253d11a19b8ea08035c14052ee42cbc529e62cc4c70John Spurlock
2544cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    public interface NetworkNameProvider {
2554cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        String getMobileDataNetworkName();
2564cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    }
2574cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk
2584cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    public static class DataUsageInfo {
2594cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        public String carrier;
2604cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        public String period;
261f668d7cceb3c6cc9143fcf92230681bddd7ccf21Jason Monk        public long startDate;
2624cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        public long limitLevel;
2634cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        public long warningLevel;
2644cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk        public long usageLevel;
2654cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk    }
2664cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk
267b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    public interface Callback {
268b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock        void onMobileDataEnabled(boolean enabled);
269b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock    }
270b98f747c714ff8252471ca0a3295c2cb9ccb4f3aJohn Spurlock}
271