blob: 34f3a8da952409cbfd56d3b7581f3c5007bdc5b3 [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;
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +090038import android.util.DataUnit;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000039import android.util.Log;
40
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +090041import com.android.internal.annotations.VisibleForTesting;
42
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000043/**
44 * Provides access to network usage history and statistics. Usage data is collected in
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010045 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000046 * <p />
47 * 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 -080048 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
49 * data about themselves. See the below note for special cases in which apps can obtain data about
50 * other applications.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000051 * <h3>
52 * Summary queries
53 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010054 * {@link #querySummaryForDevice} <p />
55 * {@link #querySummaryForUser} <p />
56 * {@link #querySummary} <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000057 * These queries aggregate network usage across the whole interval. Therefore there will be only one
Stephen Chen25147872016-10-21 12:44:26 -070058 * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
59 * and device-wide summaries a single bucket containing the totalised network usage is returned.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000060 * <h3>
61 * History queries
62 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010063 * {@link #queryDetailsForUid} <p />
64 * {@link #queryDetails} <p />
Stephen Chen25147872016-10-21 12:44:26 -070065 * These queries do not aggregate over time but do aggregate over state, metered and roaming.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +090066 * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
67 * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
68 * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
69 * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
70 * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000071 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000072 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
73 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
74 * which is a system-level permission and will not be granted to third-party apps. However,
75 * declaring the permission implies intention to use the API and the user of the device can grant
76 * permission through the Settings application.
77 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000078 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080079 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
80 * privileged apps likewise get access to usage data for all users on the device.
81 * <p />
82 * In addition to tethering usage, usage by removed users and apps, and usage by the system
83 * is also included in the results for callers with one of these higher levels of access.
84 * <p />
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060085 * <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 -080086 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
87 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000088 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060089@SystemService(Context.NETWORK_STATS_SERVICE)
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000090public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -080091 private static final String TAG = "NetworkStatsManager";
92 private static final boolean DBG = false;
93
94 /** @hide */
95 public static final int CALLBACK_LIMIT_REACHED = 0;
96 /** @hide */
97 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000098
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +090099 /**
100 * Minimum data usage threshold for registering usage callbacks.
101 *
102 * Requests registered with a threshold lower than this will only be triggered once this minimum
103 * is reached.
104 * @hide
105 */
106 public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
107
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000108 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800109 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000110
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600111 /** @hide */
112 public static final int FLAG_POLL_ON_OPEN = 1 << 0;
113 /** @hide */
114 public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1;
115
116 private int mFlags;
117
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000118 /**
119 * {@hide}
120 */
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600121 public NetworkStatsManager(Context context) throws ServiceNotFoundException {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900122 this(context, INetworkStatsService.Stub.asInterface(
123 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
124 }
125
126 /** @hide */
127 @VisibleForTesting
128 public NetworkStatsManager(Context context, INetworkStatsService service) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000129 mContext = context;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900130 mService = service;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600131 setPollOnOpen(true);
132 }
133
134 /** @hide */
135 public void setPollOnOpen(boolean pollOnOpen) {
136 if (pollOnOpen) {
137 mFlags |= FLAG_POLL_ON_OPEN;
138 } else {
139 mFlags &= ~FLAG_POLL_ON_OPEN;
140 }
141 }
142
143 /** @hide */
144 public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
145 if (augmentWithSubscriptionPlan) {
146 mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
147 } else {
148 mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
149 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000150 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800151
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900152 /** @hide */
153 public Bucket querySummaryForDevice(NetworkTemplate template,
154 long startTime, long endTime) throws SecurityException, RemoteException {
155 Bucket bucket = null;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900156 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
157 mService);
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900158 bucket = stats.getDeviceSummaryForNetwork();
159
160 stats.close();
161 return bucket;
162 }
163
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000164 /**
165 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chen25147872016-10-21 12:44:26 -0700166 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
167 * roaming. This means the bucket's start and end timestamp are going to be the same as the
168 * 'startTime' and 'endTime' parameters. State is going to be
169 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900170 * tag {@link NetworkStats.Bucket#TAG_NONE},
171 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
172 * metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800173 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000174 *
175 * @param networkType As defined in {@link ConnectivityManager}, e.g.
176 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
177 * etc.
178 * @param subscriberId If applicable, the subscriber id of the network interface.
179 * @param startTime Start of period. Defined in terms of "Unix time", see
180 * {@link java.lang.System#currentTimeMillis}.
181 * @param endTime End of period. Defined in terms of "Unix time", see
182 * {@link java.lang.System#currentTimeMillis}.
183 * @return Bucket object or null if permissions are insufficient or error happened during
184 * statistics collection.
185 */
186 public Bucket querySummaryForDevice(int networkType, String subscriberId,
187 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700188 NetworkTemplate template;
189 try {
190 template = createTemplate(networkType, subscriberId);
191 } catch (IllegalArgumentException e) {
192 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000193 return null;
194 }
195
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900196 return querySummaryForDevice(template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000197 }
198
199 /**
200 * Query network usage statistics summaries. Result is summarised data usage for all uids
201 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100202 * 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 -0700203 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
204 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
205 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
206 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000207 *
208 * @param networkType As defined in {@link ConnectivityManager}, e.g.
209 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
210 * etc.
211 * @param subscriberId If applicable, the subscriber id of the network interface.
212 * @param startTime Start of period. Defined in terms of "Unix time", see
213 * {@link java.lang.System#currentTimeMillis}.
214 * @param endTime End of period. Defined in terms of "Unix time", see
215 * {@link java.lang.System#currentTimeMillis}.
216 * @return Bucket object or null if permissions are insufficient or error happened during
217 * statistics collection.
218 */
219 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700220 long endTime) throws SecurityException, RemoteException {
221 NetworkTemplate template;
222 try {
223 template = createTemplate(networkType, subscriberId);
224 } catch (IllegalArgumentException e) {
225 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000226 return null;
227 }
228
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100229 NetworkStats stats;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900230 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700231 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000232
233 stats.close();
234 return stats.getSummaryAggregate();
235 }
236
237 /**
238 * Query network usage statistics summaries. Result filtered to include only uids belonging to
239 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900240 * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
241 * means buckets' start and end timestamps are going to be the same as the 'startTime' and
242 * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
243 * be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000244 *
245 * @param networkType As defined in {@link ConnectivityManager}, e.g.
246 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
247 * etc.
248 * @param subscriberId If applicable, the subscriber id of the network interface.
249 * @param startTime Start of period. Defined in terms of "Unix time", see
250 * {@link java.lang.System#currentTimeMillis}.
251 * @param endTime End of period. Defined in terms of "Unix time", see
252 * {@link java.lang.System#currentTimeMillis}.
253 * @return Statistics object or null if permissions are insufficient or error happened during
254 * statistics collection.
255 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100256 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700257 long endTime) throws SecurityException, RemoteException {
258 NetworkTemplate template;
259 try {
260 template = createTemplate(networkType, subscriberId);
261 } catch (IllegalArgumentException e) {
262 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000263 return null;
264 }
265
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100266 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900267 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700268 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000269
270 return result;
271 }
272
273 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800274 * Query network usage statistics details for a given uid.
275 *
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900276 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
Antonio Cansado46c753672015-12-10 15:57:56 -0800277 */
278 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900279 long startTime, long endTime, int uid) throws SecurityException {
280 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
281 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
Antonio Cansado46c753672015-12-10 15:57:56 -0800282 }
283
284 /**
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900285 * Query network usage statistics details for a given uid and tag.
286 *
287 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
288 */
289 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
290 long startTime, long endTime, int uid, int tag) throws SecurityException {
291 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
292 tag, NetworkStats.Bucket.STATE_ALL);
293 }
294
295 /**
296 * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
297 * belonging to calling user. Result is not aggregated over time. This means buckets' start and
298 * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
299 * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
300 * the same as the 'state' parameter.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900301 * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
302 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
303 * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100304 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
305 * interpolate across partial buckets. Since bucket length is in the order of hours, this
306 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000307 *
308 * @param networkType As defined in {@link ConnectivityManager}, e.g.
309 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
310 * etc.
311 * @param subscriberId If applicable, the subscriber id of the network interface.
312 * @param startTime Start of period. Defined in terms of "Unix time", see
313 * {@link java.lang.System#currentTimeMillis}.
314 * @param endTime End of period. Defined in terms of "Unix time", see
315 * {@link java.lang.System#currentTimeMillis}.
316 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700317 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Antonio Cansado904237f2016-05-25 09:57:21 -0700318 * @return Statistics object or null if an error happened during statistics collection.
319 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000320 */
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900321 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
322 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700323 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700324 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000325
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100326 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700327 try {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900328 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900329 result.startHistoryEnumeration(uid, tag, state);
Antonio Cansado6965c182016-03-30 11:37:18 -0700330 } catch (RemoteException e) {
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900331 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
332 + " state=" + state, e);
Antonio Cansado6965c182016-03-30 11:37:18 -0700333 return null;
334 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000335
336 return result;
337 }
338
339 /**
340 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chen25147872016-10-21 12:44:26 -0700341 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
342 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
343 * 'startTime' and 'endTime' parameters. State is going to be
344 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900345 * tag {@link NetworkStats.Bucket#TAG_NONE},
346 * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
347 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
348 * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100349 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
350 * interpolate across partial buckets. Since bucket length is in the order of hours, this
351 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000352 *
353 * @param networkType As defined in {@link ConnectivityManager}, e.g.
354 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
355 * etc.
356 * @param subscriberId If applicable, the subscriber id of the network interface.
357 * @param startTime Start of period. Defined in terms of "Unix time", see
358 * {@link java.lang.System#currentTimeMillis}.
359 * @param endTime End of period. Defined in terms of "Unix time", see
360 * {@link java.lang.System#currentTimeMillis}.
361 * @return Statistics object or null if permissions are insufficient or error happened during
362 * statistics collection.
363 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100364 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000365 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700366 NetworkTemplate template;
367 try {
368 template = createTemplate(networkType, subscriberId);
369 } catch (IllegalArgumentException e) {
370 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000371 return null;
372 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700373
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100374 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900375 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000376 result.startUserUidEnumeration();
377 return result;
378 }
379
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900380 /** @hide */
381 public void registerUsageCallback(NetworkTemplate template, int networkType,
382 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
383 checkNotNull(callback, "UsageCallback cannot be null");
384
385 final Looper looper;
386 if (handler == null) {
387 looper = Looper.myLooper();
388 } else {
389 looper = handler.getLooper();
390 }
391
392 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
393 template, thresholdBytes);
394 try {
395 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
396 template.getSubscriberId(), callback);
397 callback.request = mService.registerUsageCallback(
398 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
399 new Binder());
400 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
401
402 if (callback.request == null) {
403 Log.e(TAG, "Request from callback is null; should not happen");
404 }
405 } catch (RemoteException e) {
406 if (DBG) Log.d(TAG, "Remote exception when registering callback");
407 throw e.rethrowFromSystemServer();
408 }
409 }
410
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800411 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700412 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800413 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700414 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800415 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700416 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
417 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700418 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
419 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800420 }
421
422 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700423 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800424 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700425 * <p>The callbacks will continue to be called as long as the process is live or
426 * {@link #unregisterUsageCallback} is called.
427 *
428 * @param networkType Type of network to monitor. Either
429 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
430 * @param subscriberId If applicable, the subscriber id of the network interface.
431 * @param thresholdBytes Threshold in bytes to be notified on.
432 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800433 * has exceeded the specified threshold.
434 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
435 * the calling thread.
436 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700437 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
438 UsageCallback callback, @Nullable Handler handler) {
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900439 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansado6965c182016-03-30 11:37:18 -0700440 if (DBG) {
441 Log.d(TAG, "registerUsageCallback called with: {"
442 + " networkType=" + networkType
443 + " subscriberId=" + subscriberId
444 + " thresholdBytes=" + thresholdBytes
445 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800446 }
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900447 registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800448 }
449
450 /**
451 * Unregisters callbacks on data usage.
452 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700453 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800454 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700455 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800456 if (callback == null || callback.request == null
457 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700458 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800459 }
460 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700461 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800462 } catch (RemoteException e) {
463 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700464 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800465 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800466 }
467
Antonio Cansado6965c182016-03-30 11:37:18 -0700468 /**
469 * Base class for usage callbacks. Should be extended by applications wanting notifications.
470 */
471 public static abstract class UsageCallback {
472
473 /**
474 * Called when data usage has reached the given threshold.
475 */
476 public abstract void onThresholdReached(int networkType, String subscriberId);
477
478 /**
479 * @hide used for internal bookkeeping
480 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800481 private DataUsageRequest request;
482 }
483
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000484 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900485 final NetworkTemplate template;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000486 switch (networkType) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900487 case ConnectivityManager.TYPE_MOBILE:
488 template = subscriberId == null
489 ? NetworkTemplate.buildTemplateMobileWildcard()
490 : NetworkTemplate.buildTemplateMobileAll(subscriberId);
491 break;
492 case ConnectivityManager.TYPE_WIFI:
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000493 template = NetworkTemplate.buildTemplateWifiWildcard();
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900494 break;
495 default:
Antonio Cansado6965c182016-03-30 11:37:18 -0700496 throw new IllegalArgumentException("Cannot create template for network type "
497 + networkType + ", subscriberId '"
498 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000499 }
500 return template;
501 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800502
503 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700504 private final int mNetworkType;
505 private final String mSubscriberId;
506 private UsageCallback mCallback;
507
508 CallbackHandler(Looper looper, int networkType, String subscriberId,
509 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800510 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700511 mNetworkType = networkType;
512 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800513 mCallback = callback;
514 }
515
516 @Override
517 public void handleMessage(Message message) {
518 DataUsageRequest request =
519 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
520
521 switch (message.what) {
522 case CALLBACK_LIMIT_REACHED: {
523 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700524 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800525 } else {
526 Log.e(TAG, "limit reached with released callback for " + request);
527 }
528 break;
529 }
530 case CALLBACK_RELEASED: {
531 if (DBG) Log.d(TAG, "callback released for " + request);
532 mCallback = null;
533 break;
534 }
535 }
536 }
537
538 private static Object getObject(Message msg, String key) {
539 return msg.getData().getParcelable(key);
540 }
541 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000542}