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