blob: fc8248e1012af07b12e9f2e893fb93cc3cb9292a [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
junyulai80831d22019-11-21 16:26:27 +080019import android.annotation.NonNull;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080020import android.annotation.Nullable;
junyulai80831d22019-11-21 16:26:27 +080021import android.annotation.RequiresPermission;
22import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060023import android.annotation.SystemService;
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -060024import android.annotation.TestApi;
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010025import android.app.usage.NetworkStats.Bucket;
Artur Satayevd9b11b02019-12-10 17:47:51 +000026import android.compat.annotation.UnsupportedAppUsage;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000027import android.content.Context;
28import android.net.ConnectivityManager;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080029import android.net.DataUsageRequest;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060030import android.net.INetworkStatsService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000031import android.net.NetworkIdentity;
Automerger Merge Workeraf8d85f2020-03-12 09:46:48 +000032import android.net.NetworkStack;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000033import android.net.NetworkTemplate;
junyulaiea8f185b2020-03-06 14:50:48 +080034import android.net.netstats.provider.INetworkStatsProviderCallback;
35import android.net.netstats.provider.NetworkStatsProvider;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080036import android.os.Binder;
Antonio Cansadoba8288d2015-12-02 08:42:54 -080037import android.os.Handler;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080038import android.os.Looper;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060039import android.os.Message;
40import android.os.Messenger;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000041import android.os.RemoteException;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080042import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060043import android.os.ServiceManager.ServiceNotFoundException;
Michael Grooverf4f6a7a2020-06-19 19:48:07 -070044import android.telephony.TelephonyManager;
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +090045import android.util.DataUnit;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000046import android.util.Log;
47
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +090048import com.android.internal.annotations.VisibleForTesting;
49
junyulai232b2ed2020-01-13 14:36:55 +080050import java.util.Objects;
51
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000052/**
53 * Provides access to network usage history and statistics. Usage data is collected in
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010054 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000055 * <p />
56 * 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 -080057 * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
58 * data about themselves. See the below note for special cases in which apps can obtain data about
59 * other applications.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000060 * <h3>
61 * Summary queries
62 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010063 * {@link #querySummaryForDevice} <p />
64 * {@link #querySummaryForUser} <p />
65 * {@link #querySummary} <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000066 * These queries aggregate network usage across the whole interval. Therefore there will be only one
Stephen Chen25147872016-10-21 12:44:26 -070067 * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
68 * and device-wide summaries a single bucket containing the totalised network usage is returned.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000069 * <h3>
70 * History queries
71 * </h3>
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +010072 * {@link #queryDetailsForUid} <p />
73 * {@link #queryDetails} <p />
Stephen Chen25147872016-10-21 12:44:26 -070074 * These queries do not aggregate over time but do aggregate over state, metered and roaming.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +090075 * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
76 * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
77 * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
78 * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
79 * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000080 * <p />
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000081 * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
82 * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
83 * which is a system-level permission and will not be granted to third-party apps. However,
84 * declaring the permission implies intention to use the API and the user of the device can grant
85 * permission through the Settings application.
86 * <p />
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000087 * Profile owner apps are automatically granted permission to query data on the profile they manage
Jeff Davidson1efb1332015-12-09 18:04:50 -080088 * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
89 * privileged apps likewise get access to usage data for all users on the device.
90 * <p />
91 * In addition to tethering usage, usage by removed users and apps, and usage by the system
92 * is also included in the results for callers with one of these higher levels of access.
93 * <p />
Jeff Sharkeyf4de2942017-08-29 15:32:13 -060094 * <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 -080095 * the above permission, even to access an app's own data usage, and carrier-privileged apps were
96 * not included.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000097 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060098@SystemService(Context.NETWORK_STATS_SERVICE)
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +000099public class NetworkStatsManager {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800100 private static final String TAG = "NetworkStatsManager";
101 private static final boolean DBG = false;
102
103 /** @hide */
104 public static final int CALLBACK_LIMIT_REACHED = 0;
105 /** @hide */
106 public static final int CALLBACK_RELEASED = 1;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000107
Remi NGUYEN VANd06a9002018-04-04 14:51:26 +0900108 /**
109 * Minimum data usage threshold for registering usage callbacks.
110 *
111 * Requests registered with a threshold lower than this will only be triggered once this minimum
112 * is reached.
113 * @hide
114 */
115 public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
116
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000117 private final Context mContext;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800118 private final INetworkStatsService mService;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000119
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600120 /** @hide */
121 public static final int FLAG_POLL_ON_OPEN = 1 << 0;
122 /** @hide */
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -0600123 public static final int FLAG_POLL_FORCE = 1 << 1;
124 /** @hide */
125 public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600126
127 private int mFlags;
128
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000129 /**
130 * {@hide}
131 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100132 @UnsupportedAppUsage
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600133 public NetworkStatsManager(Context context) throws ServiceNotFoundException {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900134 this(context, INetworkStatsService.Stub.asInterface(
135 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
136 }
137
138 /** @hide */
139 @VisibleForTesting
140 public NetworkStatsManager(Context context, INetworkStatsService service) {
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000141 mContext = context;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900142 mService = service;
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600143 setPollOnOpen(true);
144 }
145
146 /** @hide */
147 public void setPollOnOpen(boolean pollOnOpen) {
148 if (pollOnOpen) {
149 mFlags |= FLAG_POLL_ON_OPEN;
150 } else {
151 mFlags &= ~FLAG_POLL_ON_OPEN;
152 }
153 }
154
155 /** @hide */
Artur Satayev5a525852019-10-31 15:15:50 +0000156 @UnsupportedAppUsage
Jeff Sharkeyc3c8d162018-04-20 10:59:09 -0600157 @TestApi
158 public void setPollForce(boolean pollForce) {
159 if (pollForce) {
160 mFlags |= FLAG_POLL_FORCE;
161 } else {
162 mFlags &= ~FLAG_POLL_FORCE;
163 }
164 }
165
166 /** @hide */
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600167 public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
168 if (augmentWithSubscriptionPlan) {
169 mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
170 } else {
171 mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
172 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000173 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800174
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900175 /** @hide */
176 public Bucket querySummaryForDevice(NetworkTemplate template,
177 long startTime, long endTime) throws SecurityException, RemoteException {
178 Bucket bucket = null;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900179 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
180 mService);
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900181 bucket = stats.getDeviceSummaryForNetwork();
182
183 stats.close();
184 return bucket;
185 }
186
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000187 /**
188 * Query network usage statistics summaries. Result is summarised data usage for the whole
Stephen Chen25147872016-10-21 12:44:26 -0700189 * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
190 * roaming. This means the bucket's start and end timestamp are going to be the same as the
191 * 'startTime' and 'endTime' parameters. State is going to be
192 * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900193 * tag {@link NetworkStats.Bucket#TAG_NONE},
194 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
195 * metered {@link NetworkStats.Bucket#METERED_ALL},
Antonio Cansado46c753672015-12-10 15:57:56 -0800196 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000197 *
198 * @param networkType As defined in {@link ConnectivityManager}, e.g.
199 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
200 * etc.
201 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700202 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
203 * additional restrictions. Calling apps that do not meet the new
204 * requirements to access the {@code subscriberId} can provide a {@code
205 * null} value when querying for the mobile network type to receive usage
206 * for all mobile networks. For additional details see {@link
207 * TelephonyManager#getSubscriberId()}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000208 * @param startTime Start of period. Defined in terms of "Unix time", see
209 * {@link java.lang.System#currentTimeMillis}.
210 * @param endTime End of period. Defined in terms of "Unix time", see
211 * {@link java.lang.System#currentTimeMillis}.
212 * @return Bucket object or null if permissions are insufficient or error happened during
213 * statistics collection.
214 */
215 public Bucket querySummaryForDevice(int networkType, String subscriberId,
216 long startTime, long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700217 NetworkTemplate template;
218 try {
219 template = createTemplate(networkType, subscriberId);
220 } catch (IllegalArgumentException e) {
221 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000222 return null;
223 }
224
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900225 return querySummaryForDevice(template, startTime, endTime);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000226 }
227
228 /**
229 * Query network usage statistics summaries. Result is summarised data usage for all uids
230 * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100231 * 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 -0700232 * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
233 * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
234 * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
235 * {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000236 *
237 * @param networkType As defined in {@link ConnectivityManager}, e.g.
238 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
239 * etc.
240 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700241 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
242 * additional restrictions. Calling apps that do not meet the new
243 * requirements to access the {@code subscriberId} can provide a {@code
244 * null} value when querying for the mobile network type to receive usage
245 * for all mobile networks. For additional details see {@link
246 * TelephonyManager#getSubscriberId()}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000247 * @param startTime Start of period. Defined in terms of "Unix time", see
248 * {@link java.lang.System#currentTimeMillis}.
249 * @param endTime End of period. Defined in terms of "Unix time", see
250 * {@link java.lang.System#currentTimeMillis}.
251 * @return Bucket object or null if permissions are insufficient or error happened during
252 * statistics collection.
253 */
254 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700255 long endTime) throws SecurityException, RemoteException {
256 NetworkTemplate template;
257 try {
258 template = createTemplate(networkType, subscriberId);
259 } catch (IllegalArgumentException e) {
260 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000261 return null;
262 }
263
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100264 NetworkStats stats;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900265 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700266 stats.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000267
268 stats.close();
269 return stats.getSummaryAggregate();
270 }
271
272 /**
273 * Query network usage statistics summaries. Result filtered to include only uids belonging to
274 * calling user. Result is aggregated over time, hence all buckets will have the same start and
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900275 * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
276 * means buckets' start and end timestamps are going to be the same as the 'startTime' and
277 * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
278 * be the same.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000279 *
280 * @param networkType As defined in {@link ConnectivityManager}, e.g.
281 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
282 * etc.
283 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700284 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
285 * additional restrictions. Calling apps that do not meet the new
286 * requirements to access the {@code subscriberId} can provide a {@code
287 * null} value when querying for the mobile network type to receive usage
288 * for all mobile networks. For additional details see {@link
289 * TelephonyManager#getSubscriberId()}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000290 * @param startTime Start of period. Defined in terms of "Unix time", see
291 * {@link java.lang.System#currentTimeMillis}.
292 * @param endTime End of period. Defined in terms of "Unix time", see
293 * {@link java.lang.System#currentTimeMillis}.
294 * @return Statistics object or null if permissions are insufficient or error happened during
295 * statistics collection.
296 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100297 public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
Antonio Cansado6965c182016-03-30 11:37:18 -0700298 long endTime) throws SecurityException, RemoteException {
299 NetworkTemplate template;
300 try {
301 template = createTemplate(networkType, subscriberId);
302 } catch (IllegalArgumentException e) {
303 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000304 return null;
305 }
306
Lei Yuc00a30e2019-05-09 11:53:57 -0700307 return querySummary(template, startTime, endTime);
308 }
309
310 /** @hide */
311 public NetworkStats querySummary(NetworkTemplate template, long startTime,
312 long endTime) throws SecurityException, RemoteException {
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100313 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900314 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Antonio Cansado6965c182016-03-30 11:37:18 -0700315 result.startSummaryEnumeration();
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000316
317 return result;
318 }
319
320 /**
Antonio Cansado46c753672015-12-10 15:57:56 -0800321 * Query network usage statistics details for a given uid.
322 *
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700323 * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
Antonio Cansado46c753672015-12-10 15:57:56 -0800324 */
325 public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900326 long startTime, long endTime, int uid) throws SecurityException {
327 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
328 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
Antonio Cansado46c753672015-12-10 15:57:56 -0800329 }
330
Lei Yuc00a30e2019-05-09 11:53:57 -0700331 /** @hide */
332 public NetworkStats queryDetailsForUid(NetworkTemplate template,
333 long startTime, long endTime, int uid) throws SecurityException {
334 return queryDetailsForUidTagState(template, startTime, endTime, uid,
335 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
336 }
337
Antonio Cansado46c753672015-12-10 15:57:56 -0800338 /**
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900339 * Query network usage statistics details for a given uid and tag.
340 *
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700341 * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900342 */
343 public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
344 long startTime, long endTime, int uid, int tag) throws SecurityException {
345 return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
346 tag, NetworkStats.Bucket.STATE_ALL);
347 }
348
349 /**
350 * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
351 * belonging to calling user. Result is not aggregated over time. This means buckets' start and
352 * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
353 * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
354 * the same as the 'state' parameter.
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900355 * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
356 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
357 * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100358 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
359 * interpolate across partial buckets. Since bucket length is in the order of hours, this
360 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000361 *
362 * @param networkType As defined in {@link ConnectivityManager}, e.g.
363 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
364 * etc.
365 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700366 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
367 * additional restrictions. Calling apps that do not meet the new
368 * requirements to access the {@code subscriberId} can provide a {@code
369 * null} value when querying for the mobile network type to receive usage
370 * for all mobile networks. For additional details see {@link
371 * TelephonyManager#getSubscriberId()}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000372 * @param startTime Start of period. Defined in terms of "Unix time", see
373 * {@link java.lang.System#currentTimeMillis}.
374 * @param endTime End of period. Defined in terms of "Unix time", see
375 * {@link java.lang.System#currentTimeMillis}.
376 * @param uid UID of app
Antonio Cansado6965c182016-03-30 11:37:18 -0700377 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
Lorenzo Colitti53765e02018-04-06 22:56:52 +0900378 * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
379 * traffic from all states.
Antonio Cansado904237f2016-05-25 09:57:21 -0700380 * @return Statistics object or null if an error happened during statistics collection.
381 * @throws SecurityException if permissions are insufficient to read network statistics.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000382 */
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900383 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
384 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700385 NetworkTemplate template;
Antonio Cansado904237f2016-05-25 09:57:21 -0700386 template = createTemplate(networkType, subscriberId);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000387
Lei Yuc00a30e2019-05-09 11:53:57 -0700388 return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
389 }
390
391 /** @hide */
392 public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
393 long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
394
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100395 NetworkStats result;
Antonio Cansado6965c182016-03-30 11:37:18 -0700396 try {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900397 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900398 result.startHistoryEnumeration(uid, tag, state);
Antonio Cansado6965c182016-03-30 11:37:18 -0700399 } catch (RemoteException e) {
Lorenzo Colitti84b317c2018-04-02 16:48:31 +0900400 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
401 + " state=" + state, e);
Antonio Cansado6965c182016-03-30 11:37:18 -0700402 return null;
403 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000404
405 return result;
406 }
407
408 /**
409 * Query network usage statistics details. Result filtered to include only uids belonging to
Stephen Chen25147872016-10-21 12:44:26 -0700410 * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
411 * metered, nor roaming. This means buckets' start and end timestamps are going to be between
412 * 'startTime' and 'endTime' parameters. State is going to be
413 * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
Lorenzo Colitti35c13e52018-01-19 01:12:58 +0900414 * tag {@link NetworkStats.Bucket#TAG_NONE},
415 * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
416 * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
417 * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
Zoltan Szatmary-Ban72027d22015-06-16 15:49:16 +0100418 * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
419 * interpolate across partial buckets. Since bucket length is in the order of hours, this
420 * method cannot be used to measure data usage on a fine grained time scale.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000421 *
422 * @param networkType As defined in {@link ConnectivityManager}, e.g.
423 * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
424 * etc.
425 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700426 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
427 * additional restrictions. Calling apps that do not meet the new
428 * requirements to access the {@code subscriberId} can provide a {@code
429 * null} value when querying for the mobile network type to receive usage
430 * for all mobile networks. For additional details see {@link
431 * TelephonyManager#getSubscriberId()}.
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000432 * @param startTime Start of period. Defined in terms of "Unix time", see
433 * {@link java.lang.System#currentTimeMillis}.
434 * @param endTime End of period. Defined in terms of "Unix time", see
435 * {@link java.lang.System#currentTimeMillis}.
436 * @return Statistics object or null if permissions are insufficient or error happened during
437 * statistics collection.
438 */
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100439 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000440 long endTime) throws SecurityException, RemoteException {
Antonio Cansado6965c182016-03-30 11:37:18 -0700441 NetworkTemplate template;
442 try {
443 template = createTemplate(networkType, subscriberId);
444 } catch (IllegalArgumentException e) {
445 if (DBG) Log.e(TAG, "Cannot create template", e);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000446 return null;
447 }
Antonio Cansado6965c182016-03-30 11:37:18 -0700448
Zoltan Szatmary-Ban381483b2015-05-13 17:53:17 +0100449 NetworkStats result;
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900450 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000451 result.startUserUidEnumeration();
452 return result;
453 }
454
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900455 /** @hide */
456 public void registerUsageCallback(NetworkTemplate template, int networkType,
457 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
junyulai232b2ed2020-01-13 14:36:55 +0800458 Objects.requireNonNull(callback, "UsageCallback cannot be null");
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900459
460 final Looper looper;
461 if (handler == null) {
462 looper = Looper.myLooper();
463 } else {
464 looper = handler.getLooper();
465 }
466
467 DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
468 template, thresholdBytes);
469 try {
470 CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
471 template.getSubscriberId(), callback);
472 callback.request = mService.registerUsageCallback(
473 mContext.getOpPackageName(), request, new Messenger(callbackHandler),
474 new Binder());
475 if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
476
477 if (callback.request == null) {
478 Log.e(TAG, "Request from callback is null; should not happen");
479 }
480 } catch (RemoteException e) {
481 if (DBG) Log.d(TAG, "Remote exception when registering callback");
482 throw e.rethrowFromSystemServer();
483 }
484 }
485
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800486 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700487 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800488 *
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700489 * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800490 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700491 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
492 UsageCallback callback) {
Antonio Cansadof7048372016-06-20 15:03:03 -0700493 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
494 null /* handler */);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800495 }
496
497 /**
Antonio Cansado6965c182016-03-30 11:37:18 -0700498 * Registers to receive notifications about data usage on specified networks.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800499 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700500 * <p>The callbacks will continue to be called as long as the process is live or
501 * {@link #unregisterUsageCallback} is called.
502 *
503 * @param networkType Type of network to monitor. Either
504 {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
505 * @param subscriberId If applicable, the subscriber id of the network interface.
Michael Grooverf4f6a7a2020-06-19 19:48:07 -0700506 * <p>Starting with API level 29, the {@code subscriberId} is guarded by
507 * additional restrictions. Calling apps that do not meet the new
508 * requirements to access the {@code subscriberId} can provide a {@code
509 * null} value when registering for the mobile network type to receive
510 * notifications for all mobile networks. For additional details see {@link
511 * TelephonyManager#getSubscriberId()}.
Antonio Cansado6965c182016-03-30 11:37:18 -0700512 * @param thresholdBytes Threshold in bytes to be notified on.
513 * @param callback The {@link UsageCallback} that the system will call when data usage
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800514 * has exceeded the specified threshold.
515 * @param handler to dispatch callback events through, otherwise if {@code null} it uses
516 * the calling thread.
517 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700518 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
519 UsageCallback callback, @Nullable Handler handler) {
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900520 NetworkTemplate template = createTemplate(networkType, subscriberId);
Antonio Cansado6965c182016-03-30 11:37:18 -0700521 if (DBG) {
522 Log.d(TAG, "registerUsageCallback called with: {"
523 + " networkType=" + networkType
524 + " subscriberId=" + subscriberId
525 + " thresholdBytes=" + thresholdBytes
526 + " }");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800527 }
Lorenzo Colittie0f69092018-01-22 21:00:49 +0900528 registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800529 }
530
531 /**
532 * Unregisters callbacks on data usage.
533 *
Antonio Cansado6965c182016-03-30 11:37:18 -0700534 * @param callback The {@link UsageCallback} used when registering.
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800535 */
Antonio Cansado6965c182016-03-30 11:37:18 -0700536 public void unregisterUsageCallback(UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800537 if (callback == null || callback.request == null
538 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700539 throw new IllegalArgumentException("Invalid UsageCallback");
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800540 }
541 try {
Antonio Cansado6965c182016-03-30 11:37:18 -0700542 mService.unregisterUsageRequest(callback.request);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800543 } catch (RemoteException e) {
544 if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
Antonio Cansado6965c182016-03-30 11:37:18 -0700545 throw e.rethrowFromSystemServer();
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800546 }
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800547 }
548
Antonio Cansado6965c182016-03-30 11:37:18 -0700549 /**
550 * Base class for usage callbacks. Should be extended by applications wanting notifications.
551 */
552 public static abstract class UsageCallback {
553
554 /**
555 * Called when data usage has reached the given threshold.
556 */
557 public abstract void onThresholdReached(int networkType, String subscriberId);
558
559 /**
560 * @hide used for internal bookkeeping
561 */
Antonio Cansadoba8288d2015-12-02 08:42:54 -0800562 private DataUsageRequest request;
563 }
564
junyulai80831d22019-11-21 16:26:27 +0800565 /**
junyulai7d058ec2020-01-21 13:52:04 +0800566 * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
junyulaiea8f185b2020-03-06 14:50:48 +0800567 * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
junyulai7d058ec2020-01-21 13:52:04 +0800568 * Note that no de-duplication of statistics between providers is performed, so each provider
junyulaiea8f185b2020-03-06 14:50:48 +0800569 * must only report network traffic that is not being reported by any other provider. Also note
570 * that the provider cannot be re-registered after unregistering.
junyulai80831d22019-11-21 16:26:27 +0800571 *
junyulai7d058ec2020-01-21 13:52:04 +0800572 * @param tag a human readable identifier of the custom network stats provider. This is only
573 * used for debugging.
junyulaiea8f185b2020-03-06 14:50:48 +0800574 * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
junyulai7d058ec2020-01-21 13:52:04 +0800575 * registered to the system.
junyulai80831d22019-11-21 16:26:27 +0800576 * @hide
577 */
578 @SystemApi
Automerger Merge Workeraf8d85f2020-03-12 09:46:48 +0000579 @RequiresPermission(anyOf = {
580 android.Manifest.permission.NETWORK_STATS_PROVIDER,
581 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
junyulaiea8f185b2020-03-06 14:50:48 +0800582 @NonNull public void registerNetworkStatsProvider(
junyulai80831d22019-11-21 16:26:27 +0800583 @NonNull String tag,
junyulaiea8f185b2020-03-06 14:50:48 +0800584 @NonNull NetworkStatsProvider provider) {
junyulai80831d22019-11-21 16:26:27 +0800585 try {
junyulaiea8f185b2020-03-06 14:50:48 +0800586 if (provider.getProviderCallbackBinder() != null) {
587 throw new IllegalArgumentException("provider is already registered");
588 }
589 final INetworkStatsProviderCallback cbBinder =
590 mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
591 provider.setProviderCallbackBinder(cbBinder);
junyulai80831d22019-11-21 16:26:27 +0800592 } catch (RemoteException e) {
593 e.rethrowAsRuntimeException();
594 }
junyulaiea8f185b2020-03-06 14:50:48 +0800595 }
596
597 /**
598 * Unregisters an instance of {@link NetworkStatsProvider}.
599 *
600 * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
601 * unregistered to the system.
602 * @hide
603 */
604 @SystemApi
605 @RequiresPermission(anyOf = {
606 android.Manifest.permission.NETWORK_STATS_PROVIDER,
607 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
608 @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
609 try {
610 provider.getProviderCallbackBinderOrThrow().unregister();
611 } catch (RemoteException e) {
612 e.rethrowAsRuntimeException();
613 }
junyulai80831d22019-11-21 16:26:27 +0800614 }
615
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000616 private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900617 final NetworkTemplate template;
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000618 switch (networkType) {
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900619 case ConnectivityManager.TYPE_MOBILE:
620 template = subscriberId == null
621 ? NetworkTemplate.buildTemplateMobileWildcard()
622 : NetworkTemplate.buildTemplateMobileAll(subscriberId);
623 break;
624 case ConnectivityManager.TYPE_WIFI:
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000625 template = NetworkTemplate.buildTemplateWifiWildcard();
Remi NGUYEN VAN786b7ad2018-03-05 18:14:56 +0900626 break;
627 default:
Antonio Cansado6965c182016-03-30 11:37:18 -0700628 throw new IllegalArgumentException("Cannot create template for network type "
629 + networkType + ", subscriberId '"
630 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000631 }
632 return template;
633 }
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800634
635 private static class CallbackHandler extends Handler {
Antonio Cansado6965c182016-03-30 11:37:18 -0700636 private final int mNetworkType;
637 private final String mSubscriberId;
638 private UsageCallback mCallback;
639
640 CallbackHandler(Looper looper, int networkType, String subscriberId,
641 UsageCallback callback) {
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800642 super(looper);
Antonio Cansado6965c182016-03-30 11:37:18 -0700643 mNetworkType = networkType;
644 mSubscriberId = subscriberId;
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800645 mCallback = callback;
646 }
647
648 @Override
649 public void handleMessage(Message message) {
650 DataUsageRequest request =
651 (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
652
653 switch (message.what) {
654 case CALLBACK_LIMIT_REACHED: {
655 if (mCallback != null) {
Antonio Cansado6965c182016-03-30 11:37:18 -0700656 mCallback.onThresholdReached(mNetworkType, mSubscriberId);
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800657 } else {
658 Log.e(TAG, "limit reached with released callback for " + request);
659 }
660 break;
661 }
662 case CALLBACK_RELEASED: {
663 if (DBG) Log.d(TAG, "callback released for " + request);
664 mCallback = null;
665 break;
666 }
667 }
668 }
669
670 private static Object getObject(Message msg, String key) {
671 return msg.getData().getParcelable(key);
672 }
673 }
Zoltan Szatmary-Ban9c5dfa52015-02-23 17:20:20 +0000674}