UsageStatsManager.java revision ced54398cc0dfd2f782153560c2ffd0eb8743045
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 17package android.app.usage; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.annotation.RequiresPermission; 22import android.annotation.SystemApi; 23import android.annotation.SystemService; 24import android.app.PendingIntent; 25import android.content.Context; 26import android.content.pm.ParceledListSlice; 27import android.os.RemoteException; 28import android.os.UserHandle; 29import android.util.ArrayMap; 30 31import java.lang.annotation.Retention; 32import java.lang.annotation.RetentionPolicy; 33import java.util.ArrayList; 34import java.util.Collections; 35import java.util.List; 36import java.util.Map; 37import java.util.concurrent.TimeUnit; 38 39/** 40 * Provides access to device usage history and statistics. Usage data is aggregated into 41 * time intervals: days, weeks, months, and years. 42 * <p /> 43 * When requesting usage data since a particular time, the request might look something like this: 44 * <pre> 45 * PAST REQUEST_TIME TODAY FUTURE 46 * ————————————————————————————||———————————————————————————¦-----------------------| 47 * YEAR || ¦ | 48 * ————————————————————————————||———————————————————————————¦-----------------------| 49 * MONTH | || MONTH ¦ | 50 * ——————————————————|—————————||———————————————————————————¦-----------------------| 51 * | WEEK | WEEK|| | WEEK | WE¦EK | WEEK | 52 * ————————————————————————————||———————————————————|———————¦-----------------------| 53 * || |DAY|DAY|DAY|DAY¦DAY|DAY|DAY|DAY|DAY|DAY| 54 * ————————————————————————————||———————————————————————————¦-----------------------| 55 * </pre> 56 * A request for data in the middle of a time interval will include that interval. 57 * <p/> 58 * <b>NOTE:</b> Most methods on this API require the permission 59 * android.permission.PACKAGE_USAGE_STATS. However, declaring the permission implies intention to 60 * use the API and the user of the device still needs to grant permission through the Settings 61 * application. 62 * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}. 63 * Methods which only return the information for the calling package do not require this permission. 64 * E.g. {@link #getAppStandbyBucket()} and {@link #queryEventsForSelf(long, long)}. 65 */ 66@SystemService(Context.USAGE_STATS_SERVICE) 67public final class UsageStatsManager { 68 69 /** 70 * An interval type that spans a day. See {@link #queryUsageStats(int, long, long)}. 71 */ 72 public static final int INTERVAL_DAILY = 0; 73 74 /** 75 * An interval type that spans a week. See {@link #queryUsageStats(int, long, long)}. 76 */ 77 public static final int INTERVAL_WEEKLY = 1; 78 79 /** 80 * An interval type that spans a month. See {@link #queryUsageStats(int, long, long)}. 81 */ 82 public static final int INTERVAL_MONTHLY = 2; 83 84 /** 85 * An interval type that spans a year. See {@link #queryUsageStats(int, long, long)}. 86 */ 87 public static final int INTERVAL_YEARLY = 3; 88 89 /** 90 * An interval type that will use the best fit interval for the given time range. 91 * See {@link #queryUsageStats(int, long, long)}. 92 */ 93 public static final int INTERVAL_BEST = 4; 94 95 /** 96 * The number of available intervals. Does not include {@link #INTERVAL_BEST}, since it 97 * is a pseudo interval (it actually selects a real interval). 98 * {@hide} 99 */ 100 public static final int INTERVAL_COUNT = 4; 101 102 103 /** 104 * The app is whitelisted for some reason and the bucket cannot be changed. 105 * {@hide} 106 */ 107 @SystemApi 108 public static final int STANDBY_BUCKET_EXEMPTED = 5; 109 110 /** 111 * The app was used very recently, currently in use or likely to be used very soon. Standby 112 * bucket values that are ≤ {@link #STANDBY_BUCKET_ACTIVE} will not be throttled by the 113 * system while they are in this bucket. Buckets > {@link #STANDBY_BUCKET_ACTIVE} will most 114 * likely be restricted in some way. For instance, jobs and alarms may be deferred. 115 * @see #getAppStandbyBucket() 116 */ 117 public static final int STANDBY_BUCKET_ACTIVE = 10; 118 119 /** 120 * The app was used recently and/or likely to be used in the next few hours. Restrictions will 121 * apply to these apps, such as deferral of jobs and alarms. 122 * @see #getAppStandbyBucket() 123 */ 124 public static final int STANDBY_BUCKET_WORKING_SET = 20; 125 126 /** 127 * The app was used in the last few days and/or likely to be used in the next few days. 128 * Restrictions will apply to these apps, such as deferral of jobs and alarms. The delays may be 129 * greater than for apps in higher buckets (lower bucket value). Bucket values > 130 * {@link #STANDBY_BUCKET_FREQUENT} may additionally have network access limited. 131 * @see #getAppStandbyBucket() 132 */ 133 public static final int STANDBY_BUCKET_FREQUENT = 30; 134 135 /** 136 * The app has not be used for several days and/or is unlikely to be used for several days. 137 * Apps in this bucket will have the most restrictions, including network restrictions, except 138 * during certain short periods (at a minimum, once a day) when they are allowed to execute 139 * jobs, access the network, etc. 140 * @see #getAppStandbyBucket() 141 */ 142 public static final int STANDBY_BUCKET_RARE = 40; 143 144 /** 145 * The app has never been used. 146 * {@hide} 147 */ 148 @SystemApi 149 public static final int STANDBY_BUCKET_NEVER = 50; 150 151 /** @hide */ 152 public static final int REASON_MAIN_MASK = 0xFF00; 153 /** @hide */ 154 public static final int REASON_MAIN_DEFAULT = 0x0100; 155 /** @hide */ 156 public static final int REASON_MAIN_TIMEOUT = 0x0200; 157 /** @hide */ 158 public static final int REASON_MAIN_USAGE = 0x0300; 159 /** @hide */ 160 public static final int REASON_MAIN_FORCED = 0x0400; 161 /** @hide */ 162 public static final int REASON_MAIN_PREDICTED = 0x0500; 163 164 /** @hide */ 165 public static final int REASON_SUB_MASK = 0x00FF; 166 /** @hide */ 167 public static final int REASON_SUB_USAGE_SYSTEM_INTERACTION = 0x0001; 168 /** @hide */ 169 public static final int REASON_SUB_USAGE_NOTIFICATION_SEEN = 0x0002; 170 /** @hide */ 171 public static final int REASON_SUB_USAGE_USER_INTERACTION = 0x0003; 172 /** @hide */ 173 public static final int REASON_SUB_USAGE_MOVE_TO_FOREGROUND = 0x0004; 174 /** @hide */ 175 public static final int REASON_SUB_USAGE_MOVE_TO_BACKGROUND = 0x0005; 176 /** @hide */ 177 public static final int REASON_SUB_USAGE_SYSTEM_UPDATE = 0x0006; 178 /** @hide */ 179 public static final int REASON_SUB_USAGE_ACTIVE_TIMEOUT = 0x0007; 180 /** @hide */ 181 public static final int REASON_SUB_USAGE_SYNC_ADAPTER = 0x0008; 182 183 /** @hide */ 184 @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = { 185 STANDBY_BUCKET_EXEMPTED, 186 STANDBY_BUCKET_ACTIVE, 187 STANDBY_BUCKET_WORKING_SET, 188 STANDBY_BUCKET_FREQUENT, 189 STANDBY_BUCKET_RARE, 190 STANDBY_BUCKET_NEVER, 191 }) 192 @Retention(RetentionPolicy.SOURCE) 193 public @interface StandbyBuckets {} 194 195 /** 196 * Observer id of the registered observer for the group of packages that reached the usage 197 * time limit. Included as an extra in the PendingIntent that was registered. 198 * @hide 199 */ 200 @SystemApi 201 public static final String EXTRA_OBSERVER_ID = "android.app.usage.extra.OBSERVER_ID"; 202 203 /** 204 * Original time limit in milliseconds specified by the registered observer for the group of 205 * packages that reached the usage time limit. Included as an extra in the PendingIntent that 206 * was registered. 207 * @hide 208 */ 209 @SystemApi 210 public static final String EXTRA_TIME_LIMIT = "android.app.usage.extra.TIME_LIMIT"; 211 212 /** 213 * Actual usage time in milliseconds for the group of packages that reached the specified time 214 * limit. Included as an extra in the PendingIntent that was registered. 215 * @hide 216 */ 217 @SystemApi 218 public static final String EXTRA_TIME_USED = "android.app.usage.extra.TIME_USED"; 219 220 private static final UsageEvents sEmptyResults = new UsageEvents(); 221 222 private final Context mContext; 223 private final IUsageStatsManager mService; 224 225 /** 226 * {@hide} 227 */ 228 public UsageStatsManager(Context context, IUsageStatsManager service) { 229 mContext = context; 230 mService = service; 231 } 232 233 /** 234 * Gets application usage stats for the given time range, aggregated by the specified interval. 235 * <p>The returned list will contain a {@link UsageStats} object for each package that 236 * has data for an interval that is a subset of the time range given. To illustrate:</p> 237 * <pre> 238 * intervalType = INTERVAL_YEARLY 239 * beginTime = 2013 240 * endTime = 2015 (exclusive) 241 * 242 * Results: 243 * 2013 - com.example.alpha 244 * 2013 - com.example.beta 245 * 2014 - com.example.alpha 246 * 2014 - com.example.beta 247 * 2014 - com.example.charlie 248 * </pre> 249 * 250 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 251 * 252 * @param intervalType The time interval by which the stats are aggregated. 253 * @param beginTime The inclusive beginning of the range of stats to include in the results. 254 * @param endTime The exclusive end of the range of stats to include in the results. 255 * @return A list of {@link UsageStats} 256 * 257 * @see #INTERVAL_DAILY 258 * @see #INTERVAL_WEEKLY 259 * @see #INTERVAL_MONTHLY 260 * @see #INTERVAL_YEARLY 261 * @see #INTERVAL_BEST 262 */ 263 public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) { 264 try { 265 @SuppressWarnings("unchecked") 266 ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime, 267 endTime, mContext.getOpPackageName()); 268 if (slice != null) { 269 return slice.getList(); 270 } 271 } catch (RemoteException e) { 272 // fallthrough and return the empty list. 273 } 274 return Collections.emptyList(); 275 } 276 277 /** 278 * Gets the hardware configurations the device was in for the given time range, aggregated by 279 * the specified interval. The results are ordered as in 280 * {@link #queryUsageStats(int, long, long)}. 281 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 282 * 283 * @param intervalType The time interval by which the stats are aggregated. 284 * @param beginTime The inclusive beginning of the range of stats to include in the results. 285 * @param endTime The exclusive end of the range of stats to include in the results. 286 * @return A list of {@link ConfigurationStats} 287 */ 288 public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime, 289 long endTime) { 290 try { 291 @SuppressWarnings("unchecked") 292 ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats( 293 intervalType, beginTime, endTime, mContext.getOpPackageName()); 294 if (slice != null) { 295 return slice.getList(); 296 } 297 } catch (RemoteException e) { 298 // fallthrough and return the empty list. 299 } 300 return Collections.emptyList(); 301 } 302 303 /** 304 * Gets aggregated event stats for the given time range, aggregated by the specified interval. 305 * <p>The returned list will contain a {@link EventStats} object for each event type that 306 * is being aggregated and has data for an interval that is a subset of the time range given. 307 * 308 * <p>The current event types that will be aggregated here are:</p> 309 * <ul> 310 * <li>{@link UsageEvents.Event#SCREEN_INTERACTIVE}</li> 311 * <li>{@link UsageEvents.Event#SCREEN_NON_INTERACTIVE}</li> 312 * </ul> 313 * 314 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 315 * 316 * @param intervalType The time interval by which the stats are aggregated. 317 * @param beginTime The inclusive beginning of the range of stats to include in the results. 318 * @param endTime The exclusive end of the range of stats to include in the results. 319 * @return A list of {@link EventStats} 320 * 321 * @see #INTERVAL_DAILY 322 * @see #INTERVAL_WEEKLY 323 * @see #INTERVAL_MONTHLY 324 * @see #INTERVAL_YEARLY 325 * @see #INTERVAL_BEST 326 */ 327 public List<EventStats> queryEventStats(int intervalType, long beginTime, long endTime) { 328 try { 329 @SuppressWarnings("unchecked") 330 ParceledListSlice<EventStats> slice = mService.queryEventStats(intervalType, beginTime, 331 endTime, mContext.getOpPackageName()); 332 if (slice != null) { 333 return slice.getList(); 334 } 335 } catch (RemoteException e) { 336 // fallthrough and return the empty list. 337 } 338 return Collections.emptyList(); 339 } 340 341 /** 342 * Query for events in the given time range. Events are only kept by the system for a few 343 * days. 344 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 345 * 346 * @param beginTime The inclusive beginning of the range of events to include in the results. 347 * @param endTime The exclusive end of the range of events to include in the results. 348 * @return A {@link UsageEvents}. 349 */ 350 public UsageEvents queryEvents(long beginTime, long endTime) { 351 try { 352 UsageEvents iter = mService.queryEvents(beginTime, endTime, 353 mContext.getOpPackageName()); 354 if (iter != null) { 355 return iter; 356 } 357 } catch (RemoteException e) { 358 // fallthrough and return empty result. 359 } 360 return sEmptyResults; 361 } 362 363 /** 364 * Like {@link #queryEvents(long, long)}, but only returns events for the calling package. 365 * 366 * @param beginTime The inclusive beginning of the range of events to include in the results. 367 * @param endTime The exclusive end of the range of events to include in the results. 368 * @return A {@link UsageEvents} object. 369 * 370 * @see #queryEvents(long, long) 371 */ 372 public UsageEvents queryEventsForSelf(long beginTime, long endTime) { 373 try { 374 final UsageEvents events = mService.queryEventsForPackage(beginTime, endTime, 375 mContext.getOpPackageName()); 376 if (events != null) { 377 return events; 378 } 379 } catch (RemoteException e) { 380 // fallthrough 381 } 382 return sEmptyResults; 383 } 384 385 /** 386 * A convenience method that queries for all stats in the given range (using the best interval 387 * for that range), merges the resulting data, and keys it by package name. 388 * See {@link #queryUsageStats(int, long, long)}. 389 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p> 390 * 391 * @param beginTime The inclusive beginning of the range of stats to include in the results. 392 * @param endTime The exclusive end of the range of stats to include in the results. 393 * @return A {@link java.util.Map} keyed by package name 394 */ 395 public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) { 396 List<UsageStats> stats = queryUsageStats(INTERVAL_BEST, beginTime, endTime); 397 if (stats.isEmpty()) { 398 return Collections.emptyMap(); 399 } 400 401 ArrayMap<String, UsageStats> aggregatedStats = new ArrayMap<>(); 402 final int statCount = stats.size(); 403 for (int i = 0; i < statCount; i++) { 404 UsageStats newStat = stats.get(i); 405 UsageStats existingStat = aggregatedStats.get(newStat.getPackageName()); 406 if (existingStat == null) { 407 aggregatedStats.put(newStat.mPackageName, newStat); 408 } else { 409 existingStat.add(newStat); 410 } 411 } 412 return aggregatedStats; 413 } 414 415 /** 416 * Returns whether the specified app is currently considered inactive. This will be true if the 417 * app hasn't been used directly or indirectly for a period of time defined by the system. This 418 * could be of the order of several hours or days. 419 * @param packageName The package name of the app to query 420 * @return whether the app is currently considered inactive 421 */ 422 public boolean isAppInactive(String packageName) { 423 try { 424 return mService.isAppInactive(packageName, mContext.getUserId()); 425 } catch (RemoteException e) { 426 // fall through and return default 427 } 428 return false; 429 } 430 431 /** 432 * {@hide} 433 */ 434 public void setAppInactive(String packageName, boolean inactive) { 435 try { 436 mService.setAppInactive(packageName, inactive, mContext.getUserId()); 437 } catch (RemoteException e) { 438 // fall through 439 } 440 } 441 442 /** 443 * Returns the current standby bucket of the calling app. The system determines the standby 444 * state of the app based on app usage patterns. Standby buckets determine how much an app will 445 * be restricted from running background tasks such as jobs and alarms. 446 * <p>Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to 447 * {@link #STANDBY_BUCKET_RARE}, with {@link #STANDBY_BUCKET_ACTIVE} being the least 448 * restrictive. The battery level of the device might also affect the restrictions. 449 * <p>Apps in buckets ≤ {@link #STANDBY_BUCKET_ACTIVE} have no standby restrictions imposed. 450 * Apps in buckets > {@link #STANDBY_BUCKET_FREQUENT} may have network access restricted when 451 * running in the background. 452 * <p>The standby state of an app can change at any time either due to a user interaction or a 453 * system interaction or some algorithm determining that the app can be restricted for a period 454 * of time before the user has a need for it. 455 * <p>You can also query the recent history of standby bucket changes by calling 456 * {@link #queryEventsForSelf(long, long)} and searching for 457 * {@link UsageEvents.Event#STANDBY_BUCKET_CHANGED}. 458 * 459 * @return the current standby bucket of the calling app. One of STANDBY_BUCKET_* constants. 460 */ 461 public @StandbyBuckets int getAppStandbyBucket() { 462 try { 463 return mService.getAppStandbyBucket(mContext.getOpPackageName(), 464 mContext.getOpPackageName(), 465 mContext.getUserId()); 466 } catch (RemoteException e) { 467 } 468 return STANDBY_BUCKET_ACTIVE; 469 } 470 471 /** 472 * {@hide} 473 * Returns the current standby bucket of the specified app. The caller must hold the permission 474 * android.permission.PACKAGE_USAGE_STATS. 475 * @param packageName the package for which to fetch the current standby bucket. 476 */ 477 @SystemApi 478 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) 479 public @StandbyBuckets int getAppStandbyBucket(String packageName) { 480 try { 481 return mService.getAppStandbyBucket(packageName, mContext.getOpPackageName(), 482 mContext.getUserId()); 483 } catch (RemoteException e) { 484 } 485 return STANDBY_BUCKET_ACTIVE; 486 } 487 488 /** 489 * {@hide} 490 * Changes an app's standby bucket to the provided value. The caller can only set the standby 491 * bucket for a different app than itself. 492 * @param packageName the package name of the app to set the bucket for. A SecurityException 493 * will be thrown if the package name is that of the caller. 494 * @param bucket the standby bucket to set it to, which should be one of STANDBY_BUCKET_*. 495 * Setting a standby bucket outside of the range of STANDBY_BUCKET_ACTIVE to 496 * STANDBY_BUCKET_NEVER will result in a SecurityException. 497 */ 498 @SystemApi 499 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) 500 public void setAppStandbyBucket(String packageName, @StandbyBuckets int bucket) { 501 try { 502 mService.setAppStandbyBucket(packageName, bucket, mContext.getUserId()); 503 } catch (RemoteException e) { 504 // Nothing to do 505 } 506 } 507 508 /** 509 * {@hide} 510 * Returns the current standby bucket of every app that has a bucket assigned to it. 511 * The caller must hold the permission android.permission.PACKAGE_USAGE_STATS. The key of the 512 * returned Map is the package name and the value is the bucket assigned to the package. 513 * @see #getAppStandbyBucket() 514 */ 515 @SystemApi 516 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) 517 public Map<String, Integer> getAppStandbyBuckets() { 518 try { 519 final ParceledListSlice<AppStandbyInfo> slice = mService.getAppStandbyBuckets( 520 mContext.getOpPackageName(), mContext.getUserId()); 521 final List<AppStandbyInfo> bucketList = slice.getList(); 522 final ArrayMap<String, Integer> bucketMap = new ArrayMap<>(); 523 final int n = bucketList.size(); 524 for (int i = 0; i < n; i++) { 525 final AppStandbyInfo bucketInfo = bucketList.get(i); 526 bucketMap.put(bucketInfo.mPackageName, bucketInfo.mStandbyBucket); 527 } 528 return bucketMap; 529 } catch (RemoteException e) { 530 } 531 return Collections.EMPTY_MAP; 532 } 533 534 /** 535 * {@hide} 536 * Changes the app standby bucket for multiple apps at once. The Map is keyed by the package 537 * name and the value is one of STANDBY_BUCKET_*. 538 * @param appBuckets a map of package name to bucket value. 539 */ 540 @SystemApi 541 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) 542 public void setAppStandbyBuckets(Map<String, Integer> appBuckets) { 543 if (appBuckets == null) { 544 return; 545 } 546 final List<AppStandbyInfo> bucketInfoList = new ArrayList<>(appBuckets.size()); 547 for (Map.Entry<String, Integer> bucketEntry : appBuckets.entrySet()) { 548 bucketInfoList.add(new AppStandbyInfo(bucketEntry.getKey(), bucketEntry.getValue())); 549 } 550 final ParceledListSlice<AppStandbyInfo> slice = new ParceledListSlice<>(bucketInfoList); 551 try { 552 mService.setAppStandbyBuckets(slice, mContext.getUserId()); 553 } catch (RemoteException e) { 554 } 555 } 556 557 /** 558 * @hide 559 * Register an app usage limit observer that receives a callback on the provided intent when 560 * the sum of usages of apps in the packages array exceeds the {@code timeLimit} specified. The 561 * observer will automatically be unregistered when the time limit is reached and the intent 562 * is delivered. Registering an {@code observerId} that was already registered will override 563 * the previous one. 564 * @param observerId A unique id associated with the group of apps to be monitored. There can 565 * be multiple groups with common packages and different time limits. 566 * @param packages The list of packages to observe for foreground activity time. Cannot be null 567 * and must include at least one package. 568 * @param timeLimit The total time the set of apps can be in the foreground before the 569 * callbackIntent is delivered. Must be greater than 0. 570 * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null. 571 * @param callbackIntent The PendingIntent that will be dispatched when the time limit is 572 * exceeded by the group of apps. The delivered Intent will also contain 573 * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and 574 * {@link #EXTRA_TIME_USED}. Cannot be null. 575 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or 576 * is not the profile owner of this user. 577 */ 578 @SystemApi 579 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) 580 public void registerAppUsageObserver(int observerId, @NonNull String[] packages, long timeLimit, 581 @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent) { 582 try { 583 mService.registerAppUsageObserver(observerId, packages, timeUnit.toMillis(timeLimit), 584 callbackIntent, mContext.getOpPackageName()); 585 } catch (RemoteException e) { 586 } 587 } 588 589 /** 590 * @hide 591 * Unregister the app usage observer specified by the {@code observerId}. This will only apply 592 * to any observer registered by this application. Unregistering an observer that was already 593 * unregistered or never registered will have no effect. 594 * @param observerId The id of the observer that was previously registered. 595 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or is 596 * not the profile owner of this user. 597 */ 598 @SystemApi 599 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) 600 public void unregisterAppUsageObserver(int observerId) { 601 try { 602 mService.unregisterAppUsageObserver(observerId, mContext.getOpPackageName()); 603 } catch (RemoteException e) { 604 } 605 } 606 607 /** @hide */ 608 public static String reasonToString(int standbyReason) { 609 StringBuilder sb = new StringBuilder(); 610 switch (standbyReason & REASON_MAIN_MASK) { 611 case REASON_MAIN_DEFAULT: 612 sb.append("d"); 613 break; 614 case REASON_MAIN_FORCED: 615 sb.append("f"); 616 break; 617 case REASON_MAIN_PREDICTED: 618 sb.append("p"); 619 break; 620 case REASON_MAIN_TIMEOUT: 621 sb.append("t"); 622 break; 623 case REASON_MAIN_USAGE: 624 sb.append("u-"); 625 switch (standbyReason & REASON_SUB_MASK) { 626 case REASON_SUB_USAGE_SYSTEM_INTERACTION: 627 sb.append("si"); 628 break; 629 case REASON_SUB_USAGE_NOTIFICATION_SEEN: 630 sb.append("ns"); 631 break; 632 case REASON_SUB_USAGE_USER_INTERACTION: 633 sb.append("ui"); 634 break; 635 case REASON_SUB_USAGE_MOVE_TO_FOREGROUND: 636 sb.append("mf"); 637 break; 638 case REASON_SUB_USAGE_MOVE_TO_BACKGROUND: 639 sb.append("mb"); 640 break; 641 case REASON_SUB_USAGE_SYSTEM_UPDATE: 642 sb.append("su"); 643 break; 644 case REASON_SUB_USAGE_ACTIVE_TIMEOUT: 645 sb.append("at"); 646 break; 647 case REASON_SUB_USAGE_SYNC_ADAPTER: 648 sb.append("sa"); 649 break; 650 } 651 break; 652 } 653 return sb.toString(); 654 } 655 656 /** 657 * {@hide} 658 * Temporarily whitelist the specified app for a short duration. This is to allow an app 659 * receiving a high priority message to be able to access the network and acquire wakelocks 660 * even if the device is in power-save mode or the app is currently considered inactive. 661 * @param packageName The package name of the app to whitelist. 662 * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that 663 * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes. 664 * @param user The user for whom the package should be whitelisted. Passing in a user that is 665 * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission. 666 * @see #isAppInactive(String) 667 */ 668 @SystemApi 669 @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) 670 public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) { 671 try { 672 mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier()); 673 } catch (RemoteException re) { 674 } 675 } 676 677 /** 678 * Inform usage stats that the carrier privileged apps access rules have changed. 679 * @hide 680 */ 681 public void onCarrierPrivilegedAppsChanged() { 682 try { 683 mService.onCarrierPrivilegedAppsChanged(); 684 } catch (RemoteException re) { 685 } 686 } 687 688 /** 689 * Reports a Chooser action to the UsageStatsManager. 690 * 691 * @param packageName The package name of the app that is selected. 692 * @param userId The user id of who makes the selection. 693 * @param contentType The type of the content, e.g., Image, Video, App. 694 * @param annotations The annotations of the content, e.g., Game, Selfie. 695 * @param action The action type of Intent that invokes ChooserActivity. 696 * {@link UsageEvents} 697 * @hide 698 */ 699 public void reportChooserSelection(String packageName, int userId, String contentType, 700 String[] annotations, String action) { 701 try { 702 mService.reportChooserSelection(packageName, userId, contentType, annotations, action); 703 } catch (RemoteException re) { 704 } 705 } 706} 707