1 /**
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 
17 package android.app.usage;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.annotation.SystemService;
26 import android.annotation.TestApi;
27 import android.annotation.WorkerThread;
28 import android.app.usage.NetworkStats.Bucket;
29 import android.compat.annotation.UnsupportedAppUsage;
30 import android.content.Context;
31 import android.net.ConnectivityManager;
32 import android.net.DataUsageRequest;
33 import android.net.INetworkStatsService;
34 import android.net.Network;
35 import android.net.NetworkStack;
36 import android.net.NetworkStateSnapshot;
37 import android.net.NetworkTemplate;
38 import android.net.UnderlyingNetworkInfo;
39 import android.net.netstats.provider.INetworkStatsProviderCallback;
40 import android.net.netstats.provider.NetworkStatsProvider;
41 import android.os.Binder;
42 import android.os.Build;
43 import android.os.Handler;
44 import android.os.Looper;
45 import android.os.Message;
46 import android.os.Messenger;
47 import android.os.RemoteException;
48 import android.os.ServiceManager;
49 import android.os.ServiceManager.ServiceNotFoundException;
50 import android.telephony.TelephonyManager;
51 import android.text.TextUtils;
52 import android.util.DataUnit;
53 import android.util.Log;
54 
55 import com.android.internal.annotations.VisibleForTesting;
56 import com.android.net.module.util.NetworkIdentityUtils;
57 
58 import java.util.List;
59 import java.util.Objects;
60 
61 /**
62  * Provides access to network usage history and statistics. Usage data is collected in
63  * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
64  * <p />
65  * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
66  * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
67  * data about themselves. See the below note for special cases in which apps can obtain data about
68  * other applications.
69  * <h3>
70  * Summary queries
71  * </h3>
72  * {@link #querySummaryForDevice} <p />
73  * {@link #querySummaryForUser} <p />
74  * {@link #querySummary} <p />
75  * These queries aggregate network usage across the whole interval. Therefore there will be only one
76  * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
77  * and device-wide summaries a single bucket containing the totalised network usage is returned.
78  * <h3>
79  * History queries
80  * </h3>
81  * {@link #queryDetailsForUid} <p />
82  * {@link #queryDetails} <p />
83  * These queries do not aggregate over time but do aggregate over state, metered and roaming.
84  * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
85  * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
86  * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
87  * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
88  * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
89  * <p />
90  * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
91  * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
92  * which is a system-level permission and will not be granted to third-party apps. However,
93  * declaring the permission implies intention to use the API and the user of the device can grant
94  * permission through the Settings application.
95  * <p />
96  * Profile owner apps are automatically granted permission to query data on the profile they manage
97  * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
98  * privileged apps likewise get access to usage data for all users on the device.
99  * <p />
100  * In addition to tethering usage, usage by removed users and apps, and usage by the system
101  * is also included in the results for callers with one of these higher levels of access.
102  * <p />
103  * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required
104  * the above permission, even to access an app's own data usage, and carrier-privileged apps were
105  * not included.
106  */
107 @SystemService(Context.NETWORK_STATS_SERVICE)
108 public class NetworkStatsManager {
109     private static final String TAG = "NetworkStatsManager";
110     private static final boolean DBG = false;
111 
112     /** @hide */
113     public static final int CALLBACK_LIMIT_REACHED = 0;
114     /** @hide */
115     public static final int CALLBACK_RELEASED = 1;
116 
117     /**
118      * Minimum data usage threshold for registering usage callbacks.
119      *
120      * Requests registered with a threshold lower than this will only be triggered once this minimum
121      * is reached.
122      * @hide
123      */
124     public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
125 
126     private final Context mContext;
127     private final INetworkStatsService mService;
128 
129     /** @hide */
130     public static final int FLAG_POLL_ON_OPEN = 1 << 0;
131     /** @hide */
132     public static final int FLAG_POLL_FORCE = 1 << 1;
133     /** @hide */
134     public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
135 
136     private int mFlags;
137 
138     /**
139      * {@hide}
140      */
141     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
NetworkStatsManager(Context context)142     public NetworkStatsManager(Context context) throws ServiceNotFoundException {
143         this(context, INetworkStatsService.Stub.asInterface(
144                 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
145     }
146 
147     /** @hide */
148     @VisibleForTesting
NetworkStatsManager(Context context, INetworkStatsService service)149     public NetworkStatsManager(Context context, INetworkStatsService service) {
150         mContext = context;
151         mService = service;
152         setPollOnOpen(true);
153     }
154 
155     /** @hide */
setPollOnOpen(boolean pollOnOpen)156     public void setPollOnOpen(boolean pollOnOpen) {
157         if (pollOnOpen) {
158             mFlags |= FLAG_POLL_ON_OPEN;
159         } else {
160             mFlags &= ~FLAG_POLL_ON_OPEN;
161         }
162     }
163 
164     /** @hide */
165     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
166     @TestApi
setPollForce(boolean pollForce)167     public void setPollForce(boolean pollForce) {
168         if (pollForce) {
169             mFlags |= FLAG_POLL_FORCE;
170         } else {
171             mFlags &= ~FLAG_POLL_FORCE;
172         }
173     }
174 
175     /** @hide */
setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan)176     public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
177         if (augmentWithSubscriptionPlan) {
178             mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
179         } else {
180             mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
181         }
182     }
183 
184     /** @hide */
querySummaryForDevice(NetworkTemplate template, long startTime, long endTime)185     public Bucket querySummaryForDevice(NetworkTemplate template,
186             long startTime, long endTime) throws SecurityException, RemoteException {
187         Bucket bucket = null;
188         NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
189                 mService);
190         bucket = stats.getDeviceSummaryForNetwork();
191 
192         stats.close();
193         return bucket;
194     }
195 
196     /**
197      * Query network usage statistics summaries. Result is summarised data usage for the whole
198      * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
199      * roaming. This means the bucket's start and end timestamp are going to be the same as the
200      * 'startTime' and 'endTime' parameters. State is going to be
201      * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
202      * tag {@link NetworkStats.Bucket#TAG_NONE},
203      * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
204      * metered {@link NetworkStats.Bucket#METERED_ALL},
205      * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
206      * This may take a long time, and apps should avoid calling this on their main thread.
207      *
208      * @param networkType As defined in {@link ConnectivityManager}, e.g.
209      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
210      *            etc.
211      * @param subscriberId If applicable, the subscriber id of the network interface.
212      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
213      *                     additional restrictions. Calling apps that do not meet the new
214      *                     requirements to access the {@code subscriberId} can provide a {@code
215      *                     null} value when querying for the mobile network type to receive usage
216      *                     for all mobile networks. For additional details see {@link
217      *                     TelephonyManager#getSubscriberId()}.
218      *                     <p>Starting with API level 31, calling apps can provide a
219      *                     {@code subscriberId} with wifi network type to receive usage for
220      *                     wifi networks which is under the given subscription if applicable.
221      *                     Otherwise, pass {@code null} when querying all wifi networks.
222      * @param startTime Start of period. Defined in terms of "Unix time", see
223      *            {@link java.lang.System#currentTimeMillis}.
224      * @param endTime End of period. Defined in terms of "Unix time", see
225      *            {@link java.lang.System#currentTimeMillis}.
226      * @return Bucket object or null if permissions are insufficient or error happened during
227      *         statistics collection.
228      */
229     @WorkerThread
querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime)230     public Bucket querySummaryForDevice(int networkType, String subscriberId,
231             long startTime, long endTime) throws SecurityException, RemoteException {
232         NetworkTemplate template;
233         try {
234             template = createTemplate(networkType, subscriberId);
235         } catch (IllegalArgumentException e) {
236             if (DBG) Log.e(TAG, "Cannot create template", e);
237             return null;
238         }
239 
240         return querySummaryForDevice(template, startTime, endTime);
241     }
242 
243     /**
244      * Query network usage statistics summaries. Result is summarised data usage for all uids
245      * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
246      * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
247      * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
248      * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
249      * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
250      * {@link NetworkStats.Bucket#ROAMING_ALL}.
251      * This may take a long time, and apps should avoid calling this on their main thread.
252      *
253      * @param networkType As defined in {@link ConnectivityManager}, e.g.
254      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
255      *            etc.
256      * @param subscriberId If applicable, the subscriber id of the network interface.
257      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
258      *                     additional restrictions. Calling apps that do not meet the new
259      *                     requirements to access the {@code subscriberId} can provide a {@code
260      *                     null} value when querying for the mobile network type to receive usage
261      *                     for all mobile networks. For additional details see {@link
262      *                     TelephonyManager#getSubscriberId()}.
263      *                     <p>Starting with API level 31, calling apps can provide a
264      *                     {@code subscriberId} with wifi network type to receive usage for
265      *                     wifi networks which is under the given subscription if applicable.
266      *                     Otherwise, pass {@code null} when querying all wifi networks.
267      * @param startTime Start of period. Defined in terms of "Unix time", see
268      *            {@link java.lang.System#currentTimeMillis}.
269      * @param endTime End of period. Defined in terms of "Unix time", see
270      *            {@link java.lang.System#currentTimeMillis}.
271      * @return Bucket object or null if permissions are insufficient or error happened during
272      *         statistics collection.
273      */
274     @WorkerThread
querySummaryForUser(int networkType, String subscriberId, long startTime, long endTime)275     public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
276             long endTime) throws SecurityException, RemoteException {
277         NetworkTemplate template;
278         try {
279             template = createTemplate(networkType, subscriberId);
280         } catch (IllegalArgumentException e) {
281             if (DBG) Log.e(TAG, "Cannot create template", e);
282             return null;
283         }
284 
285         NetworkStats stats;
286         stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
287         stats.startSummaryEnumeration();
288 
289         stats.close();
290         return stats.getSummaryAggregate();
291     }
292 
293     /**
294      * Query network usage statistics summaries. Result filtered to include only uids belonging to
295      * calling user. Result is aggregated over time, hence all buckets will have the same start and
296      * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
297      * means buckets' start and end timestamps are going to be the same as the 'startTime' and
298      * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
299      * be the same.
300      * This may take a long time, and apps should avoid calling this on their main thread.
301      *
302      * @param networkType As defined in {@link ConnectivityManager}, e.g.
303      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
304      *            etc.
305      * @param subscriberId If applicable, the subscriber id of the network interface.
306      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
307      *                     additional restrictions. Calling apps that do not meet the new
308      *                     requirements to access the {@code subscriberId} can provide a {@code
309      *                     null} value when querying for the mobile network type to receive usage
310      *                     for all mobile networks. For additional details see {@link
311      *                     TelephonyManager#getSubscriberId()}.
312      *                     <p>Starting with API level 31, calling apps can provide a
313      *                     {@code subscriberId} with wifi network type to receive usage for
314      *                     wifi networks which is under the given subscription if applicable.
315      *                     Otherwise, pass {@code null} when querying all wifi networks.
316      * @param startTime Start of period. Defined in terms of "Unix time", see
317      *            {@link java.lang.System#currentTimeMillis}.
318      * @param endTime End of period. Defined in terms of "Unix time", see
319      *            {@link java.lang.System#currentTimeMillis}.
320      * @return Statistics object or null if permissions are insufficient or error happened during
321      *         statistics collection.
322      */
323     @WorkerThread
querySummary(int networkType, String subscriberId, long startTime, long endTime)324     public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
325             long endTime) throws SecurityException, RemoteException {
326         NetworkTemplate template;
327         try {
328             template = createTemplate(networkType, subscriberId);
329         } catch (IllegalArgumentException e) {
330             if (DBG) Log.e(TAG, "Cannot create template", e);
331             return null;
332         }
333 
334         return querySummary(template, startTime, endTime);
335     }
336 
337     /** @hide */
querySummary(NetworkTemplate template, long startTime, long endTime)338     public NetworkStats querySummary(NetworkTemplate template, long startTime,
339             long endTime) throws SecurityException, RemoteException {
340         NetworkStats result;
341         result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
342         result.startSummaryEnumeration();
343 
344         return result;
345     }
346 
347     /**
348      * Query network usage statistics details for a given uid.
349      * This may take a long time, and apps should avoid calling this on their main thread.
350      *
351      * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
352      */
353     @WorkerThread
queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid)354     public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
355             long startTime, long endTime, int uid) throws SecurityException {
356         return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
357             NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
358     }
359 
360     /** @hide */
queryDetailsForUid(NetworkTemplate template, long startTime, long endTime, int uid)361     public NetworkStats queryDetailsForUid(NetworkTemplate template,
362             long startTime, long endTime, int uid) throws SecurityException {
363         return queryDetailsForUidTagState(template, startTime, endTime, uid,
364                 NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
365     }
366 
367     /**
368      * Query network usage statistics details for a given uid and tag.
369      * This may take a long time, and apps should avoid calling this on their main thread.
370      *
371      * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
372      */
373     @WorkerThread
queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag)374     public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
375             long startTime, long endTime, int uid, int tag) throws SecurityException {
376         return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
377             tag, NetworkStats.Bucket.STATE_ALL);
378     }
379 
380     /**
381      * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
382      * belonging to calling user. Result is not aggregated over time. This means buckets' start and
383      * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
384      * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
385      * the same as the 'state' parameter.
386      * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
387      * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
388      * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
389      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
390      * interpolate across partial buckets. Since bucket length is in the order of hours, this
391      * method cannot be used to measure data usage on a fine grained time scale.
392      * This may take a long time, and apps should avoid calling this on their main thread.
393      *
394      * @param networkType As defined in {@link ConnectivityManager}, e.g.
395      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
396      *            etc.
397      * @param subscriberId If applicable, the subscriber id of the network interface.
398      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
399      *                     additional restrictions. Calling apps that do not meet the new
400      *                     requirements to access the {@code subscriberId} can provide a {@code
401      *                     null} value when querying for the mobile network type to receive usage
402      *                     for all mobile networks. For additional details see {@link
403      *                     TelephonyManager#getSubscriberId()}.
404      *                     <p>Starting with API level 31, calling apps can provide a
405      *                     {@code subscriberId} with wifi network type to receive usage for
406      *                     wifi networks which is under the given subscription if applicable.
407      *                     Otherwise, pass {@code null} when querying all wifi networks.
408      * @param startTime Start of period. Defined in terms of "Unix time", see
409      *            {@link java.lang.System#currentTimeMillis}.
410      * @param endTime End of period. Defined in terms of "Unix time", see
411      *            {@link java.lang.System#currentTimeMillis}.
412      * @param uid UID of app
413      * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
414      * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
415      *            traffic from all states.
416      * @return Statistics object or null if an error happened during statistics collection.
417      * @throws SecurityException if permissions are insufficient to read network statistics.
418      */
419     @WorkerThread
queryDetailsForUidTagState(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag, int state)420     public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
421             long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
422         NetworkTemplate template;
423         template = createTemplate(networkType, subscriberId);
424 
425         return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
426     }
427 
428     /** @hide */
queryDetailsForUidTagState(NetworkTemplate template, long startTime, long endTime, int uid, int tag, int state)429     public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
430             long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
431 
432         NetworkStats result;
433         try {
434             result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
435             result.startHistoryEnumeration(uid, tag, state);
436         } catch (RemoteException e) {
437             Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
438                     + " state=" + state, e);
439             return null;
440         }
441 
442         return result;
443     }
444 
445     /**
446      * Query network usage statistics details. Result filtered to include only uids belonging to
447      * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
448      * metered, nor roaming. This means buckets' start and end timestamps are going to be between
449      * 'startTime' and 'endTime' parameters. State is going to be
450      * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
451      * tag {@link NetworkStats.Bucket#TAG_NONE},
452      * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
453      * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
454      * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
455      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
456      * interpolate across partial buckets. Since bucket length is in the order of hours, this
457      * method cannot be used to measure data usage on a fine grained time scale.
458      * This may take a long time, and apps should avoid calling this on their main thread.
459      *
460      * @param networkType As defined in {@link ConnectivityManager}, e.g.
461      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
462      *            etc.
463      * @param subscriberId If applicable, the subscriber id of the network interface.
464      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
465      *                     additional restrictions. Calling apps that do not meet the new
466      *                     requirements to access the {@code subscriberId} can provide a {@code
467      *                     null} value when querying for the mobile network type to receive usage
468      *                     for all mobile networks. For additional details see {@link
469      *                     TelephonyManager#getSubscriberId()}.
470      *                     <p>Starting with API level 31, calling apps can provide a
471      *                     {@code subscriberId} with wifi network type to receive usage for
472      *                     wifi networks which is under the given subscription if applicable.
473      *                     Otherwise, pass {@code null} when querying all wifi networks.
474      * @param startTime Start of period. Defined in terms of "Unix time", see
475      *            {@link java.lang.System#currentTimeMillis}.
476      * @param endTime End of period. Defined in terms of "Unix time", see
477      *            {@link java.lang.System#currentTimeMillis}.
478      * @return Statistics object or null if permissions are insufficient or error happened during
479      *         statistics collection.
480      */
481     @WorkerThread
queryDetails(int networkType, String subscriberId, long startTime, long endTime)482     public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
483             long endTime) throws SecurityException, RemoteException {
484         NetworkTemplate template;
485         try {
486             template = createTemplate(networkType, subscriberId);
487         } catch (IllegalArgumentException e) {
488             if (DBG) Log.e(TAG, "Cannot create template", e);
489             return null;
490         }
491 
492         NetworkStats result;
493         result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
494         result.startUserUidEnumeration();
495         return result;
496     }
497 
498     /** @hide */
registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler)499     public void registerUsageCallback(NetworkTemplate template, int networkType,
500             long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
501         Objects.requireNonNull(callback, "UsageCallback cannot be null");
502 
503         final Looper looper;
504         if (handler == null) {
505             looper = Looper.myLooper();
506         } else {
507             looper = handler.getLooper();
508         }
509 
510         DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
511                 template, thresholdBytes);
512         try {
513             CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
514                     template.getSubscriberId(), callback);
515             callback.request = mService.registerUsageCallback(
516                     mContext.getOpPackageName(), request, new Messenger(callbackHandler),
517                     new Binder());
518             if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
519 
520             if (callback.request == null) {
521                 Log.e(TAG, "Request from callback is null; should not happen");
522             }
523         } catch (RemoteException e) {
524             if (DBG) Log.d(TAG, "Remote exception when registering callback");
525             throw e.rethrowFromSystemServer();
526         }
527     }
528 
529     /**
530      * Registers to receive notifications about data usage on specified networks.
531      *
532      * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
533      */
registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback)534     public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
535             UsageCallback callback) {
536         registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
537                 null /* handler */);
538     }
539 
540     /**
541      * Registers to receive notifications about data usage on specified networks.
542      *
543      * <p>The callbacks will continue to be called as long as the process is live or
544      * {@link #unregisterUsageCallback} is called.
545      *
546      * @param networkType Type of network to monitor. Either
547                   {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
548      * @param subscriberId If applicable, the subscriber id of the network interface.
549      *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
550      *                     additional restrictions. Calling apps that do not meet the new
551      *                     requirements to access the {@code subscriberId} can provide a {@code
552      *                     null} value when registering for the mobile network type to receive
553      *                     notifications for all mobile networks. For additional details see {@link
554      *                     TelephonyManager#getSubscriberId()}.
555      *                     <p>Starting with API level 31, calling apps can provide a
556      *                     {@code subscriberId} with wifi network type to receive usage for
557      *                     wifi networks which is under the given subscription if applicable.
558      *                     Otherwise, pass {@code null} when querying all wifi networks.
559      * @param thresholdBytes Threshold in bytes to be notified on.
560      * @param callback The {@link UsageCallback} that the system will call when data usage
561      *            has exceeded the specified threshold.
562      * @param handler to dispatch callback events through, otherwise if {@code null} it uses
563      *            the calling thread.
564      */
registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback, @Nullable Handler handler)565     public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
566             UsageCallback callback, @Nullable Handler handler) {
567         NetworkTemplate template = createTemplate(networkType, subscriberId);
568         if (DBG) {
569             Log.d(TAG, "registerUsageCallback called with: {"
570                 + " networkType=" + networkType
571                 + " subscriberId=" + subscriberId
572                 + " thresholdBytes=" + thresholdBytes
573                 + " }");
574         }
575         registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
576     }
577 
578     /**
579      * Unregisters callbacks on data usage.
580      *
581      * @param callback The {@link UsageCallback} used when registering.
582      */
unregisterUsageCallback(UsageCallback callback)583     public void unregisterUsageCallback(UsageCallback callback) {
584         if (callback == null || callback.request == null
585                 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
586             throw new IllegalArgumentException("Invalid UsageCallback");
587         }
588         try {
589             mService.unregisterUsageRequest(callback.request);
590         } catch (RemoteException e) {
591             if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
592             throw e.rethrowFromSystemServer();
593         }
594     }
595 
596     /**
597      * Base class for usage callbacks. Should be extended by applications wanting notifications.
598      */
599     public static abstract class UsageCallback {
600 
601         /**
602          * Called when data usage has reached the given threshold.
603          */
onThresholdReached(int networkType, String subscriberId)604         public abstract void onThresholdReached(int networkType, String subscriberId);
605 
606         /**
607          * @hide used for internal bookkeeping
608          */
609         private DataUsageRequest request;
610     }
611 
612     /**
613      * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
614      * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
615      * Note that no de-duplication of statistics between providers is performed, so each provider
616      * must only report network traffic that is not being reported by any other provider. Also note
617      * that the provider cannot be re-registered after unregistering.
618      *
619      * @param tag a human readable identifier of the custom network stats provider. This is only
620      *            used for debugging.
621      * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
622      *                 registered to the system.
623      * @hide
624      */
625     @SystemApi
626     @RequiresPermission(anyOf = {
627             android.Manifest.permission.NETWORK_STATS_PROVIDER,
628             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
registerNetworkStatsProvider( @onNull String tag, @NonNull NetworkStatsProvider provider)629     @NonNull public void registerNetworkStatsProvider(
630             @NonNull String tag,
631             @NonNull NetworkStatsProvider provider) {
632         try {
633             if (provider.getProviderCallbackBinder() != null) {
634                 throw new IllegalArgumentException("provider is already registered");
635             }
636             final INetworkStatsProviderCallback cbBinder =
637                     mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
638             provider.setProviderCallbackBinder(cbBinder);
639         } catch (RemoteException e) {
640             e.rethrowAsRuntimeException();
641         }
642     }
643 
644     /**
645      * Unregisters an instance of {@link NetworkStatsProvider}.
646      *
647      * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
648      *                 unregistered to the system.
649      * @hide
650      */
651     @SystemApi
652     @RequiresPermission(anyOf = {
653             android.Manifest.permission.NETWORK_STATS_PROVIDER,
654             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
unregisterNetworkStatsProvider(@onNull NetworkStatsProvider provider)655     @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
656         try {
657             provider.getProviderCallbackBinderOrThrow().unregister();
658         } catch (RemoteException e) {
659             e.rethrowAsRuntimeException();
660         }
661     }
662 
createTemplate(int networkType, String subscriberId)663     private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
664         final NetworkTemplate template;
665         switch (networkType) {
666             case ConnectivityManager.TYPE_MOBILE:
667                 template = subscriberId == null
668                         ? NetworkTemplate.buildTemplateMobileWildcard()
669                         : NetworkTemplate.buildTemplateMobileAll(subscriberId);
670                 break;
671             case ConnectivityManager.TYPE_WIFI:
672                 template = TextUtils.isEmpty(subscriberId)
673                         ? NetworkTemplate.buildTemplateWifiWildcard()
674                         : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
675                                 subscriberId);
676                 break;
677             default:
678                 throw new IllegalArgumentException("Cannot create template for network type "
679                         + networkType + ", subscriberId '"
680                         + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + "'.");
681         }
682         return template;
683     }
684 
685     /**
686      * Notify {@code NetworkStatsService} about network status changed.
687      *
688      * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
689      *
690      * To avoid races that attribute data usage to wrong network, such as new network with
691      * the same interface after SIM hot-swap, this function will not return until
692      * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
693      * all data sources.
694      *
695      * @param defaultNetworks the list of all networks that could be used by network traffic that
696      *                        does not explicitly select a network.
697      * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for
698      *                              each network that is currently connected.
699      * @param activeIface the active (i.e., connected) default network interface for the calling
700      *                    uid. Used to determine on which network future calls to
701      *                    {@link android.net.TrafficStats#incrementOperationCount} applies to.
702      * @param underlyingNetworkInfos the list of underlying network information for all
703      *                               currently-connected VPNs.
704      *
705      * @hide
706      */
707     @SystemApi(client = MODULE_LIBRARIES)
708     @RequiresPermission(anyOf = {
709             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
710             android.Manifest.permission.NETWORK_STACK})
notifyNetworkStatus( @onNull List<Network> defaultNetworks, @NonNull List<NetworkStateSnapshot> networkStateSnapshots, @Nullable String activeIface, @NonNull List<UnderlyingNetworkInfo> underlyingNetworkInfos)711     public void notifyNetworkStatus(
712             @NonNull List<Network> defaultNetworks,
713             @NonNull List<NetworkStateSnapshot> networkStateSnapshots,
714             @Nullable String activeIface,
715             @NonNull List<UnderlyingNetworkInfo> underlyingNetworkInfos) {
716         try {
717             Objects.requireNonNull(defaultNetworks);
718             Objects.requireNonNull(networkStateSnapshots);
719             Objects.requireNonNull(underlyingNetworkInfos);
720             mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]),
721                     networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface,
722                     underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0]));
723         } catch (RemoteException e) {
724             throw e.rethrowFromSystemServer();
725         }
726     }
727 
728     private static class CallbackHandler extends Handler {
729         private final int mNetworkType;
730         private final String mSubscriberId;
731         private UsageCallback mCallback;
732 
CallbackHandler(Looper looper, int networkType, String subscriberId, UsageCallback callback)733         CallbackHandler(Looper looper, int networkType, String subscriberId,
734                 UsageCallback callback) {
735             super(looper);
736             mNetworkType = networkType;
737             mSubscriberId = subscriberId;
738             mCallback = callback;
739         }
740 
741         @Override
handleMessage(Message message)742         public void handleMessage(Message message) {
743             DataUsageRequest request =
744                     (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
745 
746             switch (message.what) {
747                 case CALLBACK_LIMIT_REACHED: {
748                     if (mCallback != null) {
749                         mCallback.onThresholdReached(mNetworkType, mSubscriberId);
750                     } else {
751                         Log.e(TAG, "limit reached with released callback for " + request);
752                     }
753                     break;
754                 }
755                 case CALLBACK_RELEASED: {
756                     if (DBG) Log.d(TAG, "callback released for " + request);
757                     mCallback = null;
758                     break;
759                 }
760             }
761         }
762 
getObject(Message msg, String key)763         private static Object getObject(Message msg, String key) {
764             return msg.getData().getParcelable(key);
765         }
766     }
767 }
768