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