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 * Keep in sync with the greatest event type value. 338 * @hide 339 */ 340 public static final int MAX_EVENT_TYPE = 30; 341 342 /** @hide */ 343 public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0; 344 345 /** @hide */ 346 @IntDef(flag = true, prefix = { "FLAG_" }, value = { 347 FLAG_IS_PACKAGE_INSTANT_APP, 348 }) 349 @Retention(RetentionPolicy.SOURCE) 350 public @interface EventFlags {} 351 352 /** 353 * Bitwise OR all valid flag constants to create this constant. 354 * @hide 355 */ 356 public static final int VALID_FLAG_BITS = FLAG_IS_PACKAGE_INSTANT_APP; 357 358 /** 359 * @hide 360 */ 361 private static final int UNASSIGNED_TOKEN = -1; 362 363 /** 364 * {@hide} 365 */ 366 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 367 public String mPackage; 368 369 /** 370 * {@hide} 371 */ 372 public int mPackageToken = UNASSIGNED_TOKEN; 373 374 /** 375 * {@hide} 376 */ 377 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 378 public String mClass; 379 380 /** 381 * {@hide} 382 */ 383 public int mClassToken = UNASSIGNED_TOKEN; 384 385 /** 386 * {@hide} 387 */ 388 public int mInstanceId; 389 390 /** 391 * {@hide} 392 */ 393 public String mTaskRootPackage; 394 395 /** 396 * {@hide} 397 */ 398 public int mTaskRootPackageToken = UNASSIGNED_TOKEN; 399 400 /** 401 * {@hide} 402 */ 403 public String mTaskRootClass; 404 405 /** 406 * {@hide} 407 */ 408 public int mTaskRootClassToken = UNASSIGNED_TOKEN; 409 410 /** 411 * {@hide} 412 */ 413 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 414 public long mTimeStamp; 415 416 /** 417 * {@hide} 418 */ 419 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 420 public int mEventType; 421 422 /** 423 * Only present for {@link #CONFIGURATION_CHANGE} event types. 424 * {@hide} 425 */ 426 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 427 public Configuration mConfiguration; 428 429 /** 430 * ID of the shortcut. 431 * Only present for {@link #SHORTCUT_INVOCATION} event types. 432 * {@hide} 433 */ 434 public String mShortcutId; 435 436 /** 437 * {@hide} 438 */ 439 public int mShortcutIdToken = UNASSIGNED_TOKEN; 440 441 /** 442 * Action type passed to ChooserActivity 443 * Only present for {@link #CHOOSER_ACTION} event types. 444 * {@hide} 445 */ 446 public String mAction; 447 448 /** 449 * Content type passed to ChooserActivity. 450 * Only present for {@link #CHOOSER_ACTION} event types. 451 * {@hide} 452 */ 453 public String mContentType; 454 455 /** 456 * Content annotations passed to ChooserActivity. 457 * Only present for {@link #CHOOSER_ACTION} event types. 458 * {@hide} 459 */ 460 public String[] mContentAnnotations; 461 462 /** 463 * The app standby bucket assigned and reason. Bucket is the high order 16 bits, reason 464 * is the low order 16 bits. 465 * Only present for {@link #STANDBY_BUCKET_CHANGED} event types 466 * {@hide} 467 */ 468 public int mBucketAndReason; 469 470 /** 471 * The id of the {@link android.app.NotificationChannel} to which an interruptive 472 * notification was posted. 473 * Only present for {@link #NOTIFICATION_INTERRUPTION} event types. 474 * {@hide} 475 */ 476 public String mNotificationChannelId; 477 478 /** 479 * {@hide} 480 */ 481 public int mNotificationChannelIdToken = UNASSIGNED_TOKEN; 482 483 /** 484 * LocusId. 485 * Currently LocusId only present for {@link #LOCUS_ID_SET} event types. 486 * {@hide} 487 */ 488 public String mLocusId; 489 490 /** 491 * {@hide} 492 */ 493 public int mLocusIdToken = UNASSIGNED_TOKEN; 494 495 /** @hide */ 496 @EventFlags 497 public int mFlags; 498 Event()499 public Event() { 500 } 501 502 /** @hide */ Event(int type, long timeStamp)503 public Event(int type, long timeStamp) { 504 mEventType = type; 505 mTimeStamp = timeStamp; 506 } 507 508 /** @hide */ Event(Event orig)509 public Event(Event orig) { 510 copyFrom(orig); 511 } 512 513 /** 514 * The package name of the source of this event. 515 */ getPackageName()516 public String getPackageName() { 517 return mPackage; 518 } 519 520 /** 521 * Indicates whether it is an instant app. 522 * @hide 523 */ 524 @SystemApi isInstantApp()525 public boolean isInstantApp() { 526 return (mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == FLAG_IS_PACKAGE_INSTANT_APP; 527 } 528 529 /** 530 * The class name of the source of this event. This may be null for 531 * certain events. 532 */ getClassName()533 public String getClassName() { 534 return mClass; 535 } 536 537 /** 538 * An activity can be instantiated multiple times, this is the unique activity instance ID. 539 * For non-activity class, instance ID is always zero. 540 * @hide 541 */ 542 @SystemApi getInstanceId()543 public int getInstanceId() { 544 return mInstanceId; 545 } 546 547 /** 548 * The package name of the task root when this event was reported. 549 * Or {@code null} for queries from apps without {@link 550 * android.Manifest.permission#PACKAGE_USAGE_STATS} 551 * @hide 552 */ 553 @SystemApi getTaskRootPackageName()554 public @Nullable String getTaskRootPackageName() { 555 return mTaskRootPackage; 556 } 557 558 /** 559 * The class name of the task root when this event was reported. 560 * Or {@code null} for queries from apps without {@link 561 * android.Manifest.permission#PACKAGE_USAGE_STATS} 562 * @hide 563 */ 564 @SystemApi getTaskRootClassName()565 public @Nullable String getTaskRootClassName() { 566 return mTaskRootClass; 567 } 568 569 /** 570 * The time at which this event occurred, measured in milliseconds since the epoch. 571 * <p/> 572 * See {@link System#currentTimeMillis()}. 573 */ getTimeStamp()574 public long getTimeStamp() { 575 return mTimeStamp; 576 } 577 578 /** 579 * The event type. 580 * @see #ACTIVITY_PAUSED 581 * @see #ACTIVITY_RESUMED 582 * @see #CONFIGURATION_CHANGE 583 * @see #USER_INTERACTION 584 * @see #STANDBY_BUCKET_CHANGED 585 * @see #FOREGROUND_SERVICE_START 586 * @see #FOREGROUND_SERVICE_STOP 587 * @see #ACTIVITY_STOPPED 588 */ getEventType()589 public int getEventType() { 590 return mEventType; 591 } 592 593 /** 594 * Returns a {@link Configuration} for this event if the event is of type 595 * {@link #CONFIGURATION_CHANGE}, otherwise it returns null. 596 */ getConfiguration()597 public Configuration getConfiguration() { 598 return mConfiguration; 599 } 600 601 /** 602 * Returns the ID of a {@link android.content.pm.ShortcutInfo} for this event 603 * if the event is of type {@link #SHORTCUT_INVOCATION}, otherwise it returns null. 604 * 605 * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) 606 */ getShortcutId()607 public String getShortcutId() { 608 return mShortcutId; 609 } 610 611 /** 612 * Returns the standby bucket of the app, if the event is of type 613 * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. 614 * @return the standby bucket associated with the event. 615 * @hide 616 */ getStandbyBucket()617 public int getStandbyBucket() { 618 return (mBucketAndReason & 0xFFFF0000) >>> 16; 619 } 620 621 /** 622 * Returns the standby bucket of the app, if the event is of type 623 * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. 624 * @return the standby bucket associated with the event. 625 * 626 */ getAppStandbyBucket()627 public int getAppStandbyBucket() { 628 return (mBucketAndReason & 0xFFFF0000) >>> 16; 629 } 630 631 /** 632 * Returns the reason for the bucketing, if the event is of type 633 * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. Reason values include 634 * the main reason which is one of REASON_MAIN_*, OR'ed with REASON_SUB_*, if there 635 * are sub-reasons for the main reason, such as REASON_SUB_USAGE_* when the main reason 636 * is REASON_MAIN_USAGE. 637 * @hide 638 */ getStandbyReason()639 public int getStandbyReason() { 640 return mBucketAndReason & 0x0000FFFF; 641 } 642 643 /** 644 * Returns the ID of the {@link android.app.NotificationChannel} for this event if the 645 * event is of type {@link #NOTIFICATION_INTERRUPTION}, otherwise it returns null; 646 * @hide 647 */ 648 @Nullable 649 @SystemApi getNotificationChannelId()650 public String getNotificationChannelId() { 651 return mNotificationChannelId; 652 } 653 654 /** @hide */ getObfuscatedIfInstantApp()655 public Event getObfuscatedIfInstantApp() { 656 if (!isInstantApp()) { 657 return this; 658 } 659 final Event ret = new Event(this); 660 ret.mPackage = INSTANT_APP_PACKAGE_NAME; 661 ret.mClass = INSTANT_APP_CLASS_NAME; 662 663 // Note there are other string fields too, but they're for app shortcuts and choosers, 664 // which instant apps can't use anyway, so there's no need to hide them. 665 return ret; 666 } 667 668 /** @hide */ getObfuscatedNotificationEvent()669 public Event getObfuscatedNotificationEvent() { 670 final Event ret = new Event(this); 671 ret.mNotificationChannelId = OBFUSCATED_NOTIFICATION_CHANNEL_ID; 672 return ret; 673 } 674 675 /** 676 * Returns the locusId for this event if the event is of type {@link #LOCUS_ID_SET}, 677 * otherwise it returns null. 678 * @hide 679 */ 680 @Nullable getLocusId()681 public String getLocusId() { 682 return mLocusId; 683 } 684 copyFrom(Event orig)685 private void copyFrom(Event orig) { 686 mPackage = orig.mPackage; 687 mClass = orig.mClass; 688 mInstanceId = orig.mInstanceId; 689 mTaskRootPackage = orig.mTaskRootPackage; 690 mTaskRootClass = orig.mTaskRootClass; 691 mTimeStamp = orig.mTimeStamp; 692 mEventType = orig.mEventType; 693 mConfiguration = orig.mConfiguration; 694 mShortcutId = orig.mShortcutId; 695 mAction = orig.mAction; 696 mContentType = orig.mContentType; 697 mContentAnnotations = orig.mContentAnnotations; 698 mFlags = orig.mFlags; 699 mBucketAndReason = orig.mBucketAndReason; 700 mNotificationChannelId = orig.mNotificationChannelId; 701 mLocusId = orig.mLocusId; 702 } 703 } 704 705 // Only used when creating the resulting events. Not used for reading/unparceling. 706 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 707 private List<Event> mEventsToWrite = null; 708 709 // Only used for reading/unparceling events. 710 @UnsupportedAppUsage 711 private Parcel mParcel = null; 712 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 713 private final int mEventCount; 714 715 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 716 private int mIndex = 0; 717 718 // Only used when parceling events. If false, task roots will be omitted from the parcel 719 private final boolean mIncludeTaskRoots; 720 721 /* 722 * In order to save space, since ComponentNames will be duplicated everywhere, 723 * we use a map and index into it. 724 */ 725 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 726 private String[] mStringPool; 727 728 /** 729 * Construct the iterator from a parcel. 730 * {@hide} 731 */ 732 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) UsageEvents(Parcel in)733 public UsageEvents(Parcel in) { 734 byte[] bytes = in.readBlob(); 735 Parcel data = Parcel.obtain(); 736 data.unmarshall(bytes, 0, bytes.length); 737 data.setDataPosition(0); 738 mEventCount = data.readInt(); 739 mIndex = data.readInt(); 740 if (mEventCount > 0) { 741 mStringPool = data.createStringArray(); 742 743 final int listByteLength = data.readInt(); 744 final int positionInParcel = data.readInt(); 745 mParcel = Parcel.obtain(); 746 mParcel.setDataPosition(0); 747 mParcel.appendFrom(data, data.dataPosition(), listByteLength); 748 mParcel.setDataSize(mParcel.dataPosition()); 749 mParcel.setDataPosition(positionInParcel); 750 } 751 mIncludeTaskRoots = true; 752 } 753 754 /** 755 * Create an empty iterator. 756 * {@hide} 757 */ UsageEvents()758 UsageEvents() { 759 mEventCount = 0; 760 mIncludeTaskRoots = true; 761 } 762 763 /** 764 * Construct the iterator in preparation for writing it to a parcel. 765 * Defaults to excluding task roots from the parcel. 766 * {@hide} 767 */ UsageEvents(List<Event> events, String[] stringPool)768 public UsageEvents(List<Event> events, String[] stringPool) { 769 this(events, stringPool, false); 770 } 771 772 /** 773 * Construct the iterator in preparation for writing it to a parcel. 774 * {@hide} 775 */ UsageEvents(List<Event> events, String[] stringPool, boolean includeTaskRoots)776 public UsageEvents(List<Event> events, String[] stringPool, boolean includeTaskRoots) { 777 mStringPool = stringPool; 778 mEventCount = events.size(); 779 mEventsToWrite = events; 780 mIncludeTaskRoots = includeTaskRoots; 781 } 782 783 /** 784 * Returns whether or not there are more events to read using 785 * {@link #getNextEvent(android.app.usage.UsageEvents.Event)}. 786 * 787 * @return true if there are more events, false otherwise. 788 */ hasNextEvent()789 public boolean hasNextEvent() { 790 return mIndex < mEventCount; 791 } 792 793 /** 794 * Retrieve the next {@link android.app.usage.UsageEvents.Event} from the collection and put the 795 * resulting data into {@code eventOut}. 796 * 797 * @param eventOut The {@link android.app.usage.UsageEvents.Event} object that will receive the 798 * next event data. 799 * @return true if an event was available, false if there are no more events. 800 */ getNextEvent(Event eventOut)801 public boolean getNextEvent(Event eventOut) { 802 if (mIndex >= mEventCount) { 803 return false; 804 } 805 806 if (mParcel != null) { 807 readEventFromParcel(mParcel, eventOut); 808 } else { 809 eventOut.copyFrom(mEventsToWrite.get(mIndex)); 810 } 811 812 mIndex++; 813 if (mIndex >= mEventCount && mParcel != null) { 814 mParcel.recycle(); 815 mParcel = null; 816 } 817 return true; 818 } 819 820 /** 821 * Resets the collection so that it can be iterated over from the beginning. 822 * 823 * @hide When this object is iterated to completion, the parcel is destroyed and 824 * so resetToStart doesn't work. 825 */ resetToStart()826 public void resetToStart() { 827 mIndex = 0; 828 if (mParcel != null) { 829 mParcel.setDataPosition(0); 830 } 831 } 832 833 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) findStringIndex(String str)834 private int findStringIndex(String str) { 835 final int index = Arrays.binarySearch(mStringPool, str); 836 if (index < 0) { 837 throw new IllegalStateException("String '" + str + "' is not in the string pool"); 838 } 839 return index; 840 } 841 842 /** 843 * Writes a single event to the parcel. Modify this when updating {@link Event}. 844 */ 845 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) writeEventToParcel(Event event, Parcel p, int flags)846 private void writeEventToParcel(Event event, Parcel p, int flags) { 847 final int packageIndex; 848 if (event.mPackage != null) { 849 packageIndex = findStringIndex(event.mPackage); 850 } else { 851 packageIndex = -1; 852 } 853 854 final int classIndex; 855 if (event.mClass != null) { 856 classIndex = findStringIndex(event.mClass); 857 } else { 858 classIndex = -1; 859 } 860 861 final int taskRootPackageIndex; 862 if (mIncludeTaskRoots && event.mTaskRootPackage != null) { 863 taskRootPackageIndex = findStringIndex(event.mTaskRootPackage); 864 } else { 865 taskRootPackageIndex = -1; 866 } 867 868 final int taskRootClassIndex; 869 if (mIncludeTaskRoots && event.mTaskRootClass != null) { 870 taskRootClassIndex = findStringIndex(event.mTaskRootClass); 871 } else { 872 taskRootClassIndex = -1; 873 } 874 p.writeInt(packageIndex); 875 p.writeInt(classIndex); 876 p.writeInt(event.mInstanceId); 877 p.writeInt(taskRootPackageIndex); 878 p.writeInt(taskRootClassIndex); 879 p.writeInt(event.mEventType); 880 p.writeLong(event.mTimeStamp); 881 882 switch (event.mEventType) { 883 case Event.CONFIGURATION_CHANGE: 884 event.mConfiguration.writeToParcel(p, flags); 885 break; 886 case Event.SHORTCUT_INVOCATION: 887 p.writeString(event.mShortcutId); 888 break; 889 case Event.CHOOSER_ACTION: 890 p.writeString(event.mAction); 891 p.writeString(event.mContentType); 892 p.writeStringArray(event.mContentAnnotations); 893 break; 894 case Event.STANDBY_BUCKET_CHANGED: 895 p.writeInt(event.mBucketAndReason); 896 break; 897 case Event.NOTIFICATION_INTERRUPTION: 898 p.writeString(event.mNotificationChannelId); 899 break; 900 case Event.LOCUS_ID_SET: 901 p.writeString(event.mLocusId); 902 break; 903 } 904 p.writeInt(event.mFlags); 905 } 906 907 /** 908 * Reads a single event from the parcel. Modify this when updating {@link Event}. 909 */ 910 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) readEventFromParcel(Parcel p, Event eventOut)911 private void readEventFromParcel(Parcel p, Event eventOut) { 912 final int packageIndex = p.readInt(); 913 if (packageIndex >= 0) { 914 eventOut.mPackage = mStringPool[packageIndex]; 915 } else { 916 eventOut.mPackage = null; 917 } 918 919 final int classIndex = p.readInt(); 920 if (classIndex >= 0) { 921 eventOut.mClass = mStringPool[classIndex]; 922 } else { 923 eventOut.mClass = null; 924 } 925 eventOut.mInstanceId = p.readInt(); 926 927 final int taskRootPackageIndex = p.readInt(); 928 if (taskRootPackageIndex >= 0) { 929 eventOut.mTaskRootPackage = mStringPool[taskRootPackageIndex]; 930 } else { 931 eventOut.mTaskRootPackage = null; 932 } 933 934 final int taskRootClassIndex = p.readInt(); 935 if (taskRootClassIndex >= 0) { 936 eventOut.mTaskRootClass = mStringPool[taskRootClassIndex]; 937 } else { 938 eventOut.mTaskRootClass = null; 939 } 940 941 eventOut.mEventType = p.readInt(); 942 eventOut.mTimeStamp = p.readLong(); 943 944 // Fill out the event-dependant fields. 945 eventOut.mConfiguration = null; 946 eventOut.mShortcutId = null; 947 eventOut.mAction = null; 948 eventOut.mContentType = null; 949 eventOut.mContentAnnotations = null; 950 eventOut.mNotificationChannelId = null; 951 eventOut.mLocusId = null; 952 953 switch (eventOut.mEventType) { 954 case Event.CONFIGURATION_CHANGE: 955 // Extract the configuration for configuration change events. 956 eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p); 957 break; 958 case Event.SHORTCUT_INVOCATION: 959 eventOut.mShortcutId = p.readString(); 960 break; 961 case Event.CHOOSER_ACTION: 962 eventOut.mAction = p.readString(); 963 eventOut.mContentType = p.readString(); 964 eventOut.mContentAnnotations = p.createStringArray(); 965 break; 966 case Event.STANDBY_BUCKET_CHANGED: 967 eventOut.mBucketAndReason = p.readInt(); 968 break; 969 case Event.NOTIFICATION_INTERRUPTION: 970 eventOut.mNotificationChannelId = p.readString(); 971 break; 972 case Event.LOCUS_ID_SET: 973 eventOut.mLocusId = p.readString(); 974 break; 975 } 976 eventOut.mFlags = p.readInt(); 977 } 978 979 @Override describeContents()980 public int describeContents() { 981 return 0; 982 } 983 984 @Override writeToParcel(Parcel dest, int flags)985 public void writeToParcel(Parcel dest, int flags) { 986 Parcel data = Parcel.obtain(); 987 data.writeInt(mEventCount); 988 data.writeInt(mIndex); 989 if (mEventCount > 0) { 990 data.writeStringArray(mStringPool); 991 992 if (mEventsToWrite != null) { 993 // Write out the events 994 Parcel p = Parcel.obtain(); 995 try { 996 p.setDataPosition(0); 997 for (int i = 0; i < mEventCount; i++) { 998 final Event event = mEventsToWrite.get(i); 999 writeEventToParcel(event, p, flags); 1000 } 1001 1002 final int listByteLength = p.dataPosition(); 1003 1004 // Write the total length of the data. 1005 data.writeInt(listByteLength); 1006 1007 // Write our current position into the data. 1008 data.writeInt(0); 1009 1010 // Write the data. 1011 data.appendFrom(p, 0, listByteLength); 1012 } finally { 1013 p.recycle(); 1014 } 1015 1016 } else if (mParcel != null) { 1017 // Write the total length of the data. 1018 data.writeInt(mParcel.dataSize()); 1019 1020 // Write out current position into the data. 1021 data.writeInt(mParcel.dataPosition()); 1022 1023 // Write the data. 1024 data.appendFrom(mParcel, 0, mParcel.dataSize()); 1025 } else { 1026 throw new IllegalStateException( 1027 "Either mParcel or mEventsToWrite must not be null"); 1028 } 1029 } 1030 // Data can be too large for a transact. Write the data as a Blob, which will be written to 1031 // ashmem if too large. 1032 dest.writeBlob(data.marshall()); 1033 } 1034 1035 public static final @android.annotation.NonNull Creator<UsageEvents> CREATOR = new Creator<UsageEvents>() { 1036 @Override 1037 public UsageEvents createFromParcel(Parcel source) { 1038 return new UsageEvents(source); 1039 } 1040 1041 @Override 1042 public UsageEvents[] newArray(int size) { 1043 return new UsageEvents[size]; 1044 } 1045 }; 1046 } 1047