blob: b2fe95869141b79b46916b8f2944b5c90e5c319d [file] [log] [blame]
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +00001/**
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package android.app.usage;
18
Antonio Cansadoba8288d2015-12-02 08:42:54 -080019import static com.android.internal.util.Preconditions.checkNotNull;
20
21import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060022import android.annotation.SystemService;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010023import android.app.usage.NetworkStats.Bucket;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000024import android.content.Context;
25import android.net.ConnectivityManager;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080026import android.net.DataUsageRequest;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060027import android.net.INetworkStatsService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000028import android.net.NetworkIdentity;
29import android.net.NetworkTemplate;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080030import android.os.Binder;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080031import android.os.Handler;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080032import android.os.Looper;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060033import android.os.Message;
34import android.os.Messenger;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000035import android.os.RemoteException;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080036import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060037import android.os.ServiceManager.ServiceNotFoundException;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000038import android.util.Log;
39
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +090040import com.android.internal.annotations.VisibleForTesting;
41
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000042/**
43 * Provides access to network usage history and statistics. Usage data is collected in
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010044 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000045 * <p />
46 * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
Jeff Davidson1efb1332015-12-09 18:04:50 -080047 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
48 * data about themselves. See the below note for special cases in which apps can obtain data about
49 * other applications.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000050 * <h3>
51 * Summary queries
52 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010053 * {@link #querySummaryForDevice} <p />
54 * {@link #querySummaryForUser} <p />
55 * {@link #querySummary} <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000056 * These queries aggregate network usage across the whole interval. Therefore there will be only one
Stephen Chen25147872016-10-21 12:44:26 -070057 * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
58 * and device-wide summaries a single bucket containing the totalised network usage is returned.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000059 * <h3>
60 * History queries
61 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010062 * {@link #queryDetailsForUid} <p />
63 * {@link #queryDetails} <p />
Stephen Chen25147872016-10-21 12:44:26 -070064 * These queries do not aggregate over time but do aggregate over state, metered and roaming.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +090065 * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
66 * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
67 * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
68 * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
69 * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000070 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000071 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
72 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
73 * which is a system-level permission and will not be granted to third-party apps. However,
74 * declaring the permission implies intention to use the API and the user of the device can grant
75 * permission through the Settings application.
76 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000077 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080078 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
79 * privileged apps likewise get access to usage data for all users on the device.
80 * <p />
81 * In addition to tethering usage, usage by removed users and apps, and usage by the system
82 * is also included in the results for callers with one of these higher levels of access.
83 * <p />
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060084 * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required
Jeff Davidson1efb1332015-12-09 18:04:50 -080085 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
86 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000087 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060088@SystemService(Context.NETWORK_STATS_SERVICE)
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000089public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -080090 private static final String TAG = "NetworkStatsManager";
91 private static final boolean DBG = false;
92
93 /** @hide */
94 public static final int CALLBACK_LIMIT_REACHED = 0;
95 /** @hide */
96 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000097
98 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080099 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000100
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600101 /** @hide */
102 public static final int FLAG_POLL_ON_OPEN = 1 << 0;
103 /** @hide */
104 public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1;
105
106 private int mFlags;
107
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000108 /**
109 * {@hide}
110 */
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600111 public NetworkStatsManager(Context context) throws ServiceNotFoundException {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900112 this(context, INetworkStatsService.Stub.asInterface(
113 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
114 }
115
116 /** @hide */
117 @VisibleForTesting
118 public NetworkStatsManager(Context context, INetworkStatsService service) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000119 mContext = context;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900120 mService = service;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600121 setPollOnOpen(true);
122 }
123
124 /** @hide */
125 public void setPollOnOpen(boolean pollOnOpen) {
126 if (pollOnOpen) {
127 mFlags |= FLAG_POLL_ON_OPEN;
128 } else {
129 mFlags &= ~FLAG_POLL_ON_OPEN;
130 }
131 }
132
133 /** @hide */
134 public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
135 if (augmentWithSubscriptionPlan) {
136 mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
137 } else {
138 mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
139 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000140 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800141
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900142 /** @hide */
143 public Bucket querySummaryForDevice(NetworkTemplate template,
144 long startTime, long endTime) throws SecurityException, RemoteException {
145 Bucket bucket = null;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900146 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
147 mService);
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900148 bucket = stats.getDeviceSummaryForNetwork();
149
150 stats.close();
151 return bucket;
152 }
153
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000154 /**
155 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chen25147872016-10-21 12:44:26 -0700156 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
157 * roaming. This means the bucket's start and end timestamp are going to be the same as the
158 * 'startTime' and 'endTime' parameters. State is going to be
159 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900160 * tag {@link NetworkStats.Bucket#TAG_NONE},
161 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
162 * metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800163 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000164 *
165 * @param networkType As defined in {@link ConnectivityManager}, e.g.
166 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
167 * etc.
168 * @param subscriberId If applicable, the subscriber id of the network interface.
169 * @param startTime Start of period. Defined in terms of "Unix time", see
170 * {@link java.lang.System#currentTimeMillis}.
171 * @param endTime End of period. Defined in terms of "Unix time", see
172 * {@link java.lang.System#currentTimeMillis}.
173 * @return Bucket object or null if permissions are insufficient or error happened during
174 * statistics collection.
175 */
176 public Bucket querySummaryForDevice(int networkType, String subscriberId,
177 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700178 NetworkTemplate template;
179 try {
180 template = createTemplate(networkType, subscriberId);
181 } catch (IllegalArgumentException e) {
182 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000183 return null;
184 }
185
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900186 return querySummaryForDevice(template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000187 }
188
189 /**
190 * Query network usage statistics summaries. Result is summarised data usage for all uids
191 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100192 * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
Stephen Chen25147872016-10-21 12:44:26 -0700193 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
194 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
195 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
196 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000197 *
198 * @param networkType As defined in {@link ConnectivityManager}, e.g.
199 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
200 * etc.
201 * @param subscriberId If applicable, the subscriber id of the network interface.
202 * @param startTime Start of period. Defined in terms of "Unix time", see
203 * {@link java.lang.System#currentTimeMillis}.
204 * @param endTime End of period. Defined in terms of "Unix time", see
205 * {@link java.lang.System#currentTimeMillis}.
206 * @return Bucket object or null if permissions are insufficient or error happened during
207 * statistics collection.
208 */
209 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700210 long endTime) throws SecurityException, RemoteException {
211 NetworkTemplate template;
212 try {
213 template = createTemplate(networkType, subscriberId);
214 } catch (IllegalArgumentException e) {
215 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000216 return null;
217 }
218
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100219 NetworkStats stats;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900220 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700221 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000222
223 stats.close();
224 return stats.getSummaryAggregate();
225 }
226
227 /**
228 * Query network usage statistics summaries. Result filtered to include only uids belonging to
229 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900230 * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
231 * means buckets' start and end timestamps are going to be the same as the 'startTime' and
232 * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
233 * be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000234 *
235 * @param networkType As defined in {@link ConnectivityManager}, e.g.
236 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
237 * etc.
238 * @param subscriberId If applicable, the subscriber id of the network interface.
239 * @param startTime Start of period. Defined in terms of "Unix time", see
240 * {@link java.lang.System#currentTimeMillis}.
241 * @param endTime End of period. Defined in terms of "Unix time", see
242 * {@link java.lang.System#currentTimeMillis}.
243 * @return Statistics object or null if permissions are insufficient or error happened during
244 * statistics collection.
245 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100246 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700247 long endTime) throws SecurityException, RemoteException {
248 NetworkTemplate template;
249 try {
250 template = createTemplate(networkType, subscriberId);
251 } catch (IllegalArgumentException e) {
252 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000253 return null;
254 }
255
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100256 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900257 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700258 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000259
260 return result;
261 }
262
263 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800264 * Query network usage statistics details for a given uid.
265 *
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900266 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
Antonio Cansado46c753672015-12-10 15:57:56 -0800267 */
268 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900269 long startTime, long endTime, int uid) throws SecurityException {
270 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
271 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
Antonio Cansado46c753672015-12-10 15:57:56 -0800272 }
273
274 /**
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900275 * Query network usage statistics details for a given uid and tag.
276 *
277 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
278 */
279 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
280 long startTime, long endTime, int uid, int tag) throws SecurityException {
281 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
282 tag, NetworkStats.Bucket.STATE_ALL);
283 }
284
285 /**
286 * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
287 * belonging to calling user. Result is not aggregated over time. This means buckets' start and
288 * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
289 * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
290 * the same as the 'state' parameter.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900291 * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
292 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
293 * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100294 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
295 * interpolate across partial buckets. Since bucket length is in the order of hours, this
296 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000297 *
298 * @param networkType As defined in {@link ConnectivityManager}, e.g.
299 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
300 * etc.
301 * @param subscriberId If applicable, the subscriber id of the network interface.
302 * @param startTime Start of period. Defined in terms of "Unix time", see
303 * {@link java.lang.System#currentTimeMillis}.
304 * @param endTime End of period. Defined in terms of "Unix time", see
305 * {@link java.lang.System#currentTimeMillis}.
306 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700307 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Antonio Cansado904237f2016-05-25 09:57:21 -0700308 * @return Statistics object or null if an error happened during statistics collection.
309 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000310 */
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900311 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
312 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700313 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700314 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000315
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100316 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700317 try {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900318 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900319 result.startHistoryEnumeration(uid, tag, state);
Antonio Cansado6965c182016-03-30 11:37:18 -0700320 } catch (RemoteException e) {
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900321 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
322 + " state=" + state, e);
Antonio Cansado6965c182016-03-30 11:37:18 -0700323 return null;
324 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000325
326 return result;
327 }
328
329 /**
330 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chen25147872016-10-21 12:44:26 -0700331 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
332 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
333 * 'startTime' and 'endTime' parameters. State is going to be
334 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900335 * tag {@link NetworkStats.Bucket#TAG_NONE},
336 * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
337 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
338 * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100339 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
340 * interpolate across partial buckets. Since bucket length is in the order of hours, this
341 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000342 *
343 * @param networkType As defined in {@link ConnectivityManager}, e.g.
344 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
345 * etc.
346 * @param subscriberId If applicable, the subscriber id of the network interface.
347 * @param startTime Start of period. Defined in terms of "Unix time", see
348 * {@link java.lang.System#currentTimeMillis}.
349 * @param endTime End of period. Defined in terms of "Unix time", see
350 * {@link java.lang.System#currentTimeMillis}.
351 * @return Statistics object or null if permissions are insufficient or error happened during
352 * statistics collection.
353 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100354 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000355 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700356 NetworkTemplate template;
357 try {
358 template = createTemplate(networkType, subscriberId);
359 } catch (IllegalArgumentException e) {
360 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000361 return null;
362 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700363
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100364 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900365 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000366 result.startUserUidEnumeration();
367 return result;
368 }
369
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900370 /** @hide */
371 public void registerUsageCallback(NetworkTemplate template, int networkType,
372 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
373 checkNotNull(callback, "UsageCallback cannot be null");
374
375 final Looper looper;
376 if (handler == null) {
377 looper = Looper.myLooper();
378 } else {
379 looper = handler.getLooper();
380 }
381
382 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
383 template, thresholdBytes);
384 try {
385 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
386 template.getSubscriberId(), callback);
387 callback.request = mService.registerUsageCallback(
388 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
389 new Binder());
390 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
391
392 if (callback.request == null) {
393 Log.e(TAG, "Request from callback is null; should not happen");
394 }
395 } catch (RemoteException e) {
396 if (DBG) Log.d(TAG, "Remote exception when registering callback");
397 throw e.rethrowFromSystemServer();
398 }
399 }
400
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800401 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700402 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800403 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700404 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800405 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700406 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
407 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700408 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
409 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800410 }
411
412 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700413 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800414 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700415 * <p>The callbacks will continue to be called as long as the process is live or
416 * {@link #unregisterUsageCallback} is called.
417 *
418 * @param networkType Type of network to monitor. Either
419 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
420 * @param subscriberId If applicable, the subscriber id of the network interface.
421 * @param thresholdBytes Threshold in bytes to be notified on.
422 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800423 * has exceeded the specified threshold.
424 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
425 * the calling thread.
426 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700427 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
428 UsageCallback callback, @Nullable Handler handler) {
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900429 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansado6965c182016-03-30 11:37:18 -0700430 if (DBG) {
431 Log.d(TAG, "registerUsageCallback called with: {"
432 + " networkType=" + networkType
433 + " subscriberId=" + subscriberId
434 + " thresholdBytes=" + thresholdBytes
435 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800436 }
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900437 registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800438 }
439
440 /**
441 * Unregisters callbacks on data usage.
442 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700443 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800444 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700445 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800446 if (callback == null || callback.request == null
447 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700448 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800449 }
450 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700451 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800452 } catch (RemoteException e) {
453 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700454 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800455 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800456 }
457
Antonio Cansado6965c182016-03-30 11:37:18 -0700458 /**
459 * Base class for usage callbacks. Should be extended by applications wanting notifications.
460 */
461 public static abstract class UsageCallback {
462
463 /**
464 * Called when data usage has reached the given threshold.
465 */
466 public abstract void onThresholdReached(int networkType, String subscriberId);
467
468 /**
469 * @hide used for internal bookkeeping
470 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800471 private DataUsageRequest request;
472 }
473
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000474 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900475 final NetworkTemplate template;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000476 switch (networkType) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900477 case ConnectivityManager.TYPE_MOBILE:
478 template = subscriberId == null
479 ? NetworkTemplate.buildTemplateMobileWildcard()
480 : NetworkTemplate.buildTemplateMobileAll(subscriberId);
481 break;
482 case ConnectivityManager.TYPE_WIFI:
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000483 template = NetworkTemplate.buildTemplateWifiWildcard();
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900484 break;
485 default:
Antonio Cansado6965c182016-03-30 11:37:18 -0700486 throw new IllegalArgumentException("Cannot create template for network type "
487 + networkType + ", subscriberId '"
488 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000489 }
490 return template;
491 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800492
493 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700494 private final int mNetworkType;
495 private final String mSubscriberId;
496 private UsageCallback mCallback;
497
498 CallbackHandler(Looper looper, int networkType, String subscriberId,
499 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800500 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700501 mNetworkType = networkType;
502 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800503 mCallback = callback;
504 }
505
506 @Override
507 public void handleMessage(Message message) {
508 DataUsageRequest request =
509 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
510
511 switch (message.what) {
512 case CALLBACK_LIMIT_REACHED: {
513 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700514 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800515 } else {
516 Log.e(TAG, "limit reached with released callback for " + request);
517 }
518 break;
519 }
520 case CALLBACK_RELEASED: {
521 if (DBG) Log.d(TAG, "callback released for " + request);
522 mCallback = null;
523 break;
524 }
525 }
526 }
527
528 private static Object getObject(Message msg, String key) {
529 return msg.getData().getParcelable(key);
530 }
531 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000532}