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 package android.app.usage; 17 18 import android.annotation.CurrentTimeMillisLong; 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SystemApi; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.res.Configuration; 26 import android.os.Build; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.PersistableBundle; 30 import android.util.Log; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.List; 37 38 /** 39 * A result returned from {@link android.app.usage.UsageStatsManager#queryEvents(long, long)} 40 * from which to read {@link android.app.usage.UsageEvents.Event} objects. 41 */ 42 public final class UsageEvents implements Parcelable { 43 private static final String TAG = "UsageEvents"; 44 45 /** @hide */ 46 public static final String INSTANT_APP_PACKAGE_NAME = "android.instant_app"; 47 48 /** @hide */ 49 public static final String INSTANT_APP_CLASS_NAME = "android.instant_class"; 50 51 /** @hide */ 52 public static final String OBFUSCATED_NOTIFICATION_CHANNEL_ID = "unknown_channel_id"; 53 54 /** 55 * Flag: indicates to not obfuscate or hide any usage event data when being queried. 56 * @hide 57 */ 58 public static final int SHOW_ALL_EVENT_DATA = 0x00000000; 59 60 /** 61 * Flag: indicates to obfuscate package and class names for instant apps when querying usage 62 * events. 63 * @hide 64 */ 65 public static final int OBFUSCATE_INSTANT_APPS = 0x00000001; 66 67 /** 68 * Flag: indicates to hide all {@link Event#SHORTCUT_INVOCATION} events when querying usage 69 * events. 70 * @hide 71 */ 72 public static final int HIDE_SHORTCUT_EVENTS = 0x00000002; 73 74 /** 75 * Flag: indicates to obfuscate the notification channel id for all notification events, 76 * such as {@link Event#NOTIFICATION_SEEN} and {@link Event#NOTIFICATION_INTERRUPTION} events, 77 * when querying usage events. 78 * @hide 79 */ 80 public static final int OBFUSCATE_NOTIFICATION_EVENTS = 0x00000004; 81 82 /** 83 * Flag: indicates to hide all {@link Event#LOCUS_ID_SET} events when querying usage events. 84 * @hide 85 */ 86 public static final int HIDE_LOCUS_EVENTS = 0x00000008; 87 88 /** 89 * An event representing a state change for a component. 90 */ 91 public static final class Event { 92 93 /** 94 * No event type. 95 */ 96 public static final int NONE = 0; 97 98 /** 99 * A device level event like {@link #DEVICE_SHUTDOWN} does not have package name, but some 100 * user code always expect a non-null {@link #mPackage} for every event. Use 101 * {@link #DEVICE_EVENT_PACKAGE_NAME} as packageName for these device level events. 102 * @hide 103 */ 104 public static final String DEVICE_EVENT_PACKAGE_NAME = "android"; 105 106 /** 107 * @deprecated by {@link #ACTIVITY_RESUMED} 108 */ 109 @Deprecated 110 public static final int MOVE_TO_FOREGROUND = 1; 111 112 /** 113 * An event type denoting that an {@link android.app.Activity} moved to the foreground. 114 * This event has a package name and class name associated with it and can be retrieved 115 * using {@link #getPackageName()} and {@link #getClassName()}. 116 * If a package has multiple activities, this event is reported for each activity that moves 117 * to foreground. 118 * This event is corresponding to {@link android.app.Activity#onResume()} of the 119 * activity's lifecycle. 120 */ 121 public static final int ACTIVITY_RESUMED = MOVE_TO_FOREGROUND; 122 123 /** 124 * @deprecated by {@link #ACTIVITY_PAUSED} 125 */ 126 @Deprecated 127 public static final int MOVE_TO_BACKGROUND = 2; 128 129 /** 130 * An event type denoting that an {@link android.app.Activity} moved to the background. 131 * This event has a package name and class name associated with it and can be retrieved 132 * using {@link #getPackageName()} and {@link #getClassName()}. 133 * If a package has multiple activities, this event is reported for each activity that moves 134 * to background. 135 * This event is corresponding to {@link android.app.Activity#onPause()} of the activity's 136 * lifecycle. 137 */ 138 public static final int ACTIVITY_PAUSED = MOVE_TO_BACKGROUND; 139 140 /** 141 * An event type denoting that a component was in the foreground when the stats 142 * rolled-over. This is effectively treated as a {@link #ACTIVITY_PAUSED}. 143 * This event has a non-null packageName, and a null className. 144 * {@hide} 145 */ 146 public static final int END_OF_DAY = 3; 147 148 /** 149 * An event type denoting that a component was in the foreground the previous day. 150 * This is effectively treated as a {@link #ACTIVITY_RESUMED}. 151 * {@hide} 152 */ 153 public static final int CONTINUE_PREVIOUS_DAY = 4; 154 155 /** 156 * An event type denoting that the device configuration has changed. 157 */ 158 public static final int CONFIGURATION_CHANGE = 5; 159 160 /** 161 * An event type denoting that a package was interacted with in some way by the system. 162 * @hide 163 */ 164 @SystemApi 165 public static final int SYSTEM_INTERACTION = 6; 166 167 /** 168 * An event type denoting that a package was interacted with in some way by the user. 169 */ 170 public static final int USER_INTERACTION = 7; 171 172 /** 173 * An event type denoting that an action equivalent to a ShortcutInfo is taken by the user. 174 * 175 * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) 176 */ 177 public static final int SHORTCUT_INVOCATION = 8; 178 179 /** 180 * An event type denoting that a package was selected by the user for ChooserActivity. 181 * @hide 182 */ 183 public static final int CHOOSER_ACTION = 9; 184 185 /** 186 * An event type denoting that a notification was viewed by the user. 187 * @hide 188 */ 189 @SystemApi 190 public static final int NOTIFICATION_SEEN = 10; 191 192 /** 193 * An event type denoting a change in App Standby Bucket. The new bucket can be 194 * retrieved by calling {@link #getAppStandbyBucket()}. 195 * 196 * @see UsageStatsManager#getAppStandbyBucket() 197 */ 198 public static final int STANDBY_BUCKET_CHANGED = 11; 199 200 /** 201 * An event type denoting that an app posted an interruptive notification. Visual and 202 * audible interruptions are included. 203 * @hide 204 */ 205 @SystemApi 206 public static final int NOTIFICATION_INTERRUPTION = 12; 207 208 /** 209 * A Slice was pinned by the default launcher or the default assistant. 210 * @hide 211 */ 212 @SystemApi 213 public static final int SLICE_PINNED_PRIV = 13; 214 215 /** 216 * A Slice was pinned by an app. 217 * @hide 218 */ 219 @SystemApi 220 public static final int SLICE_PINNED = 14; 221 222 /** 223 * An event type denoting that the screen has gone in to an interactive state (turned 224 * on for full user interaction, not ambient display or other non-interactive state). 225 */ 226 public static final int SCREEN_INTERACTIVE = 15; 227 228 /** 229 * An event type denoting that the screen has gone in to a non-interactive state 230 * (completely turned off or turned on only in a non-interactive state like ambient 231 * display). 232 */ 233 public static final int SCREEN_NON_INTERACTIVE = 16; 234 235 /** 236 * An event type denoting that the screen's keyguard has been shown, whether or not 237 * the screen is off. 238 */ 239 public static final int KEYGUARD_SHOWN = 17; 240 241 /** 242 * An event type denoting that the screen's keyguard has been hidden. This typically 243 * happens when the user unlocks their phone after turning it on. 244 */ 245 public static final int KEYGUARD_HIDDEN = 18; 246 247 /** 248 * An event type denoting start of a foreground service. 249 * This event has a package name and class name associated with it and can be retrieved 250 * using {@link #getPackageName()} and {@link #getClassName()}. 251 * If a package has multiple foreground services, this event is reported for each service 252 * that is started. 253 */ 254 public static final int FOREGROUND_SERVICE_START = 19; 255 256 /** 257 * An event type denoting stop of a foreground service. 258 * This event has a package name and class name associated with it and can be retrieved 259 * using {@link #getPackageName()} and {@link #getClassName()}. 260 * If a package has multiple foreground services, this event is reported for each service 261 * that is stopped. 262 */ 263 public static final int FOREGROUND_SERVICE_STOP = 20; 264 265 /** 266 * An event type denoting that a foreground service is at started state at beginning of a 267 * time interval. 268 * This is effectively treated as a {@link #FOREGROUND_SERVICE_START}. 269 * {@hide} 270 */ 271 public static final int CONTINUING_FOREGROUND_SERVICE = 21; 272 273 /** 274 * An event type denoting that a foreground service is at started state when the stats 275 * rolled-over at the end of a time interval. 276 * {@hide} 277 */ 278 public static final int ROLLOVER_FOREGROUND_SERVICE = 22; 279 280 /** 281 * An activity becomes invisible on the UI, corresponding to 282 * {@link android.app.Activity#onStop()} of the activity's lifecycle. 283 */ 284 public static final int ACTIVITY_STOPPED = 23; 285 286 /** 287 * An activity object is destroyed, corresponding to 288 * {@link android.app.Activity#onDestroy()} of the activity's lifecycle. 289 * {@hide} 290 */ 291 public static final int ACTIVITY_DESTROYED = 24; 292 293 /** 294 * The event type demoting that a flush of UsageStatsDatabase to file system. Before the 295 * flush all usage stats need to be updated to latest timestamp to make sure the most 296 * up to date stats are persisted. 297 * @hide 298 */ 299 public static final int FLUSH_TO_DISK = 25; 300 301 /** 302 * An event type denoting that the Android runtime underwent a shutdown process. 303 * A DEVICE_SHUTDOWN event should be treated as if all started activities and foreground 304 * services are now stopped and no explicit {@link #ACTIVITY_STOPPED} and 305 * {@link #FOREGROUND_SERVICE_STOP} events will be generated for them. 306 * 307 * <p>The DEVICE_SHUTDOWN timestamp is actually the last time UsageStats database is 308 * persisted before the actual shutdown. Events (if there are any) between this timestamp 309 * and the actual shutdown is not persisted in the database. So any open events without 310 * matching close events between DEVICE_SHUTDOWN and {@link #DEVICE_STARTUP} should be 311 * ignored because the closing time is unknown.</p> 312 */ 313 public static final int DEVICE_SHUTDOWN = 26; 314 315 /** 316 * An event type denoting that the Android runtime started up. This could be after a 317 * shutdown or a runtime restart. Any open events without matching close events between 318 * {@link #DEVICE_SHUTDOWN} and DEVICE_STARTUP should be ignored because the closing time is 319 * unknown. 320 */ 321 public static final int DEVICE_STARTUP = 27; 322 323 /** 324 * An event type denoting that a user has been unlocked for the first time. This event 325 * mainly indicates when the user's credential encrypted storage was first accessible. 326 * @hide 327 */ 328 public static final int USER_UNLOCKED = 28; 329 330 /** 331 * An event type denoting that a user has been stopped. This typically happens when the 332 * system is being turned off or when users are being switched. 333 * @hide 334 */ 335 public static final int USER_STOPPED = 29; 336 337 /** 338 * An event type denoting that new locusId has been set for a given activity. 339 * @hide 340 */ 341 public static final int LOCUS_ID_SET = 30; 342 343 /** 344 * An event type denoting that a component in the package has been used (e.g. broadcast 345 * receiver, service, content provider). This generally matches up with usage that would 346 * cause an app to leave force stop. The component itself is not provided as we are only 347 * interested in whether the package is used, not the component itself. 348 * @hide 349 */ 350 public static final int APP_COMPONENT_USED = 31; 351 352 /** 353 * Keep in sync with the greatest event type value. 354 * @hide 355 */ 356 public static final int MAX_EVENT_TYPE = 31; 357 358 /** 359 * Keep in sync with the event types defined above. 360 * @hide 361 */ 362 @IntDef(flag = false, value = { 363 NONE, 364 ACTIVITY_RESUMED, 365 ACTIVITY_PAUSED, 366 END_OF_DAY, 367 CONTINUE_PREVIOUS_DAY, 368 CONFIGURATION_CHANGE, 369 SYSTEM_INTERACTION, 370 USER_INTERACTION, 371 SHORTCUT_INVOCATION, 372 CHOOSER_ACTION, 373 NOTIFICATION_SEEN, 374 STANDBY_BUCKET_CHANGED, 375 NOTIFICATION_INTERRUPTION, 376 SLICE_PINNED_PRIV, 377 SLICE_PINNED, 378 SCREEN_INTERACTIVE, 379 SCREEN_NON_INTERACTIVE, 380 KEYGUARD_SHOWN, 381 KEYGUARD_HIDDEN, 382 FOREGROUND_SERVICE_START, 383 FOREGROUND_SERVICE_STOP, 384 CONTINUING_FOREGROUND_SERVICE, 385 ROLLOVER_FOREGROUND_SERVICE, 386 ACTIVITY_STOPPED, 387 ACTIVITY_DESTROYED, 388 FLUSH_TO_DISK, 389 DEVICE_SHUTDOWN, 390 DEVICE_STARTUP, 391 USER_UNLOCKED, 392 USER_STOPPED, 393 LOCUS_ID_SET, 394 APP_COMPONENT_USED, 395 }) 396 @Retention(RetentionPolicy.SOURCE) 397 public @interface EventType {} 398 399 /** @hide */ 400 public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0; 401 402 /** @hide */ 403 @IntDef(flag = true, prefix = { "FLAG_" }, value = { 404 FLAG_IS_PACKAGE_INSTANT_APP, 405 }) 406 @Retention(RetentionPolicy.SOURCE) 407 public @interface EventFlags {} 408 409 /** 410 * Bitwise OR all valid flag constants to create this constant. 411 * @hide 412 */ 413 public static final int VALID_FLAG_BITS = FLAG_IS_PACKAGE_INSTANT_APP; 414 415 /** 416 * @hide 417 */ 418 private static final int UNASSIGNED_TOKEN = -1; 419 420 /** 421 * {@hide} 422 */ 423 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 424 public String mPackage; 425 426 /** 427 * {@hide} 428 */ 429 public int mPackageToken = UNASSIGNED_TOKEN; 430 431 /** 432 * {@hide} 433 */ 434 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 435 public String mClass; 436 437 /** 438 * {@hide} 439 */ 440 public int mClassToken = UNASSIGNED_TOKEN; 441 442 /** 443 * Uniquely identifies an activity. It's possible for two activities with the same 444 * pkg/class name to be in lifecycle at the same time. The mInstanceId is guaranteed to be 445 * unique per activity across all apps (not just within a single app). 446 * 447 * {@hide} 448 */ 449 public int mInstanceId; 450 451 /** 452 * {@hide} 453 */ 454 public String mTaskRootPackage; 455 456 /** 457 * {@hide} 458 */ 459 public int mTaskRootPackageToken = UNASSIGNED_TOKEN; 460 461 /** 462 * {@hide} 463 */ 464 public String mTaskRootClass; 465 466 /** 467 * {@hide} 468 */ 469 public int mTaskRootClassToken = UNASSIGNED_TOKEN; 470 471 /** 472 * {@hide} 473 */ 474 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 475 public long mTimeStamp; 476 477 /** 478 * {@hide} 479 */ 480 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 481 public int mEventType; 482 483 /** 484 * Only present for {@link #CONFIGURATION_CHANGE} event types. 485 * {@hide} 486 */ 487 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 488 public Configuration mConfiguration; 489 490 /** 491 * ID of the shortcut. 492 * Only present for {@link #SHORTCUT_INVOCATION} event types. 493 * {@hide} 494 */ 495 public String mShortcutId; 496 497 /** 498 * {@hide} 499 */ 500 public int mShortcutIdToken = UNASSIGNED_TOKEN; 501 502 /** 503 * Action type passed to ChooserActivity 504 * Only present for {@link #CHOOSER_ACTION} event types. 505 * {@hide} 506 */ 507 public String mAction; 508 509 /** 510 * Content type passed to ChooserActivity. 511 * Only present for {@link #CHOOSER_ACTION} event types. 512 * {@hide} 513 */ 514 public String mContentType; 515 516 /** 517 * Content annotations passed to ChooserActivity. 518 * Only present for {@link #CHOOSER_ACTION} event types. 519 * {@hide} 520 */ 521 public String[] mContentAnnotations; 522 523 /** 524 * The app standby bucket assigned and reason. Bucket is the high order 16 bits, reason 525 * is the low order 16 bits. 526 * Only present for {@link #STANDBY_BUCKET_CHANGED} event types 527 * {@hide} 528 */ 529 public int mBucketAndReason; 530 531 /** 532 * The id of the {@link android.app.NotificationChannel} to which an interruptive 533 * notification was posted. 534 * Only present for {@link #NOTIFICATION_INTERRUPTION} event types. 535 * {@hide} 536 */ 537 public String mNotificationChannelId; 538 539 /** 540 * {@hide} 541 */ 542 public int mNotificationChannelIdToken = UNASSIGNED_TOKEN; 543 544 /** 545 * LocusId. 546 * Currently LocusId only present for {@link #LOCUS_ID_SET} event types. 547 * {@hide} 548 */ 549 public String mLocusId; 550 551 /** 552 * {@hide} 553 */ 554 public int mLocusIdToken = UNASSIGNED_TOKEN; 555 556 /** @hide */ 557 public PersistableBundle mExtras = null; 558 559 /** @hide */ 560 public static class UserInteractionEventExtrasToken { 561 public int mCategoryToken = UNASSIGNED_TOKEN; 562 public int mActionToken = UNASSIGNED_TOKEN; 563 UserInteractionEventExtrasToken()564 public UserInteractionEventExtrasToken() { 565 // Do nothing. 566 } 567 } 568 569 /** @hide */ 570 public UserInteractionEventExtrasToken mUserInteractionExtrasToken = null; 571 572 /** @hide */ 573 @EventFlags 574 public int mFlags; 575 Event()576 public Event() { 577 } 578 579 /** @hide */ Event(int type, long timeStamp)580 public Event(int type, long timeStamp) { 581 mEventType = type; 582 mTimeStamp = timeStamp; 583 } 584 585 /** @hide */ Event(Event orig)586 public Event(Event orig) { 587 copyFrom(orig); 588 } 589 590 /** 591 * The package name of the source of this event. 592 */ getPackageName()593 public String getPackageName() { 594 return mPackage; 595 } 596 597 /** 598 * Indicates whether it is an instant app. 599 * @hide 600 */ 601 @SystemApi isInstantApp()602 public boolean isInstantApp() { 603 return (mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == FLAG_IS_PACKAGE_INSTANT_APP; 604 } 605 606 /** 607 * The class name of the source of this event. This may be null for 608 * certain events. 609 */ getClassName()610 public String getClassName() { 611 return mClass; 612 } 613 614 /** 615 * An activity can be instantiated multiple times, this is the unique activity instance ID. 616 * For non-activity class, instance ID is always zero. 617 * @hide 618 */ 619 @SystemApi getInstanceId()620 public int getInstanceId() { 621 return mInstanceId; 622 } 623 624 /** 625 * The package name of the task root when this event was reported. 626 * Or {@code null} for queries from apps without {@link 627 * android.Manifest.permission#PACKAGE_USAGE_STATS} 628 * @hide 629 */ 630 @SystemApi getTaskRootPackageName()631 public @Nullable String getTaskRootPackageName() { 632 return mTaskRootPackage; 633 } 634 635 /** 636 * The class name of the task root when this event was reported. 637 * Or {@code null} for queries from apps without {@link 638 * android.Manifest.permission#PACKAGE_USAGE_STATS} 639 * @hide 640 */ 641 @SystemApi getTaskRootClassName()642 public @Nullable String getTaskRootClassName() { 643 return mTaskRootClass; 644 } 645 646 /** 647 * The time at which this event occurred, measured in milliseconds since the epoch. 648 * <p/> 649 * See {@link System#currentTimeMillis()}. 650 */ 651 @CurrentTimeMillisLong getTimeStamp()652 public long getTimeStamp() { 653 return mTimeStamp; 654 } 655 656 /** 657 * The event type. 658 * @see #ACTIVITY_PAUSED 659 * @see #ACTIVITY_RESUMED 660 * @see #CONFIGURATION_CHANGE 661 * @see #USER_INTERACTION 662 * @see #STANDBY_BUCKET_CHANGED 663 * @see #FOREGROUND_SERVICE_START 664 * @see #FOREGROUND_SERVICE_STOP 665 * @see #ACTIVITY_STOPPED 666 */ getEventType()667 public int getEventType() { 668 return mEventType; 669 } 670 671 /** 672 * Retrieves a map of extended data from the event if the event is of type 673 * {@link #USER_INTERACTION}. 674 * 675 * @return the map of all extras that associated with the reported user interaction 676 * event. The returned {@link PersistableBundle} will contain the extras 677 * {@link UsageStatsManager#EXTRA_EVENT_CATEGORY} and 678 * {@link UsageStatsManager#EXTRA_EVENT_ACTION}. {@link PersistableBundle#EMPTY} 679 * will be returned if the details are not available. 680 */ 681 @FlaggedApi(Flags.FLAG_USER_INTERACTION_TYPE_API) getExtras()682 public @NonNull PersistableBundle getExtras() { 683 return mExtras == null ? PersistableBundle.EMPTY : mExtras; 684 } 685 686 /** 687 * Returns a {@link Configuration} for this event if the event is of type 688 * {@link #CONFIGURATION_CHANGE}, otherwise it returns null. 689 */ getConfiguration()690 public Configuration getConfiguration() { 691 return mConfiguration; 692 } 693 694 /** 695 * Returns the ID of a {@link android.content.pm.ShortcutInfo} for this event 696 * if the event is of type {@link #SHORTCUT_INVOCATION}, otherwise it returns null. 697 * 698 * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) 699 */ getShortcutId()700 public String getShortcutId() { 701 return mShortcutId; 702 } 703 704 /** 705 * Returns the standby bucket of the app, if the event is of type 706 * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. 707 * @return the standby bucket associated with the event. 708 */ getAppStandbyBucket()709 public int getAppStandbyBucket() { 710 return (mBucketAndReason & 0xFFFF0000) >>> 16; 711 } 712 713 /** 714 * Returns the reason for the bucketing, if the event is of type 715 * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. Reason values include 716 * the main reason which is one of REASON_MAIN_*, OR'ed with REASON_SUB_*, if there 717 * are sub-reasons for the main reason, such as REASON_SUB_USAGE_* when the main reason 718 * is REASON_MAIN_USAGE. 719 * @hide 720 */ getStandbyReason()721 public int getStandbyReason() { 722 return mBucketAndReason & 0x0000FFFF; 723 } 724 725 /** 726 * Returns the ID of the {@link android.app.NotificationChannel} for this event if the 727 * event is of type {@link #NOTIFICATION_INTERRUPTION}, otherwise it returns null; 728 * @hide 729 */ 730 @Nullable 731 @SystemApi getNotificationChannelId()732 public String getNotificationChannelId() { 733 return mNotificationChannelId; 734 } 735 736 /** @hide */ getObfuscatedIfInstantApp()737 public Event getObfuscatedIfInstantApp() { 738 if (!isInstantApp()) { 739 return this; 740 } 741 final Event ret = new Event(this); 742 ret.mPackage = INSTANT_APP_PACKAGE_NAME; 743 ret.mClass = INSTANT_APP_CLASS_NAME; 744 745 // Note there are other string fields too, but they're for app shortcuts and choosers, 746 // which instant apps can't use anyway, so there's no need to hide them. 747 return ret; 748 } 749 750 /** @hide */ getObfuscatedNotificationEvent()751 public Event getObfuscatedNotificationEvent() { 752 final Event ret = new Event(this); 753 ret.mNotificationChannelId = OBFUSCATED_NOTIFICATION_CHANNEL_ID; 754 return ret; 755 } 756 757 /** 758 * Returns the locusId for this event if the event is of type {@link #LOCUS_ID_SET}, 759 * otherwise it returns null. 760 * @hide 761 */ 762 @Nullable getLocusId()763 public String getLocusId() { 764 return mLocusId; 765 } 766 copyFrom(Event orig)767 private void copyFrom(Event orig) { 768 mPackage = orig.mPackage; 769 mClass = orig.mClass; 770 mInstanceId = orig.mInstanceId; 771 mTaskRootPackage = orig.mTaskRootPackage; 772 mTaskRootClass = orig.mTaskRootClass; 773 mTimeStamp = orig.mTimeStamp; 774 mEventType = orig.mEventType; 775 mConfiguration = orig.mConfiguration; 776 mShortcutId = orig.mShortcutId; 777 mAction = orig.mAction; 778 mContentType = orig.mContentType; 779 mContentAnnotations = orig.mContentAnnotations; 780 mFlags = orig.mFlags; 781 mBucketAndReason = orig.mBucketAndReason; 782 mNotificationChannelId = orig.mNotificationChannelId; 783 mLocusId = orig.mLocusId; 784 mExtras = orig.mExtras; 785 } 786 } 787 788 // Only used when creating the resulting events. Not used for reading/unparceling. 789 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 790 private List<Event> mEventsToWrite = null; 791 792 // Only used for reading/unparceling events. 793 @UnsupportedAppUsage 794 private Parcel mParcel = null; 795 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 796 private int mEventCount; 797 798 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 799 private int mIndex = 0; 800 801 // Only used when parceling events. If false, task roots will be omitted from the parcel 802 private final boolean mIncludeTaskRoots; 803 804 /* 805 * In order to save space, since ComponentNames will be duplicated everywhere, 806 * we use a map and index into it. 807 */ 808 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 809 private String[] mStringPool; 810 811 /** 812 * Construct the iterator from a parcel. 813 * {@hide} 814 */ 815 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) UsageEvents(Parcel in)816 public UsageEvents(Parcel in) { 817 if (Flags.useParceledList()) { 818 readUsageEventsFromParcelWithParceledList(in); 819 } else { 820 readUsageEventsFromParcelWithBlob(in); 821 } 822 823 mIncludeTaskRoots = true; 824 } 825 readUsageEventsFromParcelWithParceledList(Parcel in)826 private void readUsageEventsFromParcelWithParceledList(Parcel in) { 827 mEventCount = in.readInt(); 828 mIndex = in.readInt(); 829 ParcelableUsageEventList slice = in.readParcelable(getClass().getClassLoader(), 830 ParcelableUsageEventList.class); 831 if (slice != null) { 832 mEventsToWrite = slice.getList(); 833 } else { 834 mEventsToWrite = new ArrayList<>(); 835 } 836 837 if (mEventCount != mEventsToWrite.size()) { 838 Log.w(TAG, "Partial usage event list received: " + mEventCount + " != " 839 + mEventsToWrite.size()); 840 mEventCount = mEventsToWrite.size(); 841 } 842 } 843 readUsageEventsFromParcelWithBlob(Parcel in)844 private void readUsageEventsFromParcelWithBlob(Parcel in) { 845 byte[] bytes = in.readBlob(); 846 Parcel data = Parcel.obtain(); 847 data.unmarshall(bytes, 0, bytes.length); 848 data.setDataPosition(0); 849 mEventCount = data.readInt(); 850 mIndex = data.readInt(); 851 if (mEventCount > 0) { 852 mStringPool = data.createStringArray(); 853 854 final int listByteLength = data.readInt(); 855 final int positionInParcel = data.readInt(); 856 mParcel = Parcel.obtain(); 857 mParcel.setDataPosition(0); 858 mParcel.appendFrom(data, data.dataPosition(), listByteLength); 859 mParcel.setDataSize(mParcel.dataPosition()); 860 mParcel.setDataPosition(positionInParcel); 861 } 862 } 863 864 /** 865 * Create an empty iterator. 866 * {@hide} 867 */ UsageEvents()868 UsageEvents() { 869 mEventCount = 0; 870 mIncludeTaskRoots = true; 871 } 872 873 /** 874 * Construct the iterator in preparation for writing it to a parcel. 875 * Defaults to excluding task roots from the parcel. 876 * {@hide} 877 */ UsageEvents(List<Event> events, String[] stringPool)878 public UsageEvents(List<Event> events, String[] stringPool) { 879 this(events, stringPool, false); 880 } 881 882 /** 883 * Construct the iterator in preparation for writing it to a parcel. 884 * {@hide} 885 */ UsageEvents(List<Event> events, String[] stringPool, boolean includeTaskRoots)886 public UsageEvents(List<Event> events, String[] stringPool, boolean includeTaskRoots) { 887 mStringPool = stringPool; 888 mEventCount = events.size(); 889 mEventsToWrite = events; 890 mIncludeTaskRoots = includeTaskRoots; 891 } 892 893 /** 894 * Returns whether or not there are more events to read using 895 * {@link #getNextEvent(android.app.usage.UsageEvents.Event)}. 896 * 897 * @return true if there are more events, false otherwise. 898 */ hasNextEvent()899 public boolean hasNextEvent() { 900 return mIndex < mEventCount; 901 } 902 903 /** 904 * Retrieve the next {@link android.app.usage.UsageEvents.Event} from the collection and put the 905 * resulting data into {@code eventOut}. 906 * 907 * @param eventOut The {@link android.app.usage.UsageEvents.Event} object that will receive the 908 * next event data. 909 * @return true if an event was available, false if there are no more events. 910 */ getNextEvent(Event eventOut)911 public boolean getNextEvent(Event eventOut) { 912 if (eventOut == null) { 913 throw new IllegalArgumentException("Given eventOut must not be null"); 914 } 915 if (mIndex >= mEventCount) { 916 return false; 917 } 918 919 if (Flags.useParceledList()) { 920 return getNextEventFromParceledList(eventOut); 921 } 922 923 if (mParcel != null) { 924 readEventFromParcel(mParcel, eventOut); 925 } else { 926 eventOut.copyFrom(mEventsToWrite.get(mIndex)); 927 } 928 929 mIndex++; 930 if (mIndex >= mEventCount && mParcel != null) { 931 mParcel.recycle(); 932 mParcel = null; 933 } 934 return true; 935 } 936 getNextEventFromParceledList(Event eventOut)937 private boolean getNextEventFromParceledList(Event eventOut) { 938 eventOut.copyFrom(mEventsToWrite.get(mIndex)); 939 mIndex++; 940 return true; 941 } 942 943 /** 944 * Resets the collection so that it can be iterated over from the beginning. 945 * 946 * @hide When this object is iterated to completion, the parcel is destroyed and 947 * so resetToStart doesn't work. 948 */ resetToStart()949 public void resetToStart() { 950 mIndex = 0; 951 if (mParcel != null) { 952 mParcel.setDataPosition(0); 953 } 954 } 955 956 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) findStringIndex(String str)957 private int findStringIndex(String str) { 958 final int index = Arrays.binarySearch(mStringPool, str); 959 if (index < 0) { 960 throw new IllegalStateException("String '" + str + "' is not in the string pool"); 961 } 962 return index; 963 } 964 965 /** 966 * Writes a single event to the parcel. Modify this when updating {@link Event}. 967 */ 968 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) writeEventToParcel(Event event, Parcel p, int flags)969 private void writeEventToParcel(Event event, Parcel p, int flags) { 970 final int packageIndex; 971 if (event.mPackage != null) { 972 packageIndex = findStringIndex(event.mPackage); 973 } else { 974 packageIndex = -1; 975 } 976 977 final int classIndex; 978 if (event.mClass != null) { 979 classIndex = findStringIndex(event.mClass); 980 } else { 981 classIndex = -1; 982 } 983 984 final int taskRootPackageIndex; 985 if (mIncludeTaskRoots && event.mTaskRootPackage != null) { 986 taskRootPackageIndex = findStringIndex(event.mTaskRootPackage); 987 } else { 988 taskRootPackageIndex = -1; 989 } 990 991 final int taskRootClassIndex; 992 if (mIncludeTaskRoots && event.mTaskRootClass != null) { 993 taskRootClassIndex = findStringIndex(event.mTaskRootClass); 994 } else { 995 taskRootClassIndex = -1; 996 } 997 p.writeInt(packageIndex); 998 p.writeInt(classIndex); 999 p.writeInt(event.mInstanceId); 1000 p.writeInt(taskRootPackageIndex); 1001 p.writeInt(taskRootClassIndex); 1002 p.writeInt(event.mEventType); 1003 p.writeLong(event.mTimeStamp); 1004 1005 switch (event.mEventType) { 1006 case Event.CONFIGURATION_CHANGE: 1007 event.mConfiguration.writeToParcel(p, flags); 1008 break; 1009 case Event.SHORTCUT_INVOCATION: 1010 p.writeString(event.mShortcutId); 1011 break; 1012 case Event.CHOOSER_ACTION: 1013 p.writeString(event.mAction); 1014 p.writeString(event.mContentType); 1015 p.writeStringArray(event.mContentAnnotations); 1016 break; 1017 case Event.STANDBY_BUCKET_CHANGED: 1018 p.writeInt(event.mBucketAndReason); 1019 break; 1020 case Event.NOTIFICATION_INTERRUPTION: 1021 p.writeString(event.mNotificationChannelId); 1022 break; 1023 case Event.LOCUS_ID_SET: 1024 p.writeString(event.mLocusId); 1025 break; 1026 case Event.USER_INTERACTION: 1027 if (event.mExtras != null) { 1028 p.writeInt(1); 1029 p.writePersistableBundle(event.mExtras); 1030 } else { 1031 p.writeInt(0); 1032 } 1033 break; 1034 } 1035 p.writeInt(event.mFlags); 1036 } 1037 1038 /** 1039 * Reads a single event from the parcel. Modify this when updating {@link Event}. 1040 */ 1041 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) readEventFromParcel(Parcel p, Event eventOut)1042 private void readEventFromParcel(Parcel p, Event eventOut) { 1043 final int packageIndex = p.readInt(); 1044 if (packageIndex >= 0) { 1045 eventOut.mPackage = mStringPool[packageIndex]; 1046 } else { 1047 eventOut.mPackage = null; 1048 } 1049 1050 final int classIndex = p.readInt(); 1051 if (classIndex >= 0) { 1052 eventOut.mClass = mStringPool[classIndex]; 1053 } else { 1054 eventOut.mClass = null; 1055 } 1056 eventOut.mInstanceId = p.readInt(); 1057 1058 final int taskRootPackageIndex = p.readInt(); 1059 if (taskRootPackageIndex >= 0) { 1060 eventOut.mTaskRootPackage = mStringPool[taskRootPackageIndex]; 1061 } else { 1062 eventOut.mTaskRootPackage = null; 1063 } 1064 1065 final int taskRootClassIndex = p.readInt(); 1066 if (taskRootClassIndex >= 0) { 1067 eventOut.mTaskRootClass = mStringPool[taskRootClassIndex]; 1068 } else { 1069 eventOut.mTaskRootClass = null; 1070 } 1071 1072 eventOut.mEventType = p.readInt(); 1073 eventOut.mTimeStamp = p.readLong(); 1074 1075 // Fill out the event-dependant fields. 1076 eventOut.mConfiguration = null; 1077 eventOut.mShortcutId = null; 1078 eventOut.mAction = null; 1079 eventOut.mContentType = null; 1080 eventOut.mContentAnnotations = null; 1081 eventOut.mNotificationChannelId = null; 1082 eventOut.mLocusId = null; 1083 eventOut.mExtras = null; 1084 1085 switch (eventOut.mEventType) { 1086 case Event.CONFIGURATION_CHANGE: 1087 // Extract the configuration for configuration change events. 1088 eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p); 1089 break; 1090 case Event.SHORTCUT_INVOCATION: 1091 eventOut.mShortcutId = p.readString(); 1092 break; 1093 case Event.CHOOSER_ACTION: 1094 eventOut.mAction = p.readString(); 1095 eventOut.mContentType = p.readString(); 1096 eventOut.mContentAnnotations = p.readStringArray(); 1097 break; 1098 case Event.STANDBY_BUCKET_CHANGED: 1099 eventOut.mBucketAndReason = p.readInt(); 1100 break; 1101 case Event.NOTIFICATION_INTERRUPTION: 1102 eventOut.mNotificationChannelId = p.readString(); 1103 break; 1104 case Event.LOCUS_ID_SET: 1105 eventOut.mLocusId = p.readString(); 1106 break; 1107 case Event.USER_INTERACTION: 1108 if (p.readInt() != 0) { 1109 eventOut.mExtras = p.readPersistableBundle(getClass().getClassLoader()); 1110 } 1111 break; 1112 } 1113 eventOut.mFlags = p.readInt(); 1114 } 1115 1116 @Override describeContents()1117 public int describeContents() { 1118 return 0; 1119 } 1120 1121 @Override writeToParcel(Parcel dest, int flags)1122 public void writeToParcel(Parcel dest, int flags) { 1123 if (Flags.useParceledList()) { 1124 writeUsageEventsToParcelWithParceledList(dest, flags); 1125 } else { 1126 writeUsageEventsToParcelWithBlob(dest, flags); 1127 } 1128 } 1129 writeUsageEventsToParcelWithParceledList(Parcel dest, int flags)1130 private void writeUsageEventsToParcelWithParceledList(Parcel dest, int flags) { 1131 dest.writeInt(mEventCount); 1132 dest.writeInt(mIndex); 1133 dest.writeParcelable(new ParcelableUsageEventList(mEventsToWrite), flags); 1134 } 1135 writeUsageEventsToParcelWithBlob(Parcel dest, int flags)1136 private void writeUsageEventsToParcelWithBlob(Parcel dest, int flags) { 1137 Parcel data = Parcel.obtain(); 1138 data.writeInt(mEventCount); 1139 data.writeInt(mIndex); 1140 if (mEventCount > 0) { 1141 data.writeStringArray(mStringPool); 1142 1143 if (mEventsToWrite != null) { 1144 // Write out the events 1145 Parcel p = Parcel.obtain(); 1146 try { 1147 p.setDataPosition(0); 1148 for (int i = 0; i < mEventCount; i++) { 1149 final Event event = mEventsToWrite.get(i); 1150 writeEventToParcel(event, p, flags); 1151 } 1152 1153 final int listByteLength = p.dataPosition(); 1154 1155 // Write the total length of the data. 1156 data.writeInt(listByteLength); 1157 1158 // Write our current position into the data. 1159 data.writeInt(0); 1160 1161 // Write the data. 1162 data.appendFrom(p, 0, listByteLength); 1163 } finally { 1164 p.recycle(); 1165 } 1166 1167 } else if (mParcel != null) { 1168 // Write the total length of the data. 1169 data.writeInt(mParcel.dataSize()); 1170 1171 // Write out current position into the data. 1172 data.writeInt(mParcel.dataPosition()); 1173 1174 // Write the data. 1175 data.appendFrom(mParcel, 0, mParcel.dataSize()); 1176 } else { 1177 throw new IllegalStateException( 1178 "Either mParcel or mEventsToWrite must not be null"); 1179 } 1180 } 1181 // Data can be too large for a transact. Write the data as a Blob, which will be written to 1182 // ashmem if too large. 1183 dest.writeBlob(data.marshall()); 1184 data.recycle(); 1185 } 1186 1187 public static final @android.annotation.NonNull Creator<UsageEvents> CREATOR = new Creator<UsageEvents>() { 1188 @Override 1189 public UsageEvents createFromParcel(Parcel source) { 1190 return new UsageEvents(source); 1191 } 1192 1193 @Override 1194 public UsageEvents[] newArray(int size) { 1195 return new UsageEvents[size]; 1196 } 1197 }; 1198 } 1199