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