1 /** 2 * Copyright (C) 2014 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.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.annotation.SystemService; 25 import android.annotation.TestApi; 26 import android.annotation.UnsupportedAppUsage; 27 import android.app.Activity; 28 import android.app.PendingIntent; 29 import android.content.Context; 30 import android.content.pm.ParceledListSlice; 31 import android.os.Build; 32 import android.os.RemoteException; 33 import android.os.UserHandle; 34 import android.util.ArrayMap; 35 36 import java.lang.annotation.Retention; 37 import java.lang.annotation.RetentionPolicy; 38 import java.time.Duration; 39 import java.util.ArrayList; 40 import java.util.Collections; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.concurrent.TimeUnit; 44 45 /** 46 * Provides access to device usage history and statistics. Usage data is aggregated into 47 * time intervals: days, weeks, months, and years. 48 * <p /> 49 * When requesting usage data since a particular time, the request might look something like this: 50 * <pre> 51 * PAST REQUEST_TIME TODAY FUTURE 52 * ————————————————————————————||———————————————————————————¦-----------------------| 53 * YEAR || ¦ | 54 * ————————————————————————————||———————————————————————————¦-----------------------| 55 * MONTH | || MONTH ¦ | 56 * ——————————————————|—————————||———————————————————————————¦-----------------------| 57 * | WEEK | WEEK|| | WEEK | WE¦EK | WEEK | 58 * ————————————————————————————||———————————————————|———————¦-----------------------| 59 * || |DAY|DAY|DAY|DAY¦DAY|DAY|DAY|DAY|DAY|DAY| 60 * ————————————————————————————||———————————————————————————¦-----------------------| 61 * </pre> 62 * A request for data in the middle of a time interval will include that interval. 63 * <p/> 64 * <b>NOTE:</b> Most methods on this API require the permission 65 * android.permission.PACKAGE_USAGE_STATS. However, declaring the permission implies intention to 66 * use the API and the user of the device still needs to grant permission through the Settings 67 * application. 68 * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}. 69 * Methods which only return the information for the calling package do not require this permission. 70 * E.g. {@link #getAppStandbyBucket()} and {@link #queryEventsForSelf(long, long)}. 71 */ 72 @SystemService(Context.USAGE_STATS_SERVICE) 73 public final class UsageStatsManager { 74 75 /** 76 * An interval type that spans a day. See {@link #queryUsageStats(int, long, long)}. 77 */ 78 public static final int INTERVAL_DAILY = 0; 79 80 /** 81 * An interval type that spans a week. See {@link #queryUsageStats(int, long, long)}. 82 */ 83 public static final int INTERVAL_WEEKLY = 1; 84 85 /** 86 * An interval type that spans a month. See {@link #queryUsageStats(int, long, long)}. 87 */ 88 public static final int INTERVAL_MONTHLY = 2; 89 90 /** 91 * An interval type that spans a year. See {@link #queryUsageStats(int, long, long)}. 92 */ 93 public static final int INTERVAL_YEARLY = 3; 94 95 /** 96 * An interval type that will use the best fit interval for the given time range. 97 * See {@link #queryUsageStats(int, long, long)}. 98 */ 99 public static final int INTERVAL_BEST = 4; 100 101 /** 102 * The number of available intervals. Does not include {@link #INTERVAL_BEST}, since it 103 * is a pseudo interval (it actually selects a real interval). 104 * {@hide} 105 */ 106 public static final int INTERVAL_COUNT = 4; 107 108 109 /** 110 * The app is whitelisted for some reason and the bucket cannot be changed. 111 * {@hide} 112 */ 113 @SystemApi 114 public static final int STANDBY_BUCKET_EXEMPTED = 5; 115 116 /** 117 * The app was used very recently, currently in use or likely to be used very soon. Standby 118 * bucket values that are ≤ {@link #STANDBY_BUCKET_ACTIVE} will not be throttled by the 119 * system while they are in this bucket. Buckets > {@link #STANDBY_BUCKET_ACTIVE} will most 120 * likely be restricted in some way. For instance, jobs and alarms may be deferred. 121 * @see #getAppStandbyBucket() 122 */ 123 public static final int STANDBY_BUCKET_ACTIVE = 10; 124 125 /** 126 * The app was used recently and/or likely to be used in the next few hours. Restrictions will 127 * apply to these apps, such as deferral of jobs and alarms. 128 * @see #getAppStandbyBucket() 129 */ 130 public static final int STANDBY_BUCKET_WORKING_SET = 20; 131 132 /** 133 * The app was used in the last few days and/or likely to be used in the next few days. 134 * Restrictions will apply to these apps, such as deferral of jobs and alarms. The delays may be 135 * greater than for apps in higher buckets (lower bucket value). Bucket values > 136 * {@link #STANDBY_BUCKET_FREQUENT} may additionally have network access limited. 137 * @see #getAppStandbyBucket() 138 */ 139 public static final int STANDBY_BUCKET_FREQUENT = 30; 140 141 /** 142 * The app has not be used for several days and/or is unlikely to be used for several days. 143 * Apps in this bucket will have the most restrictions, including network restrictions, except 144 * during certain short periods (at a minimum, once a day) when they are allowed to execute 145 * jobs, access the network, etc. 146 * @see #getAppStandbyBucket() 147 */ 148 public static final int STANDBY_BUCKET_RARE = 40; 149 150 /** 151 * The app has never been used. 152 * {@hide} 153 */ 154 @SystemApi 155 public static final int STANDBY_BUCKET_NEVER = 50; 156 157 /** @hide */ 158 public static final int REASON_MAIN_MASK = 0xFF00; 159 /** @hide */ 160 public static final int REASON_MAIN_DEFAULT = 0x0100; 161 /** @hide */ 162 public static final int REASON_MAIN_TIMEOUT = 0x0200; 163 /** @hide */ 164 public static final int REASON_MAIN_USAGE = 0x0300; 165 /** @hide */ 166 public static final int REASON_MAIN_FORCED = 0x0400; 167 /** @hide */ 168 public static final int REASON_MAIN_PREDICTED = 0x0500; 169 170 /** @hide */ 171 public static final int REASON_SUB_MASK = 0x00FF; 172 /** @hide */ 173 public static final int REASON_SUB_USAGE_SYSTEM_INTERACTION = 0x0001; 174 /** @hide */ 175 public static final int REASON_SUB_USAGE_NOTIFICATION_SEEN = 0x0002; 176 /** @hide */ 177 public static final int REASON_SUB_USAGE_USER_INTERACTION = 0x0003; 178 /** @hide */ 179 public static final int REASON_SUB_USAGE_MOVE_TO_FOREGROUND = 0x0004; 180 /** @hide */ 181 public static final int REASON_SUB_USAGE_MOVE_TO_BACKGROUND = 0x0005; 182 /** @hide */ 183 public static final int REASON_SUB_USAGE_SYSTEM_UPDATE = 0x0006; 184 /** @hide */ 185 public static final int REASON_SUB_USAGE_ACTIVE_TIMEOUT = 0x0007; 186 /** @hide */ 187 public static final int REASON_SUB_USAGE_SYNC_ADAPTER = 0x0008; 188 /** @hide */ 189 public static final int REASON_SUB_USAGE_SLICE_PINNED = 0x0009; 190 /** @hide */ 191 public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A; 192 /** @hide */ 193 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE = 0x000B; 194 /** @hide */ 195 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C; 196 /** @hide */ 197 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D; 198 /** @hide */ 199 public static final int REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED = 0x000E; 200 /** @hide */ 201 public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000F; 202 /** @hide */ 203 public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001; 204 205 206 /** @hide */ 207 @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = { 208 STANDBY_BUCKET_EXEMPTED, 209 STANDBY_BUCKET_ACTIVE, 210 STANDBY_BUCKET_WORKING_SET, 211 STANDBY_BUCKET_FREQUENT, 212 STANDBY_BUCKET_RARE, 213 STANDBY_BUCKET_NEVER, 214 }) 215 @Retention(RetentionPolicy.SOURCE) 216 public @interface StandbyBuckets {} 217 218 /** 219 * Observer id of the registered observer for the group of packages that reached the usage 220 * time limit. Included as an extra in the PendingIntent that was registered. 221 * @hide 222 */ 223 @SystemApi 224 public static final String EXTRA_OBSERVER_ID = "android.app.usage.extra.OBSERVER_ID"; 225 226 /** 227 * Original time limit in milliseconds specified by the registered observer for the group of 228 * packages that reached the usage time limit. Included as an extra in the PendingIntent that 229 * was registered. 230 * @hide 231 */ 232 @SystemApi 233 public static final String EXTRA_TIME_LIMIT = "android.app.usage.extra.TIME_LIMIT"; 234 235 /** 236 * Actual usage time in milliseconds for the group of packages that reached the specified time 237 * limit. Included as an extra in the PendingIntent that was registered. 238 * @hide 239 */ 240 @SystemApi 241 public static final String EXTRA_TIME_USED = "android.app.usage.extra.TIME_USED"; 242 243 244 /** 245 * App usage observers will consider the task root package the source of usage. 246 * @hide 247 */ 248 @SystemApi 249 public static final int USAGE_SOURCE_TASK_ROOT_ACTIVITY = 1; 250 251 /** 252 * App usage observers will consider the visible activity's package the source of usage. 253 * @hide 254 */ 255 @SystemApi 256 public static final int USAGE_SOURCE_CURRENT_ACTIVITY = 2; 257 258 /** @hide */ 259 @IntDef(prefix = { "USAGE_SOURCE_" }, value = { 260 USAGE_SOURCE_TASK_ROOT_ACTIVITY, 261 USAGE_SOURCE_CURRENT_ACTIVITY, 262 }) 263 @Retention(RetentionPolicy.SOURCE) 264 public @interface UsageSource {} 265 266 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 267 private static final UsageEvents sEmptyResults = new UsageEvents(); 268 269 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 270 private final Context mContext; 271 @UnsupportedAppUsage 272 private final IUsageStatsManager mService; 273 274 /** 275 * {@hide} 276 */ UsageStatsManager(Context context, IUsageStatsManager service)277 public UsageStatsManager(Context context, IUsageStatsManager service) { 278 mContext = context; 279 mService = service; 280 } 281 282 /** 283 * Gets application usage stats for the given time range, aggregated by the specified interval. 284 * 285 * <p> 286 * The returned list will contain one or more {@link UsageStats} objects for each package, with 287 * usage data that covers at least the given time range. 288 * Note: The begin and end times of the time range may be expanded to the nearest whole interval 289 * period. 290 * </p> 291 * 292 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 293 * 294 * @param intervalType The time interval by which the stats are aggregated. 295 * @param beginTime The inclusive beginning of the range of stats to include in the results. 296 * Defined in terms of "Unix time", see 297 * {@link java.lang.System#currentTimeMillis}. 298 * @param endTime The exclusive end of the range of stats to include in the results. Defined 299 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 300 * @return A list of {@link UsageStats} 301 * 302 * @see #INTERVAL_DAILY 303 * @see #INTERVAL_WEEKLY 304 * @see #INTERVAL_MONTHLY 305 * @see #INTERVAL_YEARLY 306 * @see #INTERVAL_BEST 307 */ queryUsageStats(int intervalType, long beginTime, long endTime)308 public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) { 309 try { 310 @SuppressWarnings("unchecked") 311 ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime, 312 endTime, mContext.getOpPackageName()); 313 if (slice != null) { 314 return slice.getList(); 315 } 316 } catch (RemoteException e) { 317 // fallthrough and return the empty list. 318 } 319 return Collections.emptyList(); 320 } 321 322 /** 323 * Gets the hardware configurations the device was in for the given time range, aggregated by 324 * the specified interval. The results are ordered as in 325 * {@link #queryUsageStats(int, long, long)}. 326 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 327 * 328 * @param intervalType The time interval by which the stats are aggregated. 329 * @param beginTime The inclusive beginning of the range of stats to include in the results. 330 * Defined in terms of "Unix time", see 331 * {@link java.lang.System#currentTimeMillis}. 332 * @param endTime The exclusive end of the range of stats to include in the results. Defined 333 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 334 * @return A list of {@link ConfigurationStats} 335 */ queryConfigurations(int intervalType, long beginTime, long endTime)336 public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime, 337 long endTime) { 338 try { 339 @SuppressWarnings("unchecked") 340 ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats( 341 intervalType, beginTime, endTime, mContext.getOpPackageName()); 342 if (slice != null) { 343 return slice.getList(); 344 } 345 } catch (RemoteException e) { 346 // fallthrough and return the empty list. 347 } 348 return Collections.emptyList(); 349 } 350 351 /** 352 * Gets aggregated event stats for the given time range, aggregated by the specified interval. 353 * <p>The returned list will contain a {@link EventStats} object for each event type that 354 * is being aggregated and has data for an interval that is a subset of the time range given. 355 * 356 * <p>The current event types that will be aggregated here are:</p> 357 * <ul> 358 * <li>{@link UsageEvents.Event#SCREEN_INTERACTIVE}</li> 359 * <li>{@link UsageEvents.Event#SCREEN_NON_INTERACTIVE}</li> 360 * <li>{@link UsageEvents.Event#KEYGUARD_SHOWN}</li> 361 * <li>{@link UsageEvents.Event#KEYGUARD_HIDDEN}</li> 362 * </ul> 363 * 364 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 365 * 366 * @param intervalType The time interval by which the stats are aggregated. 367 * @param beginTime The inclusive beginning of the range of stats to include in the results. 368 * Defined in terms of "Unix time", see 369 * {@link java.lang.System#currentTimeMillis}. 370 * @param endTime The exclusive end of the range of stats to include in the results. Defined 371 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 372 * @return A list of {@link EventStats} 373 * 374 * @see #INTERVAL_DAILY 375 * @see #INTERVAL_WEEKLY 376 * @see #INTERVAL_MONTHLY 377 * @see #INTERVAL_YEARLY 378 * @see #INTERVAL_BEST 379 */ queryEventStats(int intervalType, long beginTime, long endTime)380 public List<EventStats> queryEventStats(int intervalType, long beginTime, long endTime) { 381 try { 382 @SuppressWarnings("unchecked") 383 ParceledListSlice<EventStats> slice = mService.queryEventStats(intervalType, beginTime, 384 endTime, mContext.getOpPackageName()); 385 if (slice != null) { 386 return slice.getList(); 387 } 388 } catch (RemoteException e) { 389 // fallthrough and return the empty list. 390 } 391 return Collections.emptyList(); 392 } 393 394 /** 395 * Query for events in the given time range. Events are only kept by the system for a few 396 * days. 397 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 398 * 399 * @param beginTime The inclusive beginning of the range of events to include in the results. 400 * Defined in terms of "Unix time", see 401 * {@link java.lang.System#currentTimeMillis}. 402 * @param endTime The exclusive end of the range of events to include in the results. Defined 403 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 404 * @return A {@link UsageEvents}. 405 */ queryEvents(long beginTime, long endTime)406 public UsageEvents queryEvents(long beginTime, long endTime) { 407 try { 408 UsageEvents iter = mService.queryEvents(beginTime, endTime, 409 mContext.getOpPackageName()); 410 if (iter != null) { 411 return iter; 412 } 413 } catch (RemoteException e) { 414 // fallthrough and return empty result. 415 } 416 return sEmptyResults; 417 } 418 419 /** 420 * Like {@link #queryEvents(long, long)}, but only returns events for the calling package. 421 * 422 * @param beginTime The inclusive beginning of the range of events to include in the results. 423 * Defined in terms of "Unix time", see 424 * {@link java.lang.System#currentTimeMillis}. 425 * @param endTime The exclusive end of the range of events to include in the results. Defined 426 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 427 * @return A {@link UsageEvents} object. 428 * 429 * @see #queryEvents(long, long) 430 */ queryEventsForSelf(long beginTime, long endTime)431 public UsageEvents queryEventsForSelf(long beginTime, long endTime) { 432 try { 433 final UsageEvents events = mService.queryEventsForPackage(beginTime, endTime, 434 mContext.getOpPackageName()); 435 if (events != null) { 436 return events; 437 } 438 } catch (RemoteException e) { 439 // fallthrough 440 } 441 return sEmptyResults; 442 } 443 444 /** 445 * A convenience method that queries for all stats in the given range (using the best interval 446 * for that range), merges the resulting data, and keys it by package name. 447 * See {@link #queryUsageStats(int, long, long)}. 448 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 449 * 450 * @param beginTime The inclusive beginning of the range of stats to include in the results. 451 * Defined in terms of "Unix time", see 452 * {@link java.lang.System#currentTimeMillis}. 453 * @param endTime The exclusive end of the range of stats to include in the results. Defined 454 * in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. 455 * @return A {@link java.util.Map} keyed by package name 456 */ queryAndAggregateUsageStats(long beginTime, long endTime)457 public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) { 458 List<UsageStats> stats = queryUsageStats(INTERVAL_BEST, beginTime, endTime); 459 if (stats.isEmpty()) { 460 return Collections.emptyMap(); 461 } 462 463 ArrayMap<String, UsageStats> aggregatedStats = new ArrayMap<>(); 464 final int statCount = stats.size(); 465 for (int i = 0; i < statCount; i++) { 466 UsageStats newStat = stats.get(i); 467 UsageStats existingStat = aggregatedStats.get(newStat.getPackageName()); 468 if (existingStat == null) { 469 aggregatedStats.put(newStat.mPackageName, newStat); 470 } else { 471 existingStat.add(newStat); 472 } 473 } 474 return aggregatedStats; 475 } 476 477 /** 478 * Returns whether the specified app is currently considered inactive. This will be true if the 479 * app hasn't been used directly or indirectly for a period of time defined by the system. This 480 * could be of the order of several hours or days. 481 * @param packageName The package name of the app to query 482 * @return whether the app is currently considered inactive 483 */ isAppInactive(String packageName)484 public boolean isAppInactive(String packageName) { 485 try { 486 return mService.isAppInactive(packageName, mContext.getUserId()); 487 } catch (RemoteException e) { 488 // fall through and return default 489 } 490 return false; 491 } 492 493 /** 494 * {@hide} 495 */ setAppInactive(String packageName, boolean inactive)496 public void setAppInactive(String packageName, boolean inactive) { 497 try { 498 mService.setAppInactive(packageName, inactive, mContext.getUserId()); 499 } catch (RemoteException e) { 500 // fall through 501 } 502 } 503 504 /** 505 * Returns the current standby bucket of the calling app. The system determines the standby 506 * state of the app based on app usage patterns. Standby buckets determine how much an app will 507 * be restricted from running background tasks such as jobs and alarms. 508 * <p>Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to 509 * {@link #STANDBY_BUCKET_RARE}, with {@link #STANDBY_BUCKET_ACTIVE} being the least 510 * restrictive. The battery level of the device might also affect the restrictions. 511 * <p>Apps in buckets ≤ {@link #STANDBY_BUCKET_ACTIVE} have no standby restrictions imposed. 512 * Apps in buckets > {@link #STANDBY_BUCKET_FREQUENT} may have network access restricted when 513 * running in the background. 514 * <p>The standby state of an app can change at any time either due to a user interaction or a 515 * system interaction or some algorithm determining that the app can be restricted for a period 516 * of time before the user has a need for it. 517 * <p>You can also query the recent history of standby bucket changes by calling 518 * {@link #queryEventsForSelf(long, long)} and searching for 519 * {@link UsageEvents.Event#STANDBY_BUCKET_CHANGED}. 520 * 521 * @return the current standby bucket of the calling app. One of STANDBY_BUCKET_* constants. 522 */ getAppStandbyBucket()523 public @StandbyBuckets int getAppStandbyBucket() { 524 try { 525 return mService.getAppStandbyBucket(mContext.getOpPackageName(), 526 mContext.getOpPackageName(), 527 mContext.getUserId()); 528 } catch (RemoteException e) { 529 } 530 return STANDBY_BUCKET_ACTIVE; 531 } 532 533 /** 534 * {@hide} 535 * Returns the current standby bucket of the specified app. The caller must hold the permission 536 * android.permission.PACKAGE_USAGE_STATS. 537 * @param packageName the package for which to fetch the current standby bucket. 538 */ 539 @SystemApi 540 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) getAppStandbyBucket(String packageName)541 public @StandbyBuckets int getAppStandbyBucket(String packageName) { 542 try { 543 return mService.getAppStandbyBucket(packageName, mContext.getOpPackageName(), 544 mContext.getUserId()); 545 } catch (RemoteException e) { 546 } 547 return STANDBY_BUCKET_ACTIVE; 548 } 549 550 /** 551 * {@hide} 552 * Changes an app's standby bucket to the provided value. The caller can only set the standby 553 * bucket for a different app than itself. 554 * @param packageName the package name of the app to set the bucket for. A SecurityException 555 * will be thrown if the package name is that of the caller. 556 * @param bucket the standby bucket to set it to, which should be one of STANDBY_BUCKET_*. 557 * Setting a standby bucket outside of the range of STANDBY_BUCKET_ACTIVE to 558 * STANDBY_BUCKET_NEVER will result in a SecurityException. 559 */ 560 @SystemApi 561 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) setAppStandbyBucket(String packageName, @StandbyBuckets int bucket)562 public void setAppStandbyBucket(String packageName, @StandbyBuckets int bucket) { 563 try { 564 mService.setAppStandbyBucket(packageName, bucket, mContext.getUserId()); 565 } catch (RemoteException e) { 566 throw e.rethrowFromSystemServer(); 567 } 568 } 569 570 /** 571 * {@hide} 572 * Returns the current standby bucket of every app that has a bucket assigned to it. 573 * The caller must hold the permission android.permission.PACKAGE_USAGE_STATS. The key of the 574 * returned Map is the package name and the value is the bucket assigned to the package. 575 * @see #getAppStandbyBucket() 576 */ 577 @SystemApi 578 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) getAppStandbyBuckets()579 public Map<String, Integer> getAppStandbyBuckets() { 580 try { 581 final ParceledListSlice<AppStandbyInfo> slice = mService.getAppStandbyBuckets( 582 mContext.getOpPackageName(), mContext.getUserId()); 583 final List<AppStandbyInfo> bucketList = slice.getList(); 584 final ArrayMap<String, Integer> bucketMap = new ArrayMap<>(); 585 final int n = bucketList.size(); 586 for (int i = 0; i < n; i++) { 587 final AppStandbyInfo bucketInfo = bucketList.get(i); 588 bucketMap.put(bucketInfo.mPackageName, bucketInfo.mStandbyBucket); 589 } 590 return bucketMap; 591 } catch (RemoteException e) { 592 throw e.rethrowFromSystemServer(); 593 } 594 } 595 596 /** 597 * {@hide} 598 * Changes the app standby bucket for multiple apps at once. The Map is keyed by the package 599 * name and the value is one of STANDBY_BUCKET_*. 600 * @param appBuckets a map of package name to bucket value. 601 */ 602 @SystemApi 603 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) setAppStandbyBuckets(Map<String, Integer> appBuckets)604 public void setAppStandbyBuckets(Map<String, Integer> appBuckets) { 605 if (appBuckets == null) { 606 return; 607 } 608 final List<AppStandbyInfo> bucketInfoList = new ArrayList<>(appBuckets.size()); 609 for (Map.Entry<String, Integer> bucketEntry : appBuckets.entrySet()) { 610 bucketInfoList.add(new AppStandbyInfo(bucketEntry.getKey(), bucketEntry.getValue())); 611 } 612 final ParceledListSlice<AppStandbyInfo> slice = new ParceledListSlice<>(bucketInfoList); 613 try { 614 mService.setAppStandbyBuckets(slice, mContext.getUserId()); 615 } catch (RemoteException e) { 616 throw e.rethrowFromSystemServer(); 617 } 618 } 619 620 /** 621 * @hide 622 * Register an app usage limit observer that receives a callback on the provided intent when 623 * the sum of usages of apps and tokens in the {@code observed} array exceeds the 624 * {@code timeLimit} specified. The structure of a token is a String with the reporting 625 * package's name and a token the reporting app will use, separated by the forward slash 626 * character. Example: com.reporting.package/5OM3*0P4QU3-7OK3N 627 * The observer will automatically be unregistered when the time limit is reached and the 628 * intent is delivered. Registering an {@code observerId} that was already registered will 629 * override the previous one. No more than 1000 unique {@code observerId} may be registered by 630 * a single uid at any one time. 631 * @param observerId A unique id associated with the group of apps to be monitored. There can 632 * be multiple groups with common packages and different time limits. 633 * @param observedEntities The list of packages and token to observe for usage time. Cannot be 634 * null and must include at least one package or token. 635 * @param timeLimit The total time the set of apps can be in the foreground before the 636 * callbackIntent is delivered. Must be at least one minute. 637 * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null. 638 * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is 639 * exceeded by the group of apps. The delivered Intent will also contain 640 * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and 641 * {@link #EXTRA_TIME_USED}. Cannot be null. 642 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and 643 * is not the profile owner of this user. 644 */ 645 @SystemApi 646 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) registerAppUsageObserver(int observerId, @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent)647 public void registerAppUsageObserver(int observerId, @NonNull String[] observedEntities, 648 long timeLimit, @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent) { 649 try { 650 mService.registerAppUsageObserver(observerId, observedEntities, 651 timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName()); 652 } catch (RemoteException e) { 653 throw e.rethrowFromSystemServer(); 654 } 655 } 656 657 /** 658 * @hide 659 * Unregister the app usage observer specified by the {@code observerId}. This will only apply 660 * to any observer registered by this application. Unregistering an observer that was already 661 * unregistered or never registered will have no effect. 662 * @param observerId The id of the observer that was previously registered. 663 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and is 664 * not the profile owner of this user. 665 */ 666 @SystemApi 667 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) unregisterAppUsageObserver(int observerId)668 public void unregisterAppUsageObserver(int observerId) { 669 try { 670 mService.unregisterAppUsageObserver(observerId, mContext.getOpPackageName()); 671 } catch (RemoteException e) { 672 throw e.rethrowFromSystemServer(); 673 } 674 } 675 676 /** 677 * Register a usage session observer that receives a callback on the provided {@code 678 * limitReachedCallbackIntent} when the sum of usages of apps and tokens in the {@code 679 * observed} array exceeds the {@code timeLimit} specified within a usage session. The 680 * structure of a token is a String with the reporting packages' name and a token the 681 * reporting app will use, separated by the forward slash character. 682 * Example: com.reporting.package/5OM3*0P4QU3-7OK3N 683 * After the {@code timeLimit} has been reached, the usage session observer will receive a 684 * callback on the provided {@code sessionEndCallbackIntent} when the usage session ends. 685 * Registering another session observer against a {@code sessionObserverId} that has already 686 * been registered will override the previous session observer. 687 * 688 * @param sessionObserverId A unique id associated with the group of apps to be 689 * monitored. There can be multiple groups with common 690 * packages and different time limits. 691 * @param observedEntities The list of packages and token to observe for usage time. Cannot be 692 * null and must include at least one package or token. 693 * @param timeLimit The total time the set of apps can be used continuously before the {@code 694 * limitReachedCallbackIntent} is delivered. Must be at least one minute. 695 * @param sessionThresholdTime The time that can take place between usage sessions before the 696 * next session is considered a new session. Must be non-negative. 697 * @param limitReachedCallbackIntent The {@link PendingIntent} that will be dispatched when the 698 * usage limit is exceeded by the group of apps. The 699 * delivered Intent will also contain the extras {@link 700 * #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and {@link 701 * #EXTRA_TIME_USED}. Cannot be null. 702 * @param sessionEndCallbackIntent The {@link PendingIntent} that will be dispatched when the 703 * session has ended after the usage limit has been exceeded. 704 * The session is considered at its end after the {@code 705 * observed} usage has stopped and an additional {@code 706 * sessionThresholdTime} has passed. The delivered Intent will 707 * also contain the extras {@link #EXTRA_OBSERVER_ID} and {@link 708 * #EXTRA_TIME_USED}. Can be null. 709 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and 710 * is not the profile owner of this user. 711 * @hide 712 */ 713 @SystemApi 714 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) registerUsageSessionObserver(int sessionObserverId, @NonNull String[] observedEntities, @NonNull Duration timeLimit, @NonNull Duration sessionThresholdTime, @NonNull PendingIntent limitReachedCallbackIntent, @Nullable PendingIntent sessionEndCallbackIntent)715 public void registerUsageSessionObserver(int sessionObserverId, 716 @NonNull String[] observedEntities, @NonNull Duration timeLimit, 717 @NonNull Duration sessionThresholdTime, 718 @NonNull PendingIntent limitReachedCallbackIntent, 719 @Nullable PendingIntent sessionEndCallbackIntent) { 720 try { 721 mService.registerUsageSessionObserver(sessionObserverId, observedEntities, 722 timeLimit.toMillis(), sessionThresholdTime.toMillis(), 723 limitReachedCallbackIntent, sessionEndCallbackIntent, 724 mContext.getOpPackageName()); 725 } catch (RemoteException e) { 726 throw e.rethrowFromSystemServer(); 727 } 728 } 729 730 /** 731 * Unregister the usage session observer specified by the {@code sessionObserverId}. This will 732 * only apply to any app session observer registered by this application. Unregistering an 733 * observer that was already unregistered or never registered will have no effect. 734 * 735 * @param sessionObserverId The id of the observer that was previously registered. 736 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and 737 * is not the profile owner of this user. 738 * @hide 739 */ 740 @SystemApi 741 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) unregisterUsageSessionObserver(int sessionObserverId)742 public void unregisterUsageSessionObserver(int sessionObserverId) { 743 try { 744 mService.unregisterUsageSessionObserver(sessionObserverId, mContext.getOpPackageName()); 745 } catch (RemoteException e) { 746 throw e.rethrowFromSystemServer(); 747 } 748 } 749 750 /** 751 * Register a usage limit observer that receives a callback on the provided intent when the 752 * sum of usages of apps and tokens in the provided {@code observedEntities} array exceeds the 753 * {@code timeLimit} specified. The structure of a token is a {@link String} with the reporting 754 * package's name and a token that the calling app will use, separated by the forward slash 755 * character. Example: com.reporting.package/5OM3*0P4QU3-7OK3N 756 * <p> 757 * Registering an {@code observerId} that was already registered will override the previous one. 758 * No more than 1000 unique {@code observerId} may be registered by a single uid 759 * at any one time. 760 * A limit is not cleared when the usage time is exceeded. It needs to be unregistered via 761 * {@link #unregisterAppUsageLimitObserver}. 762 * <p> 763 * Note: usage limits are not persisted in the system and are cleared on reboots. Callers 764 * must reset any limits that they need on reboots. 765 * <p> 766 * This method is similar to {@link #registerAppUsageObserver}, but the usage limit set here 767 * will be visible to the launcher so that it can report the limit to the user and how much 768 * of it is remaining. 769 * @see android.content.pm.LauncherApps#getAppUsageLimit 770 * 771 * @param observerId A unique id associated with the group of apps to be monitored. There can 772 * be multiple groups with common packages and different time limits. 773 * @param observedEntities The list of packages and token to observe for usage time. Cannot be 774 * null and must include at least one package or token. 775 * @param timeLimit The total time the set of apps can be in the foreground before the 776 * {@code callbackIntent} is delivered. Must be at least one minute. 777 * @param timeUsed The time that has already been used by the set of apps in 778 * {@code observedEntities}. Note: a time used equal to or greater than 779 * {@code timeLimit} can be set to indicate that the user has already exhausted 780 * the limit for a group, in which case, the given {@code callbackIntent} will 781 * be ignored. 782 * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is 783 * exceeded by the group of apps. The delivered Intent will also contain 784 * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and 785 * {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is 786 * being registered with a {@code timeUsed} equal to or greater than 787 * {@code timeLimit}. 788 * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE 789 * permissions. 790 * @hide 791 */ 792 @SystemApi 793 @RequiresPermission(allOf = { 794 android.Manifest.permission.SUSPEND_APPS, 795 android.Manifest.permission.OBSERVE_APP_USAGE}) registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities, @NonNull Duration timeLimit, @NonNull Duration timeUsed, @Nullable PendingIntent callbackIntent)796 public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities, 797 @NonNull Duration timeLimit, @NonNull Duration timeUsed, 798 @Nullable PendingIntent callbackIntent) { 799 try { 800 mService.registerAppUsageLimitObserver(observerId, observedEntities, 801 timeLimit.toMillis(), timeUsed.toMillis(), callbackIntent, 802 mContext.getOpPackageName()); 803 } catch (RemoteException e) { 804 throw e.rethrowFromSystemServer(); 805 } 806 } 807 808 /** 809 * Unregister the app usage limit observer specified by the {@code observerId}. 810 * This will only apply to any observer registered by this application. Unregistering 811 * an observer that was already unregistered or never registered will have no effect. 812 * 813 * @param observerId The id of the observer that was previously registered. 814 * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE 815 * permissions. 816 * @hide 817 */ 818 @SystemApi 819 @RequiresPermission(allOf = { 820 android.Manifest.permission.SUSPEND_APPS, 821 android.Manifest.permission.OBSERVE_APP_USAGE}) unregisterAppUsageLimitObserver(int observerId)822 public void unregisterAppUsageLimitObserver(int observerId) { 823 try { 824 mService.unregisterAppUsageLimitObserver(observerId, mContext.getOpPackageName()); 825 } catch (RemoteException e) { 826 throw e.rethrowFromSystemServer(); 827 } 828 } 829 830 /** 831 * Report usage associated with a particular {@code token} has started. Tokens are app defined 832 * strings used to represent usage of in-app features. Apps with the {@link 833 * android.Manifest.permission#OBSERVE_APP_USAGE} permission can register time limit observers 834 * to monitor the usage of a token. In app usage can only associated with an {@code activity} 835 * and usage will be considered stopped if the activity stops or crashes. 836 * @see #registerAppUsageObserver 837 * @see #registerUsageSessionObserver 838 * @see #registerAppUsageLimitObserver 839 * 840 * @param activity The activity {@code token} is associated with. 841 * @param token The token to report usage against. 842 * @hide 843 */ 844 @SystemApi reportUsageStart(@onNull Activity activity, @NonNull String token)845 public void reportUsageStart(@NonNull Activity activity, @NonNull String token) { 846 try { 847 mService.reportUsageStart(activity.getActivityToken(), token, 848 mContext.getOpPackageName()); 849 } catch (RemoteException e) { 850 throw e.rethrowFromSystemServer(); 851 } 852 } 853 854 /** 855 * Report usage associated with a particular {@code token} had started some amount of time in 856 * the past. Tokens are app defined strings used to represent usage of in-app features. Apps 857 * with the {@link android.Manifest.permission#OBSERVE_APP_USAGE} permission can register time 858 * limit observers to monitor the usage of a token. In app usage can only associated with an 859 * {@code activity} and usage will be considered stopped if the activity stops or crashes. 860 * @see #registerAppUsageObserver 861 * @see #registerUsageSessionObserver 862 * @see #registerAppUsageLimitObserver 863 * 864 * @param activity The activity {@code token} is associated with. 865 * @param token The token to report usage against. 866 * @param timeAgoMs How long ago the start of usage took place 867 * @hide 868 */ 869 @SystemApi reportUsageStart(@onNull Activity activity, @NonNull String token, long timeAgoMs)870 public void reportUsageStart(@NonNull Activity activity, @NonNull String token, 871 long timeAgoMs) { 872 try { 873 mService.reportPastUsageStart(activity.getActivityToken(), token, timeAgoMs, 874 mContext.getOpPackageName()); 875 } catch (RemoteException e) { 876 throw e.rethrowFromSystemServer(); 877 } 878 } 879 880 /** 881 * Report the usage associated with a particular {@code token} has stopped. 882 * 883 * @param activity The activity {@code token} is associated with. 884 * @param token The token to report usage against. 885 * @hide 886 */ 887 @SystemApi reportUsageStop(@onNull Activity activity, @NonNull String token)888 public void reportUsageStop(@NonNull Activity activity, @NonNull String token) { 889 try { 890 mService.reportUsageStop(activity.getActivityToken(), token, 891 mContext.getOpPackageName()); 892 } catch (RemoteException e) { 893 throw e.rethrowFromSystemServer(); 894 } 895 } 896 897 /** 898 * Get what App Usage Observers will consider the source of usage for an activity. Usage Source 899 * is decided at boot and will not change until next boot. 900 * @see #USAGE_SOURCE_TASK_ROOT_ACTIVITY 901 * @see #USAGE_SOURCE_CURRENT_ACTIVITY 902 * 903 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and 904 * is not the profile owner of this user. 905 * @hide 906 */ 907 @SystemApi getUsageSource()908 public @UsageSource int getUsageSource() { 909 try { 910 return mService.getUsageSource(); 911 } catch (RemoteException e) { 912 throw e.rethrowFromSystemServer(); 913 } 914 } 915 916 /** 917 * Force the Usage Source be reread from global settings. 918 * @hide 919 */ 920 @TestApi forceUsageSourceSettingRead()921 public void forceUsageSourceSettingRead() { 922 try { 923 mService.forceUsageSourceSettingRead(); 924 } catch (RemoteException e) { 925 throw e.rethrowFromSystemServer(); 926 } 927 } 928 929 /** @hide */ reasonToString(int standbyReason)930 public static String reasonToString(int standbyReason) { 931 StringBuilder sb = new StringBuilder(); 932 switch (standbyReason & REASON_MAIN_MASK) { 933 case REASON_MAIN_DEFAULT: 934 sb.append("d"); 935 break; 936 case REASON_MAIN_FORCED: 937 sb.append("f"); 938 break; 939 case REASON_MAIN_PREDICTED: 940 sb.append("p"); 941 switch (standbyReason & REASON_SUB_MASK) { 942 case REASON_SUB_PREDICTED_RESTORED: 943 sb.append("-r"); 944 break; 945 } 946 break; 947 case REASON_MAIN_TIMEOUT: 948 sb.append("t"); 949 break; 950 case REASON_MAIN_USAGE: 951 sb.append("u"); 952 switch (standbyReason & REASON_SUB_MASK) { 953 case REASON_SUB_USAGE_SYSTEM_INTERACTION: 954 sb.append("-si"); 955 break; 956 case REASON_SUB_USAGE_NOTIFICATION_SEEN: 957 sb.append("-ns"); 958 break; 959 case REASON_SUB_USAGE_USER_INTERACTION: 960 sb.append("-ui"); 961 break; 962 case REASON_SUB_USAGE_MOVE_TO_FOREGROUND: 963 sb.append("-mf"); 964 break; 965 case REASON_SUB_USAGE_MOVE_TO_BACKGROUND: 966 sb.append("-mb"); 967 break; 968 case REASON_SUB_USAGE_SYSTEM_UPDATE: 969 sb.append("-su"); 970 break; 971 case REASON_SUB_USAGE_ACTIVE_TIMEOUT: 972 sb.append("-at"); 973 break; 974 case REASON_SUB_USAGE_SYNC_ADAPTER: 975 sb.append("-sa"); 976 break; 977 case REASON_SUB_USAGE_SLICE_PINNED: 978 sb.append("-lp"); 979 break; 980 case REASON_SUB_USAGE_SLICE_PINNED_PRIV: 981 sb.append("-lv"); 982 break; 983 case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE: 984 sb.append("-en"); 985 break; 986 case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE: 987 sb.append("-ed"); 988 break; 989 case REASON_SUB_USAGE_EXEMPTED_SYNC_START: 990 sb.append("-es"); 991 break; 992 case REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED: 993 sb.append("-uss"); 994 break; 995 case REASON_SUB_USAGE_FOREGROUND_SERVICE_START: 996 sb.append("-fss"); 997 break; 998 } 999 break; 1000 } 1001 return sb.toString(); 1002 } 1003 1004 /** @hide */ usageSourceToString(int usageSource)1005 public static String usageSourceToString(int usageSource) { 1006 switch (usageSource) { 1007 case USAGE_SOURCE_TASK_ROOT_ACTIVITY: 1008 return "TASK_ROOT_ACTIVITY"; 1009 case USAGE_SOURCE_CURRENT_ACTIVITY: 1010 return "CURRENT_ACTIVITY"; 1011 default: 1012 StringBuilder sb = new StringBuilder(); 1013 sb.append("UNKNOWN("); 1014 sb.append(usageSource); 1015 sb.append(")"); 1016 return sb.toString(); 1017 } 1018 } 1019 1020 /** 1021 * {@hide} 1022 * Temporarily whitelist the specified app for a short duration. This is to allow an app 1023 * receiving a high priority message to be able to access the network and acquire wakelocks 1024 * even if the device is in power-save mode or the app is currently considered inactive. 1025 * @param packageName The package name of the app to whitelist. 1026 * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that 1027 * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes. 1028 * @param user The user for whom the package should be whitelisted. Passing in a user that is 1029 * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission. 1030 * @see #isAppInactive(String) 1031 */ 1032 @SystemApi 1033 @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) whitelistAppTemporarily(String packageName, long duration, UserHandle user)1034 public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) { 1035 try { 1036 mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier()); 1037 } catch (RemoteException re) { 1038 throw re.rethrowFromSystemServer(); 1039 } 1040 } 1041 1042 /** 1043 * Inform usage stats that the carrier privileged apps access rules have changed. 1044 * @hide 1045 */ onCarrierPrivilegedAppsChanged()1046 public void onCarrierPrivilegedAppsChanged() { 1047 try { 1048 mService.onCarrierPrivilegedAppsChanged(); 1049 } catch (RemoteException re) { 1050 throw re.rethrowFromSystemServer(); 1051 } 1052 } 1053 1054 /** 1055 * Reports a Chooser action to the UsageStatsManager. 1056 * 1057 * @param packageName The package name of the app that is selected. 1058 * @param userId The user id of who makes the selection. 1059 * @param contentType The type of the content, e.g., Image, Video, App. 1060 * @param annotations The annotations of the content, e.g., Game, Selfie. 1061 * @param action The action type of Intent that invokes ChooserActivity. 1062 * {@link UsageEvents} 1063 * @hide 1064 */ reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1065 public void reportChooserSelection(String packageName, int userId, String contentType, 1066 String[] annotations, String action) { 1067 try { 1068 mService.reportChooserSelection(packageName, userId, contentType, annotations, action); 1069 } catch (RemoteException re) { 1070 } 1071 } 1072 } 1073