blob: 8e40449fa5469714afa08256dd4f3d193322ab62 [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;
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -060023import android.annotation.TestApi;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010024import android.annotation.UnsupportedAppUsage;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010025import android.app.usage.NetworkStats.Bucket;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000026import android.content.Context;
27import android.net.ConnectivityManager;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080028import android.net.DataUsageRequest;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060029import android.net.INetworkStatsService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000030import android.net.NetworkIdentity;
31import android.net.NetworkTemplate;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080032import android.os.Binder;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080033import android.os.Handler;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080034import android.os.Looper;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060035import android.os.Message;
36import android.os.Messenger;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000037import android.os.RemoteException;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080038import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060039import android.os.ServiceManager.ServiceNotFoundException;
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +090040import android.util.DataUnit;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000041import android.util.Log;
42
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +090043import com.android.internal.annotations.VisibleForTesting;
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 */
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -0600149 @TestApi
150 public void setPollForce(boolean pollForce) {
151 if (pollForce) {
152 mFlags |= FLAG_POLL_FORCE;
153 } else {
154 mFlags &= ~FLAG_POLL_FORCE;
155 }
156 }
157
158 /** @hide */
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600159 public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
160 if (augmentWithSubscriptionPlan) {
161 mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
162 } else {
163 mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
164 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000165 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800166
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900167 /** @hide */
168 public Bucket querySummaryForDevice(NetworkTemplate template,
169 long startTime, long endTime) throws SecurityException, RemoteException {
170 Bucket bucket = null;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900171 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
172 mService);
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900173 bucket = stats.getDeviceSummaryForNetwork();
174
175 stats.close();
176 return bucket;
177 }
178
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000179 /**
180 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chen25147872016-10-21 12:44:26 -0700181 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
182 * roaming. This means the bucket's start and end timestamp are going to be the same as the
183 * 'startTime' and 'endTime' parameters. State is going to be
184 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900185 * tag {@link NetworkStats.Bucket#TAG_NONE},
186 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
187 * metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800188 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000189 *
190 * @param networkType As defined in {@link ConnectivityManager}, e.g.
191 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
192 * etc.
193 * @param subscriberId If applicable, the subscriber id of the network interface.
194 * @param startTime Start of period. Defined in terms of "Unix time", see
195 * {@link java.lang.System#currentTimeMillis}.
196 * @param endTime End of period. Defined in terms of "Unix time", see
197 * {@link java.lang.System#currentTimeMillis}.
198 * @return Bucket object or null if permissions are insufficient or error happened during
199 * statistics collection.
200 */
201 public Bucket querySummaryForDevice(int networkType, String subscriberId,
202 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700203 NetworkTemplate template;
204 try {
205 template = createTemplate(networkType, subscriberId);
206 } catch (IllegalArgumentException e) {
207 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000208 return null;
209 }
210
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900211 return querySummaryForDevice(template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000212 }
213
214 /**
215 * Query network usage statistics summaries. Result is summarised data usage for all uids
216 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100217 * 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 -0700218 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
219 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
220 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
221 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000222 *
223 * @param networkType As defined in {@link ConnectivityManager}, e.g.
224 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
225 * etc.
226 * @param subscriberId If applicable, the subscriber id of the network interface.
227 * @param startTime Start of period. Defined in terms of "Unix time", see
228 * {@link java.lang.System#currentTimeMillis}.
229 * @param endTime End of period. Defined in terms of "Unix time", see
230 * {@link java.lang.System#currentTimeMillis}.
231 * @return Bucket object or null if permissions are insufficient or error happened during
232 * statistics collection.
233 */
234 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700235 long endTime) throws SecurityException, RemoteException {
236 NetworkTemplate template;
237 try {
238 template = createTemplate(networkType, subscriberId);
239 } catch (IllegalArgumentException e) {
240 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000241 return null;
242 }
243
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100244 NetworkStats stats;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900245 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700246 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000247
248 stats.close();
249 return stats.getSummaryAggregate();
250 }
251
252 /**
253 * Query network usage statistics summaries. Result filtered to include only uids belonging to
254 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900255 * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
256 * means buckets' start and end timestamps are going to be the same as the 'startTime' and
257 * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
258 * be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000259 *
260 * @param networkType As defined in {@link ConnectivityManager}, e.g.
261 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
262 * etc.
263 * @param subscriberId If applicable, the subscriber id of the network interface.
264 * @param startTime Start of period. Defined in terms of "Unix time", see
265 * {@link java.lang.System#currentTimeMillis}.
266 * @param endTime End of period. Defined in terms of "Unix time", see
267 * {@link java.lang.System#currentTimeMillis}.
268 * @return Statistics object or null if permissions are insufficient or error happened during
269 * statistics collection.
270 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100271 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700272 long endTime) throws SecurityException, RemoteException {
273 NetworkTemplate template;
274 try {
275 template = createTemplate(networkType, subscriberId);
276 } catch (IllegalArgumentException e) {
277 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000278 return null;
279 }
280
Lei Yuc00a30e2019-05-09 11:53:57 -0700281 return querySummary(template, startTime, endTime);
282 }
283
284 /** @hide */
285 public NetworkStats querySummary(NetworkTemplate template, long startTime,
286 long endTime) throws SecurityException, RemoteException {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100287 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900288 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700289 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000290
291 return result;
292 }
293
294 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800295 * Query network usage statistics details for a given uid.
296 *
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900297 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
Antonio Cansado46c753672015-12-10 15:57:56 -0800298 */
299 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900300 long startTime, long endTime, int uid) throws SecurityException {
301 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
302 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
Antonio Cansado46c753672015-12-10 15:57:56 -0800303 }
304
Lei Yuc00a30e2019-05-09 11:53:57 -0700305 /** @hide */
306 public NetworkStats queryDetailsForUid(NetworkTemplate template,
307 long startTime, long endTime, int uid) throws SecurityException {
308 return queryDetailsForUidTagState(template, startTime, endTime, uid,
309 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
310 }
311
Antonio Cansado46c753672015-12-10 15:57:56 -0800312 /**
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900313 * Query network usage statistics details for a given uid and tag.
314 *
315 * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
316 */
317 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
318 long startTime, long endTime, int uid, int tag) throws SecurityException {
319 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
320 tag, NetworkStats.Bucket.STATE_ALL);
321 }
322
323 /**
324 * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
325 * belonging to calling user. Result is not aggregated over time. This means buckets' start and
326 * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
327 * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
328 * the same as the 'state' parameter.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900329 * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
330 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
331 * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100332 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
333 * interpolate across partial buckets. Since bucket length is in the order of hours, this
334 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000335 *
336 * @param networkType As defined in {@link ConnectivityManager}, e.g.
337 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
338 * etc.
339 * @param subscriberId If applicable, the subscriber id of the network interface.
340 * @param startTime Start of period. Defined in terms of "Unix time", see
341 * {@link java.lang.System#currentTimeMillis}.
342 * @param endTime End of period. Defined in terms of "Unix time", see
343 * {@link java.lang.System#currentTimeMillis}.
344 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700345 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Lorenzo Colitti53765e02018-04-06 22:56:52 +0900346 * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
347 * traffic from all states.
Antonio Cansado904237f2016-05-25 09:57:21 -0700348 * @return Statistics object or null if an error happened during statistics collection.
349 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000350 */
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900351 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
352 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700353 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700354 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000355
Lei Yuc00a30e2019-05-09 11:53:57 -0700356 return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
357 }
358
359 /** @hide */
360 public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
361 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
362
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100363 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700364 try {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900365 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900366 result.startHistoryEnumeration(uid, tag, state);
Antonio Cansado6965c182016-03-30 11:37:18 -0700367 } catch (RemoteException e) {
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900368 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
369 + " state=" + state, e);
Antonio Cansado6965c182016-03-30 11:37:18 -0700370 return null;
371 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000372
373 return result;
374 }
375
376 /**
377 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chen25147872016-10-21 12:44:26 -0700378 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
379 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
380 * 'startTime' and 'endTime' parameters. State is going to be
381 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900382 * tag {@link NetworkStats.Bucket#TAG_NONE},
383 * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
384 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
385 * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100386 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
387 * interpolate across partial buckets. Since bucket length is in the order of hours, this
388 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000389 *
390 * @param networkType As defined in {@link ConnectivityManager}, e.g.
391 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
392 * etc.
393 * @param subscriberId If applicable, the subscriber id of the network interface.
394 * @param startTime Start of period. Defined in terms of "Unix time", see
395 * {@link java.lang.System#currentTimeMillis}.
396 * @param endTime End of period. Defined in terms of "Unix time", see
397 * {@link java.lang.System#currentTimeMillis}.
398 * @return Statistics object or null if permissions are insufficient or error happened during
399 * statistics collection.
400 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100401 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000402 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700403 NetworkTemplate template;
404 try {
405 template = createTemplate(networkType, subscriberId);
406 } catch (IllegalArgumentException e) {
407 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000408 return null;
409 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700410
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100411 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900412 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000413 result.startUserUidEnumeration();
414 return result;
415 }
416
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900417 /** @hide */
418 public void registerUsageCallback(NetworkTemplate template, int networkType,
419 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
420 checkNotNull(callback, "UsageCallback cannot be null");
421
422 final Looper looper;
423 if (handler == null) {
424 looper = Looper.myLooper();
425 } else {
426 looper = handler.getLooper();
427 }
428
429 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
430 template, thresholdBytes);
431 try {
432 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
433 template.getSubscriberId(), callback);
434 callback.request = mService.registerUsageCallback(
435 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
436 new Binder());
437 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
438
439 if (callback.request == null) {
440 Log.e(TAG, "Request from callback is null; should not happen");
441 }
442 } catch (RemoteException e) {
443 if (DBG) Log.d(TAG, "Remote exception when registering callback");
444 throw e.rethrowFromSystemServer();
445 }
446 }
447
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800448 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700449 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800450 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700451 * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800452 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700453 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
454 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700455 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
456 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800457 }
458
459 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700460 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800461 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700462 * <p>The callbacks will continue to be called as long as the process is live or
463 * {@link #unregisterUsageCallback} is called.
464 *
465 * @param networkType Type of network to monitor. Either
466 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
467 * @param subscriberId If applicable, the subscriber id of the network interface.
468 * @param thresholdBytes Threshold in bytes to be notified on.
469 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800470 * has exceeded the specified threshold.
471 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
472 * the calling thread.
473 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700474 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
475 UsageCallback callback, @Nullable Handler handler) {
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900476 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansado6965c182016-03-30 11:37:18 -0700477 if (DBG) {
478 Log.d(TAG, "registerUsageCallback called with: {"
479 + " networkType=" + networkType
480 + " subscriberId=" + subscriberId
481 + " thresholdBytes=" + thresholdBytes
482 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800483 }
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900484 registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800485 }
486
487 /**
488 * Unregisters callbacks on data usage.
489 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700490 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800491 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700492 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800493 if (callback == null || callback.request == null
494 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700495 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800496 }
497 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700498 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800499 } catch (RemoteException e) {
500 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700501 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800502 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800503 }
504
Antonio Cansado6965c182016-03-30 11:37:18 -0700505 /**
506 * Base class for usage callbacks. Should be extended by applications wanting notifications.
507 */
508 public static abstract class UsageCallback {
509
510 /**
511 * Called when data usage has reached the given threshold.
512 */
513 public abstract void onThresholdReached(int networkType, String subscriberId);
514
515 /**
516 * @hide used for internal bookkeeping
517 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800518 private DataUsageRequest request;
519 }
520
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000521 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900522 final NetworkTemplate template;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000523 switch (networkType) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900524 case ConnectivityManager.TYPE_MOBILE:
525 template = subscriberId == null
526 ? NetworkTemplate.buildTemplateMobileWildcard()
527 : NetworkTemplate.buildTemplateMobileAll(subscriberId);
528 break;
529 case ConnectivityManager.TYPE_WIFI:
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000530 template = NetworkTemplate.buildTemplateWifiWildcard();
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900531 break;
532 default:
Antonio Cansado6965c182016-03-30 11:37:18 -0700533 throw new IllegalArgumentException("Cannot create template for network type "
534 + networkType + ", subscriberId '"
535 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000536 }
537 return template;
538 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800539
540 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700541 private final int mNetworkType;
542 private final String mSubscriberId;
543 private UsageCallback mCallback;
544
545 CallbackHandler(Looper looper, int networkType, String subscriberId,
546 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800547 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700548 mNetworkType = networkType;
549 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800550 mCallback = callback;
551 }
552
553 @Override
554 public void handleMessage(Message message) {
555 DataUsageRequest request =
556 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
557
558 switch (message.what) {
559 case CALLBACK_LIMIT_REACHED: {
560 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700561 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800562 } else {
563 Log.e(TAG, "limit reached with released callback for " + request);
564 }
565 break;
566 }
567 case CALLBACK_RELEASED: {
568 if (DBG) Log.d(TAG, "callback released for " + request);
569 mCallback = null;
570 break;
571 }
572 }
573 }
574
575 private static Object getObject(Message msg, String key) {
576 return msg.getData().getParcelable(key);
577 }
578 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000579}