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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.annotation.SystemService; 24 import android.annotation.TestApi; 25 import android.app.usage.NetworkStats.Bucket; 26 import android.compat.annotation.UnsupportedAppUsage; 27 import android.content.Context; 28 import android.net.ConnectivityManager; 29 import android.net.DataUsageRequest; 30 import android.net.INetworkStatsService; 31 import android.net.NetworkIdentity; 32 import android.net.NetworkStack; 33 import android.net.NetworkTemplate; 34 import android.net.netstats.provider.INetworkStatsProviderCallback; 35 import android.net.netstats.provider.NetworkStatsProvider; 36 import android.os.Binder; 37 import android.os.Handler; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.Messenger; 41 import android.os.RemoteException; 42 import android.os.ServiceManager; 43 import android.os.ServiceManager.ServiceNotFoundException; 44 import android.telephony.TelephonyManager; 45 import android.util.DataUnit; 46 import android.util.Log; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 50 import java.util.Objects; 51 52 /** 53 * Provides access to network usage history and statistics. Usage data is collected in 54 * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details. 55 * <p /> 56 * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and 57 * 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. 60 * <h3> 61 * Summary queries 62 * </h3> 63 * {@link #querySummaryForDevice} <p /> 64 * {@link #querySummaryForUser} <p /> 65 * {@link #querySummary} <p /> 66 * These queries aggregate network usage across the whole interval. Therefore there will be only one 67 * 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. 69 * <h3> 70 * History queries 71 * </h3> 72 * {@link #queryDetailsForUid} <p /> 73 * {@link #queryDetails} <p /> 74 * These queries do not aggregate over time but do aggregate over state, metered and roaming. 75 * 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}. 80 * <p /> 81 * <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 /> 87 * Profile owner apps are automatically granted permission to query data on the profile they manage 88 * (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 /> 94 * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required 95 * the above permission, even to access an app's own data usage, and carrier-privileged apps were 96 * not included. 97 */ 98 @SystemService(Context.NETWORK_STATS_SERVICE) 99 public class NetworkStatsManager { 100 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; 107 108 /** 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 117 private final Context mContext; 118 private final INetworkStatsService mService; 119 120 /** @hide */ 121 public static final int FLAG_POLL_ON_OPEN = 1 << 0; 122 /** @hide */ 123 public static final int FLAG_POLL_FORCE = 1 << 1; 124 /** @hide */ 125 public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2; 126 127 private int mFlags; 128 129 /** 130 * {@hide} 131 */ 132 @UnsupportedAppUsage NetworkStatsManager(Context context)133 public NetworkStatsManager(Context context) throws ServiceNotFoundException { 134 this(context, INetworkStatsService.Stub.asInterface( 135 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); 136 } 137 138 /** @hide */ 139 @VisibleForTesting NetworkStatsManager(Context context, INetworkStatsService service)140 public NetworkStatsManager(Context context, INetworkStatsService service) { 141 mContext = context; 142 mService = service; 143 setPollOnOpen(true); 144 } 145 146 /** @hide */ setPollOnOpen(boolean pollOnOpen)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 */ 156 @UnsupportedAppUsage 157 @TestApi setPollForce(boolean pollForce)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 */ setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan)167 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 } 173 } 174 175 /** @hide */ querySummaryForDevice(NetworkTemplate template, long startTime, long endTime)176 public Bucket querySummaryForDevice(NetworkTemplate template, 177 long startTime, long endTime) throws SecurityException, RemoteException { 178 Bucket bucket = null; 179 NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, 180 mService); 181 bucket = stats.getDeviceSummaryForNetwork(); 182 183 stats.close(); 184 return bucket; 185 } 186 187 /** 188 * Query network usage statistics summaries. Result is summarised data usage for the whole 189 * 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}, 193 * tag {@link NetworkStats.Bucket#TAG_NONE}, 194 * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, 195 * metered {@link NetworkStats.Bucket#METERED_ALL}, 196 * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. 197 * 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. 202 * <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()}. 208 * @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 */ querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime)215 public Bucket querySummaryForDevice(int networkType, String subscriberId, 216 long startTime, long endTime) throws SecurityException, RemoteException { 217 NetworkTemplate template; 218 try { 219 template = createTemplate(networkType, subscriberId); 220 } catch (IllegalArgumentException e) { 221 if (DBG) Log.e(TAG, "Cannot create template", e); 222 return null; 223 } 224 225 return querySummaryForDevice(template, startTime, endTime); 226 } 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. 231 * This means the bucket's start and end timestamp are going to be the same as the 'startTime' 232 * 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}. 236 * 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. 241 * <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()}. 247 * @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 */ querySummaryForUser(int networkType, String subscriberId, long startTime, long endTime)254 public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime, 255 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); 261 return null; 262 } 263 264 NetworkStats stats; 265 stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); 266 stats.startSummaryEnumeration(); 267 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 275 * 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. 279 * 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. 284 * <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()}. 290 * @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 */ querySummary(int networkType, String subscriberId, long startTime, long endTime)297 public NetworkStats querySummary(int networkType, String subscriberId, long startTime, 298 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); 304 return null; 305 } 306 307 return querySummary(template, startTime, endTime); 308 } 309 310 /** @hide */ querySummary(NetworkTemplate template, long startTime, long endTime)311 public NetworkStats querySummary(NetworkTemplate template, long startTime, 312 long endTime) throws SecurityException, RemoteException { 313 NetworkStats result; 314 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); 315 result.startSummaryEnumeration(); 316 317 return result; 318 } 319 320 /** 321 * Query network usage statistics details for a given uid. 322 * 323 * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) 324 */ queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid)325 public NetworkStats queryDetailsForUid(int networkType, String subscriberId, 326 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); 329 } 330 331 /** @hide */ queryDetailsForUid(NetworkTemplate template, long startTime, long endTime, int uid)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 338 /** 339 * Query network usage statistics details for a given uid and tag. 340 * 341 * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) 342 */ queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag)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. 355 * 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}. 358 * <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. 361 * 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. 366 * <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()}. 372 * @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 377 * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags. 378 * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate 379 * traffic from all states. 380 * @return Statistics object or null if an error happened during statistics collection. 381 * @throws SecurityException if permissions are insufficient to read network statistics. 382 */ queryDetailsForUidTagState(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag, int state)383 public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId, 384 long startTime, long endTime, int uid, int tag, int state) throws SecurityException { 385 NetworkTemplate template; 386 template = createTemplate(networkType, subscriberId); 387 388 return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state); 389 } 390 391 /** @hide */ queryDetailsForUidTagState(NetworkTemplate template, long startTime, long endTime, int uid, int tag, int state)392 public NetworkStats queryDetailsForUidTagState(NetworkTemplate template, 393 long startTime, long endTime, int uid, int tag, int state) throws SecurityException { 394 395 NetworkStats result; 396 try { 397 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); 398 result.startHistoryEnumeration(uid, tag, state); 399 } catch (RemoteException e) { 400 Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag 401 + " state=" + state, e); 402 return null; 403 } 404 405 return result; 406 } 407 408 /** 409 * Query network usage statistics details. Result filtered to include only uids belonging to 410 * 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, 414 * 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}. 418 * <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. 421 * 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. 426 * <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()}. 432 * @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 */ queryDetails(int networkType, String subscriberId, long startTime, long endTime)439 public NetworkStats queryDetails(int networkType, String subscriberId, long startTime, 440 long endTime) throws SecurityException, RemoteException { 441 NetworkTemplate template; 442 try { 443 template = createTemplate(networkType, subscriberId); 444 } catch (IllegalArgumentException e) { 445 if (DBG) Log.e(TAG, "Cannot create template", e); 446 return null; 447 } 448 449 NetworkStats result; 450 result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); 451 result.startUserUidEnumeration(); 452 return result; 453 } 454 455 /** @hide */ registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler)456 public void registerUsageCallback(NetworkTemplate template, int networkType, 457 long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { 458 Objects.requireNonNull(callback, "UsageCallback cannot be null"); 459 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 486 /** 487 * Registers to receive notifications about data usage on specified networks. 488 * 489 * @see #registerUsageCallback(int, String, long, UsageCallback, Handler) 490 */ registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback)491 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, 492 UsageCallback callback) { 493 registerUsageCallback(networkType, subscriberId, thresholdBytes, callback, 494 null /* handler */); 495 } 496 497 /** 498 * Registers to receive notifications about data usage on specified networks. 499 * 500 * <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. 506 * <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()}. 512 * @param thresholdBytes Threshold in bytes to be notified on. 513 * @param callback The {@link UsageCallback} that the system will call when data usage 514 * has exceeded the specified threshold. 515 * @param handler to dispatch callback events through, otherwise if {@code null} it uses 516 * the calling thread. 517 */ registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback, @Nullable Handler handler)518 public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, 519 UsageCallback callback, @Nullable Handler handler) { 520 NetworkTemplate template = createTemplate(networkType, subscriberId); 521 if (DBG) { 522 Log.d(TAG, "registerUsageCallback called with: {" 523 + " networkType=" + networkType 524 + " subscriberId=" + subscriberId 525 + " thresholdBytes=" + thresholdBytes 526 + " }"); 527 } 528 registerUsageCallback(template, networkType, thresholdBytes, callback, handler); 529 } 530 531 /** 532 * Unregisters callbacks on data usage. 533 * 534 * @param callback The {@link UsageCallback} used when registering. 535 */ unregisterUsageCallback(UsageCallback callback)536 public void unregisterUsageCallback(UsageCallback callback) { 537 if (callback == null || callback.request == null 538 || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) { 539 throw new IllegalArgumentException("Invalid UsageCallback"); 540 } 541 try { 542 mService.unregisterUsageRequest(callback.request); 543 } catch (RemoteException e) { 544 if (DBG) Log.d(TAG, "Remote exception when unregistering callback"); 545 throw e.rethrowFromSystemServer(); 546 } 547 } 548 549 /** 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 */ onThresholdReached(int networkType, String subscriberId)557 public abstract void onThresholdReached(int networkType, String subscriberId); 558 559 /** 560 * @hide used for internal bookkeeping 561 */ 562 private DataUsageRequest request; 563 } 564 565 /** 566 * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics 567 * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}. 568 * Note that no de-duplication of statistics between providers is performed, so each provider 569 * 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. 571 * 572 * @param tag a human readable identifier of the custom network stats provider. This is only 573 * used for debugging. 574 * @param provider the subclass of {@link NetworkStatsProvider} that needs to be 575 * registered to the system. 576 * @hide 577 */ 578 @SystemApi 579 @RequiresPermission(anyOf = { 580 android.Manifest.permission.NETWORK_STATS_PROVIDER, 581 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) registerNetworkStatsProvider( @onNull String tag, @NonNull NetworkStatsProvider provider)582 @NonNull public void registerNetworkStatsProvider( 583 @NonNull String tag, 584 @NonNull NetworkStatsProvider provider) { 585 try { 586 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); 592 } catch (RemoteException e) { 593 e.rethrowAsRuntimeException(); 594 } 595 } 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}) unregisterNetworkStatsProvider(@onNull NetworkStatsProvider provider)608 @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) { 609 try { 610 provider.getProviderCallbackBinderOrThrow().unregister(); 611 } catch (RemoteException e) { 612 e.rethrowAsRuntimeException(); 613 } 614 } 615 createTemplate(int networkType, String subscriberId)616 private static NetworkTemplate createTemplate(int networkType, String subscriberId) { 617 final NetworkTemplate template; 618 switch (networkType) { 619 case ConnectivityManager.TYPE_MOBILE: 620 template = subscriberId == null 621 ? NetworkTemplate.buildTemplateMobileWildcard() 622 : NetworkTemplate.buildTemplateMobileAll(subscriberId); 623 break; 624 case ConnectivityManager.TYPE_WIFI: 625 template = NetworkTemplate.buildTemplateWifiWildcard(); 626 break; 627 default: 628 throw new IllegalArgumentException("Cannot create template for network type " 629 + networkType + ", subscriberId '" 630 + NetworkIdentity.scrubSubscriberId(subscriberId) + "'."); 631 } 632 return template; 633 } 634 635 private static class CallbackHandler extends Handler { 636 private final int mNetworkType; 637 private final String mSubscriberId; 638 private UsageCallback mCallback; 639 CallbackHandler(Looper looper, int networkType, String subscriberId, UsageCallback callback)640 CallbackHandler(Looper looper, int networkType, String subscriberId, 641 UsageCallback callback) { 642 super(looper); 643 mNetworkType = networkType; 644 mSubscriberId = subscriberId; 645 mCallback = callback; 646 } 647 648 @Override handleMessage(Message message)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) { 656 mCallback.onThresholdReached(mNetworkType, mSubscriberId); 657 } 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 getObject(Message msg, String key)670 private static Object getObject(Message msg, String key) { 671 return msg.getData().getParcelable(key); 672 } 673 } 674 } 675