blob: 4346d9738ec7bc8fd0b20034ca0379c231cc7c21 [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 android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060020import android.annotation.SystemService;
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -060021import android.annotation.TestApi;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010022import android.app.usage.NetworkStats.Bucket;
Artur Satayevc895b1b2019-12-10 17:47:51 +000023import android.compat.annotation.UnsupportedAppUsage;
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
Daulet Zhanguzin0af97d62019-12-30 15:41:28 +000043import java.util.Objects;
44
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000045/**
46 * Provides access to network usage history and statistics. Usage data is collected in
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010047 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000048 * <p />
49 * 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 -080050 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
51 * data about themselves. See the below note for special cases in which apps can obtain data about
52 * other applications.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000053 * <h3>
54 * Summary queries
55 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010056 * {@link #querySummaryForDevice} <p />
57 * {@link #querySummaryForUser} <p />
58 * {@link #querySummary} <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000059 * These queries aggregate network usage across the whole interval. Therefore there will be only one
Stephen Chen25147872016-10-21 12:44:26 -070060 * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
61 * and device-wide summaries a single bucket containing the totalised network usage is returned.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000062 * <h3>
63 * History queries
64 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010065 * {@link #queryDetailsForUid} <p />
66 * {@link #queryDetails} <p />
Stephen Chen25147872016-10-21 12:44:26 -070067 * These queries do not aggregate over time but do aggregate over state, metered and roaming.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +090068 * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
69 * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
70 * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
71 * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
72 * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000073 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000074 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
75 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
76 * which is a system-level permission and will not be granted to third-party apps. However,
77 * declaring the permission implies intention to use the API and the user of the device can grant
78 * permission through the Settings application.
79 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000080 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080081 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
82 * privileged apps likewise get access to usage data for all users on the device.
83 * <p />
84 * In addition to tethering usage, usage by removed users and apps, and usage by the system
85 * is also included in the results for callers with one of these higher levels of access.
86 * <p />
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060087 * <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 -080088 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
89 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000090 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060091@SystemService(Context.NETWORK_STATS_SERVICE)
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000092public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -080093 private static final String TAG = "NetworkStatsManager";
94 private static final boolean DBG = false;
95
96 /** @hide */
97 public static final int CALLBACK_LIMIT_REACHED = 0;
98 /** @hide */
99 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000100
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +0900101 /**
102 * Minimum data usage threshold for registering usage callbacks.
103 *
104 * Requests registered with a threshold lower than this will only be triggered once this minimum
105 * is reached.
106 * @hide
107 */
108 public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
109
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000110 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800111 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000112
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600113 /** @hide */
114 public static final int FLAG_POLL_ON_OPEN = 1 << 0;
115 /** @hide */
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -0600116 public static final int FLAG_POLL_FORCE = 1 << 1;
117 /** @hide */
118 public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600119
120 private int mFlags;
121
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000122 /**
123 * {@hide}
124 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100125 @UnsupportedAppUsage
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600126 public NetworkStatsManager(Context context) throws ServiceNotFoundException {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900127 this(context, INetworkStatsService.Stub.asInterface(
128 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
129 }
130
131 /** @hide */
132 @VisibleForTesting
133 public NetworkStatsManager(Context context, INetworkStatsService service) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000134 mContext = context;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900135 mService = service;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600136 setPollOnOpen(true);
137 }
138
139 /** @hide */
140 public void setPollOnOpen(boolean pollOnOpen) {
141 if (pollOnOpen) {
142 mFlags |= FLAG_POLL_ON_OPEN;
143 } else {
144 mFlags &= ~FLAG_POLL_ON_OPEN;
145 }
146 }
147
148 /** @hide */
Artur Satayevf0b7d0b2019-11-04 11:16:45 +0000149 @UnsupportedAppUsage
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -0600150 @TestApi
151 public void setPollForce(boolean pollForce) {
152 if (pollForce) {
153 mFlags |= FLAG_POLL_FORCE;
154 } else {
155 mFlags &= ~FLAG_POLL_FORCE;
156 }
157 }
158
159 /** @hide */
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600160 public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
161 if (augmentWithSubscriptionPlan) {
162 mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
163 } else {
164 mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
165 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000166 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800167
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900168 /** @hide */
169 public Bucket querySummaryForDevice(NetworkTemplate template,
170 long startTime, long endTime) throws SecurityException, RemoteException {
171 Bucket bucket = null;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900172 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
173 mService);
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900174 bucket = stats.getDeviceSummaryForNetwork();
175
176 stats.close();
177 return bucket;
178 }
179
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000180 /**
181 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chen25147872016-10-21 12:44:26 -0700182 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
183 * roaming. This means the bucket's start and end timestamp are going to be the same as the
184 * 'startTime' and 'endTime' parameters. State is going to be
185 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900186 * tag {@link NetworkStats.Bucket#TAG_NONE},
187 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
188 * metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800189 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000190 *
191 * @param networkType As defined in {@link ConnectivityManager}, e.g.
192 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
193 * etc.
194 * @param subscriberId If applicable, the subscriber id of the network interface.
195 * @param startTime Start of period. Defined in terms of "Unix time", see
196 * {@link java.lang.System#currentTimeMillis}.
197 * @param endTime End of period. Defined in terms of "Unix time", see
198 * {@link java.lang.System#currentTimeMillis}.
199 * @return Bucket object or null if permissions are insufficient or error happened during
200 * statistics collection.
201 */
202 public Bucket querySummaryForDevice(int networkType, String subscriberId,
203 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700204 NetworkTemplate template;
205 try {
206 template = createTemplate(networkType, subscriberId);
207 } catch (IllegalArgumentException e) {
208 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000209 return null;
210 }
211
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900212 return querySummaryForDevice(template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000213 }
214
215 /**
216 * Query network usage statistics summaries. Result is summarised data usage for all uids
217 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100218 * 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 -0700219 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
220 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
221 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
222 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000223 *
224 * @param networkType As defined in {@link ConnectivityManager}, e.g.
225 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
226 * etc.
227 * @param subscriberId If applicable, the subscriber id of the network interface.
228 * @param startTime Start of period. Defined in terms of "Unix time", see
229 * {@link java.lang.System#currentTimeMillis}.
230 * @param endTime End of period. Defined in terms of "Unix time", see
231 * {@link java.lang.System#currentTimeMillis}.
232 * @return Bucket object or null if permissions are insufficient or error happened during
233 * statistics collection.
234 */
235 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700236 long endTime) throws SecurityException, RemoteException {
237 NetworkTemplate template;
238 try {
239 template = createTemplate(networkType, subscriberId);
240 } catch (IllegalArgumentException e) {
241 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000242 return null;
243 }
244
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100245 NetworkStats stats;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900246 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700247 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000248
249 stats.close();
250 return stats.getSummaryAggregate();
251 }
252
253 /**
254 * Query network usage statistics summaries. Result filtered to include only uids belonging to
255 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900256 * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
257 * means buckets' start and end timestamps are going to be the same as the 'startTime' and
258 * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
259 * be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000260 *
261 * @param networkType As defined in {@link ConnectivityManager}, e.g.
262 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
263 * etc.
264 * @param subscriberId If applicable, the subscriber id of the network interface.
265 * @param startTime Start of period. Defined in terms of "Unix time", see
266 * {@link java.lang.System#currentTimeMillis}.
267 * @param endTime End of period. Defined in terms of "Unix time", see
268 * {@link java.lang.System#currentTimeMillis}.
269 * @return Statistics object or null if permissions are insufficient or error happened during
270 * statistics collection.
271 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100272 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700273 long endTime) throws SecurityException, RemoteException {
274 NetworkTemplate template;
275 try {
276 template = createTemplate(networkType, subscriberId);
277 } catch (IllegalArgumentException e) {
278 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000279 return null;
280 }
281
Lei Yuc00a30e2019-05-09 11:53:57 -0700282 return querySummary(template, startTime, endTime);
283 }
284
285 /** @hide */
286 public NetworkStats querySummary(NetworkTemplate template, long startTime,
287 long endTime) throws SecurityException, RemoteException {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100288 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900289 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700290 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000291
292 return result;
293 }
294
295 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800296 * Query network usage statistics details for a given uid.
297 *
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900298 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
Antonio Cansado46c753672015-12-10 15:57:56 -0800299 */
300 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900301 long startTime, long endTime, int uid) throws SecurityException {
302 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
303 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
Antonio Cansado46c753672015-12-10 15:57:56 -0800304 }
305
Lei Yuc00a30e2019-05-09 11:53:57 -0700306 /** @hide */
307 public NetworkStats queryDetailsForUid(NetworkTemplate template,
308 long startTime, long endTime, int uid) throws SecurityException {
309 return queryDetailsForUidTagState(template, startTime, endTime, uid,
310 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
311 }
312
Antonio Cansado46c753672015-12-10 15:57:56 -0800313 /**
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900314 * Query network usage statistics details for a given uid and tag.
315 *
316 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
317 */
318 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
319 long startTime, long endTime, int uid, int tag) throws SecurityException {
320 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
321 tag, NetworkStats.Bucket.STATE_ALL);
322 }
323
324 /**
325 * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
326 * belonging to calling user. Result is not aggregated over time. This means buckets' start and
327 * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
328 * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
329 * the same as the 'state' parameter.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900330 * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
331 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
332 * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100333 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
334 * interpolate across partial buckets. Since bucket length is in the order of hours, this
335 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000336 *
337 * @param networkType As defined in {@link ConnectivityManager}, e.g.
338 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
339 * etc.
340 * @param subscriberId If applicable, the subscriber id of the network interface.
341 * @param startTime Start of period. Defined in terms of "Unix time", see
342 * {@link java.lang.System#currentTimeMillis}.
343 * @param endTime End of period. Defined in terms of "Unix time", see
344 * {@link java.lang.System#currentTimeMillis}.
345 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700346 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Lorenzo Colitti53765e02018-04-06 22:56:52 +0900347 * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
348 * traffic from all states.
Antonio Cansado904237f2016-05-25 09:57:21 -0700349 * @return Statistics object or null if an error happened during statistics collection.
350 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000351 */
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900352 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
353 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700354 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700355 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000356
Lei Yuc00a30e2019-05-09 11:53:57 -0700357 return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
358 }
359
360 /** @hide */
361 public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
362 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
363
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100364 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700365 try {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900366 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900367 result.startHistoryEnumeration(uid, tag, state);
Antonio Cansado6965c182016-03-30 11:37:18 -0700368 } catch (RemoteException e) {
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900369 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
370 + " state=" + state, e);
Antonio Cansado6965c182016-03-30 11:37:18 -0700371 return null;
372 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000373
374 return result;
375 }
376
377 /**
378 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chen25147872016-10-21 12:44:26 -0700379 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
380 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
381 * 'startTime' and 'endTime' parameters. State is going to be
382 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900383 * tag {@link NetworkStats.Bucket#TAG_NONE},
384 * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
385 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
386 * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100387 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
388 * interpolate across partial buckets. Since bucket length is in the order of hours, this
389 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000390 *
391 * @param networkType As defined in {@link ConnectivityManager}, e.g.
392 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
393 * etc.
394 * @param subscriberId If applicable, the subscriber id of the network interface.
395 * @param startTime Start of period. Defined in terms of "Unix time", see
396 * {@link java.lang.System#currentTimeMillis}.
397 * @param endTime End of period. Defined in terms of "Unix time", see
398 * {@link java.lang.System#currentTimeMillis}.
399 * @return Statistics object or null if permissions are insufficient or error happened during
400 * statistics collection.
401 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100402 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000403 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700404 NetworkTemplate template;
405 try {
406 template = createTemplate(networkType, subscriberId);
407 } catch (IllegalArgumentException e) {
408 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000409 return null;
410 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700411
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100412 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900413 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000414 result.startUserUidEnumeration();
415 return result;
416 }
417
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900418 /** @hide */
419 public void registerUsageCallback(NetworkTemplate template, int networkType,
420 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
Daulet Zhanguzin0af97d62019-12-30 15:41:28 +0000421 Objects.requireNonNull(callback, "UsageCallback cannot be null");
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900422
423 final Looper looper;
424 if (handler == null) {
425 looper = Looper.myLooper();
426 } else {
427 looper = handler.getLooper();
428 }
429
430 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
431 template, thresholdBytes);
432 try {
433 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
434 template.getSubscriberId(), callback);
435 callback.request = mService.registerUsageCallback(
436 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
437 new Binder());
438 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
439
440 if (callback.request == null) {
441 Log.e(TAG, "Request from callback is null; should not happen");
442 }
443 } catch (RemoteException e) {
444 if (DBG) Log.d(TAG, "Remote exception when registering callback");
445 throw e.rethrowFromSystemServer();
446 }
447 }
448
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800449 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700450 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800451 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700452 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800453 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700454 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
455 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700456 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
457 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800458 }
459
460 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700461 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800462 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700463 * <p>The callbacks will continue to be called as long as the process is live or
464 * {@link #unregisterUsageCallback} is called.
465 *
466 * @param networkType Type of network to monitor. Either
467 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
468 * @param subscriberId If applicable, the subscriber id of the network interface.
469 * @param thresholdBytes Threshold in bytes to be notified on.
470 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800471 * has exceeded the specified threshold.
472 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
473 * the calling thread.
474 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700475 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
476 UsageCallback callback, @Nullable Handler handler) {
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900477 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansado6965c182016-03-30 11:37:18 -0700478 if (DBG) {
479 Log.d(TAG, "registerUsageCallback called with: {"
480 + " networkType=" + networkType
481 + " subscriberId=" + subscriberId
482 + " thresholdBytes=" + thresholdBytes
483 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800484 }
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900485 registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800486 }
487
488 /**
489 * Unregisters callbacks on data usage.
490 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700491 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800492 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700493 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800494 if (callback == null || callback.request == null
495 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700496 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800497 }
498 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700499 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800500 } catch (RemoteException e) {
501 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700502 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800503 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800504 }
505
Antonio Cansado6965c182016-03-30 11:37:18 -0700506 /**
507 * Base class for usage callbacks. Should be extended by applications wanting notifications.
508 */
509 public static abstract class UsageCallback {
510
511 /**
512 * Called when data usage has reached the given threshold.
513 */
514 public abstract void onThresholdReached(int networkType, String subscriberId);
515
516 /**
517 * @hide used for internal bookkeeping
518 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800519 private DataUsageRequest request;
520 }
521
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000522 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900523 final NetworkTemplate template;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000524 switch (networkType) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900525 case ConnectivityManager.TYPE_MOBILE:
526 template = subscriberId == null
527 ? NetworkTemplate.buildTemplateMobileWildcard()
528 : NetworkTemplate.buildTemplateMobileAll(subscriberId);
529 break;
530 case ConnectivityManager.TYPE_WIFI:
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000531 template = NetworkTemplate.buildTemplateWifiWildcard();
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900532 break;
533 default:
Antonio Cansado6965c182016-03-30 11:37:18 -0700534 throw new IllegalArgumentException("Cannot create template for network type "
535 + networkType + ", subscriberId '"
536 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000537 }
538 return template;
539 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800540
541 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700542 private final int mNetworkType;
543 private final String mSubscriberId;
544 private UsageCallback mCallback;
545
546 CallbackHandler(Looper looper, int networkType, String subscriberId,
547 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800548 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700549 mNetworkType = networkType;
550 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800551 mCallback = callback;
552 }
553
554 @Override
555 public void handleMessage(Message message) {
556 DataUsageRequest request =
557 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
558
559 switch (message.what) {
560 case CALLBACK_LIMIT_REACHED: {
561 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700562 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800563 } else {
564 Log.e(TAG, "limit reached with released callback for " + request);
565 }
566 break;
567 }
568 case CALLBACK_RELEASED: {
569 if (DBG) Log.d(TAG, "callback released for " + request);
570 mCallback = null;
571 break;
572 }
573 }
574 }
575
576 private static Object getObject(Message msg, String key) {
577 return msg.getData().getParcelable(key);
578 }
579 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000580}