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