• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SuppressLint;
24 import android.content.Intent;
25 import android.content.pm.ApplicationInfo;
26 import android.icu.text.SimpleDateFormat;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.os.UserHandle;
30 import android.text.TextUtils;
31 import android.util.ArrayMap;
32 import android.util.Xml;
33 import android.util.proto.ProtoInputStream;
34 import android.util.proto.ProtoOutputStream;
35 import android.util.proto.WireTypeMismatchException;
36 
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.internal.util.XmlUtils;
39 import com.android.modules.utils.TypedXmlPullParser;
40 import com.android.modules.utils.TypedXmlSerializer;
41 
42 import org.xmlpull.v1.XmlPullParserException;
43 
44 import java.io.ByteArrayInputStream;
45 import java.io.ByteArrayOutputStream;
46 import java.io.IOException;
47 import java.io.ObjectInputStream;
48 import java.io.ObjectOutputStream;
49 import java.io.PrintWriter;
50 import java.lang.annotation.Retention;
51 import java.lang.annotation.RetentionPolicy;
52 import java.util.Map;
53 import java.util.Objects;
54 
55 /**
56  * Describes information related to an application process's startup.
57  *
58  * <p>
59  * Many aspects concerning why and how an applications process was started are valuable for apps
60  * both for logging and for potential behavior changes. Reason for process start, start type,
61  * start times, throttling, and other useful diagnostic data can be obtained from
62  * {@link ApplicationStartInfo} records.
63  * </p>
64  *
65  * <p>
66 *  ApplicationStartInfo objects can be retrieved via:
67 *  - {@link ActivityManager#getHistoricalProcessStartReasons}, which can be called during or after
68  *      a application's startup. Using this method, an app can retrieve information about an
69  *      in-progress app start.
70 *  - {@link ActivityManager#addApplicationStartInfoCompletionListener}, which returns an
71  *      ApplicationStartInfo object via a callback when the startup is complete, or immediately
72  *      if requested after the startup is complete.
73  * </p>
74  */
75 @FlaggedApi(Flags.FLAG_APP_START_INFO)
76 public final class ApplicationStartInfo implements Parcelable {
77 
78     /**
79      * State indicating process startup has started. Some information is available in
80      * {@link ApplicationStartInfo} and more will be added.
81      */
82     public static final int STARTUP_STATE_STARTED = 0;
83 
84     /**
85      * State indicating process startup has failed. Startup information in
86      * {@link ApplicationStartInfo} is incomplete, but no more will be added.
87      */
88     public static final int STARTUP_STATE_ERROR = 1;
89 
90     /**
91      * State indicating process startup has made it to first frame draw. Startup
92      * information in {@link ApplicationStartInfo} is complete with potential exception
93      * of fully drawn timestamp which is not guaranteed to be set.
94      */
95     public static final int STARTUP_STATE_FIRST_FRAME_DRAWN = 2;
96 
97     /** Process started due to alarm. */
98     public static final int START_REASON_ALARM = 0;
99 
100     /** Process started to run backup. */
101     public static final int START_REASON_BACKUP = 1;
102 
103     /** Process started due to boot complete. */
104     public static final int START_REASON_BOOT_COMPLETE = 2;
105 
106     /**  Process started due to broadcast received for any reason not explicitly listed. */
107     public static final int START_REASON_BROADCAST = 3;
108 
109     /** Process started due to access of ContentProvider for any reason not explicitly listed. */
110     public static final int START_REASON_CONTENT_PROVIDER = 4;
111 
112     /** * Process started to run scheduled job. */
113     public static final int START_REASON_JOB = 5;
114 
115     /** Process started due to click app icon or widget from launcher. */
116     public static final int START_REASON_LAUNCHER = 6;
117 
118     /** Process started from launcher recents. */
119     public static final int START_REASON_LAUNCHER_RECENTS = 7;
120 
121     /** Process started not for any of the listed reasons. */
122     public static final int START_REASON_OTHER = 8;
123 
124     /** Process started due to push message. */
125     public static final int START_REASON_PUSH = 9;
126 
127     /** Process started due to Service started for any reason not explicitly listed.. */
128     public static final int START_REASON_SERVICE = 10;
129 
130     /** Process started due to Activity started for any reason not explicitly listed. */
131     public static final int START_REASON_START_ACTIVITY = 11;
132 
133     /** Start type not yet set. */
134     public static final int START_TYPE_UNSET = 0;
135 
136     /** Process started from scratch. */
137     public static final int START_TYPE_COLD = 1;
138 
139     /** Process retained minimally SavedInstanceState. */
140     public static final int START_TYPE_WARM = 2;
141 
142     /** Process brought back to foreground. */
143     public static final int START_TYPE_HOT = 3;
144 
145     /**
146      * Default. The system always creates a new instance of the activity in the target task and
147      * routes the intent to it.
148      */
149     public static final int LAUNCH_MODE_STANDARD = 0;
150 
151     /**
152      * If an instance of the activity already exists at the top of the target task, the system
153      * routes the intent to that instance through a call to its onNewIntent() method, rather than
154      * creating a new instance of the activity.
155      */
156     public static final int LAUNCH_MODE_SINGLE_TOP = 1;
157 
158     /**
159      * The system creates the activity at the root of a new task or locates the activity on an
160      * existing task with the same affinity. If an instance of the activity already exists and is at
161      * the root of the task, the system routes the intent to existing instance through a call to its
162      * onNewIntent() method, rather than creating a new one.
163      */
164     public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2;
165 
166     /**
167      * Same as "singleTask", except that the system doesn't launch any other activities into the
168      * task holding the instance. The activity is always the single and only member of its task.
169      */
170     public static final int LAUNCH_MODE_SINGLE_TASK = 3;
171 
172     /**
173      * The activity can only be running as the root activity of the task, the first activity that
174      * created the task, and therefore there will only be one instance of this activity in a task;
175      * but activity can be instantiated multiple times in different tasks.
176      */
177     public static final int LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK = 4;
178 
179     /** The end of the range, beginning with 0, reserved for system timestamps.*/
180     public static final int START_TIMESTAMP_RESERVED_RANGE_SYSTEM = 20;
181 
182     /** The beginning of the range reserved for developer supplied timestamps.*/
183     public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START =
184             START_TIMESTAMP_RESERVED_RANGE_SYSTEM + 1;
185 
186     /** The end of the range reserved for developer supplied timestamps.*/
187     public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER = 30;
188 
189     /** Clock monotonic timestamp of launch started. */
190     public static final int START_TIMESTAMP_LAUNCH = 0;
191 
192     /** Clock monotonic timestamp of process fork. */
193     public static final int START_TIMESTAMP_FORK = 1;
194 
195     /** Clock monotonic timestamp of Application onCreate called. */
196     public static final int START_TIMESTAMP_APPLICATION_ONCREATE = 2;
197 
198     /** Clock monotonic timestamp of bindApplication called. */
199     public static final int START_TIMESTAMP_BIND_APPLICATION = 3;
200 
201     /** Clock monotonic timestamp of first frame drawn. */
202     public static final int START_TIMESTAMP_FIRST_FRAME = 4;
203 
204     /** Clock monotonic timestamp of reportFullyDrawn called by application. */
205     public static final int START_TIMESTAMP_FULLY_DRAWN = 5;
206 
207     /** Clock monotonic timestamp of initial renderthread frame. */
208     public static final int START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME = 6;
209 
210     /** Clock monotonic timestamp of surfaceflinger composition complete. */
211     public static final int START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE = 7;
212 
213     /** Process was started for an activity component. */
214     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
215     public static final int START_COMPONENT_ACTIVITY = 1;
216 
217     /** Process was started for a broadcast component. */
218     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
219     public static final int START_COMPONENT_BROADCAST = 2;
220 
221     /** Process was started for a content provider component. */
222     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
223     public static final int START_COMPONENT_CONTENT_PROVIDER = 3;
224 
225     /** Process was started for a service component. */
226     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
227     public static final int START_COMPONENT_SERVICE = 4;
228 
229     /** Process was started not for one of the four standard components. */
230     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
231     public static final int START_COMPONENT_OTHER = 5;
232 
233     /**
234      * @see #getMonotonicCreationTimeMs
235      */
236     private long mMonotonicCreationTimeMs;
237 
238     /**
239      * @see #getStartupState
240      */
241     private @StartupState int mStartupState;
242 
243     /**
244      * @see #getPid
245      */
246     private int mPid;
247 
248     /**
249      * @see #getRealUid
250      */
251     private int mRealUid;
252 
253     /**
254      * @see #getPackageUid
255      */
256     private int mPackageUid;
257 
258     /**
259      * @see #getDefiningUid
260      */
261     private int mDefiningUid;
262 
263     /**
264      * @see #getPackageName
265      */
266     private String mPackageName;
267 
268     /**
269      * @see #getProcessName
270      */
271     private String mProcessName;
272 
273     /**
274      * @see #getReason
275      */
276     private @StartReason int mReason;
277 
278     /**
279      * @see #getStartupTimestamps
280      */
281     private ArrayMap<Integer, Long> mStartupTimestampsNs;
282 
283     /**
284      * @see #getStartType
285      */
286     private @StartType int mStartType;
287 
288     /**
289      * @see #getIntent
290      */
291     private Intent mStartIntent;
292 
293     /**
294      * @see #getLaunchMode
295      */
296     private @LaunchMode int mLaunchMode;
297 
298     /**
299      * @see #wasForceStopped()
300      */
301     private boolean mWasForceStopped;
302 
303     /**
304      * @see #getStartComponent()
305      */
306     private @StartComponent int mStartComponent;
307 
308     /**
309      * @hide *
310      */
311     @IntDef(
312             prefix = {"STARTUP_STATE_"},
313             value = {
314                 STARTUP_STATE_STARTED,
315                 STARTUP_STATE_ERROR,
316                 STARTUP_STATE_FIRST_FRAME_DRAWN,
317             })
318     @Retention(RetentionPolicy.SOURCE)
319     public @interface StartupState {}
320 
321     /**
322      * @hide *
323      */
324     @IntDef(
325             prefix = {"START_REASON_"},
326             value = {
327                 START_REASON_ALARM,
328                 START_REASON_BACKUP,
329                 START_REASON_BOOT_COMPLETE,
330                 START_REASON_BROADCAST,
331                 START_REASON_CONTENT_PROVIDER,
332                 START_REASON_JOB,
333                 START_REASON_LAUNCHER,
334                 START_REASON_LAUNCHER_RECENTS,
335                 START_REASON_OTHER,
336                 START_REASON_PUSH,
337                 START_REASON_SERVICE,
338                 START_REASON_START_ACTIVITY,
339             })
340     @Retention(RetentionPolicy.SOURCE)
341     public @interface StartReason {}
342 
343     /**
344      * @hide *
345      */
346     @IntDef(
347             prefix = {"START_TYPE_"},
348             value = {
349                 START_TYPE_UNSET,
350                 START_TYPE_COLD,
351                 START_TYPE_WARM,
352                 START_TYPE_HOT,
353             })
354     @Retention(RetentionPolicy.SOURCE)
355     public @interface StartType {}
356 
357     /**
358      * @hide *
359      */
360     @IntDef(
361             prefix = {"LAUNCH_MODE_"},
362             value = {
363                 LAUNCH_MODE_STANDARD,
364                 LAUNCH_MODE_SINGLE_TOP,
365                 LAUNCH_MODE_SINGLE_INSTANCE,
366                 LAUNCH_MODE_SINGLE_TASK,
367                 LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK,
368             })
369     @Retention(RetentionPolicy.SOURCE)
370     public @interface LaunchMode {}
371 
372     /**
373      * @hide *
374      */
375     @IntDef(
376             prefix = {"START_COMPONENT_"},
377             value = {
378                 START_COMPONENT_ACTIVITY,
379                 START_COMPONENT_BROADCAST,
380                 START_COMPONENT_CONTENT_PROVIDER,
381                 START_COMPONENT_SERVICE,
382                 START_COMPONENT_OTHER,
383             })
384     @Retention(RetentionPolicy.SOURCE)
385     public @interface StartComponent {}
386 
387     /**
388      * @see #getStartupState
389      * @hide
390      */
setStartupState(final @StartupState int startupState)391     public void setStartupState(final @StartupState int startupState) {
392         mStartupState = startupState;
393     }
394 
395     /**
396      * @see #getPid
397      * @hide
398      */
setPid(final int pid)399     public void setPid(final int pid) {
400         mPid = pid;
401     }
402 
403     /**
404      * @see #getRealUid
405      * @hide
406      */
setRealUid(final int uid)407     public void setRealUid(final int uid) {
408         mRealUid = uid;
409     }
410 
411     /**
412      * @see #getPackageUid
413      * @hide
414      */
setPackageUid(final int uid)415     public void setPackageUid(final int uid) {
416         mPackageUid = uid;
417     }
418 
419     /**
420      * @see #getDefiningUid
421      * @hide
422      */
setDefiningUid(final int uid)423     public void setDefiningUid(final int uid) {
424         mDefiningUid = uid;
425     }
426 
427     /**
428      * @see #getPackageName
429      * @hide
430      */
setPackageName(final String packageName)431     public void setPackageName(final String packageName) {
432         mPackageName = intern(packageName);
433     }
434 
435     /**
436      * @see #getProcessName
437      * @hide
438      */
setProcessName(final String processName)439     public void setProcessName(final String processName) {
440         mProcessName = intern(processName);
441     }
442 
443     /**
444      * @see #getReason
445      * @hide
446      */
setReason(@tartReason int reason)447     public void setReason(@StartReason int reason) {
448         mReason = reason;
449     }
450 
451     /**
452      * @see #getStartupTimestamps
453      * @hide
454      */
addStartupTimestamp(int key, long timestampNs)455     public void addStartupTimestamp(int key, long timestampNs) {
456         if (key < 0 || key > START_TIMESTAMP_RESERVED_RANGE_DEVELOPER) {
457             return;
458         }
459         if (mStartupTimestampsNs == null) {
460             mStartupTimestampsNs = new ArrayMap<Integer, Long>();
461         }
462         mStartupTimestampsNs.put(key, timestampNs);
463     }
464 
465     /**
466      * @see #getStartType
467      * @hide
468      */
setStartType(@tartType int startType)469     public void setStartType(@StartType int startType) {
470         mStartType = startType;
471     }
472 
473     /**
474      * @see #getStartIntent
475      *
476      * <p class="note"> Note: This method will clone the provided intent and ensure that the cloned
477      * intent doesn't contain any large objects like bitmaps in its extras by stripping it in the
478      * least aggressive acceptable way for the individual intent.</p>
479      *
480      * @hide
481      */
setIntent(Intent startIntent)482     public void setIntent(Intent startIntent) {
483         if (startIntent != null) {
484             if (startIntent.canStripForHistory()) {
485                 // If maybeStripForHistory will return a lightened version, do that.
486                 mStartIntent = startIntent.maybeStripForHistory();
487             } else if (startIntent.getExtras() != null) {
488                 // If maybeStripForHistory would not return a lightened version and extras is
489                 // non-null then extras contains un-parcelled data. Use cloneFilter to strip data
490                 // more aggressively.
491                 mStartIntent = startIntent.cloneFilter();
492             } else {
493                 // Finally, if maybeStripForHistory would not return a lightened version and extras
494                 // is null then do a regular clone so we don't leak the intent.
495                 mStartIntent = new Intent(startIntent);
496             }
497 
498             // If the newly cloned intent has an original intent, clear that as we don't need it and
499             // can't guarantee it doesn't need to be stripped as well.
500             if (mStartIntent.getOriginalIntent() != null) {
501                 mStartIntent.setOriginalIntent(null);
502             }
503         }
504     }
505 
506     /**
507      * @see #getLaunchMode
508      * @hide
509      */
setLaunchMode(@aunchMode int launchMode)510     public void setLaunchMode(@LaunchMode int launchMode) {
511         mLaunchMode = launchMode;
512     }
513 
514     /**
515      * @see #wasForceStopped()
516      * @param wasForceStopped whether the app had been force-stopped in the past
517      * @hide
518      */
setForceStopped(boolean wasForceStopped)519     public void setForceStopped(boolean wasForceStopped) {
520         mWasForceStopped = wasForceStopped;
521     }
522 
523     /**
524      * @see #getStartComponent()
525      * @hide
526      */
setStartComponent(@tartComponent int startComponent)527     public void setStartComponent(@StartComponent int startComponent) {
528         mStartComponent = startComponent;
529     }
530 
531     /**
532      * Current state of startup.
533      *
534      * Can be used to determine whether the object will have additional fields added as it may be
535      * queried before all data is collected.
536      *
537      * <p class="note"> Note: field will always be set and available.</p>
538      */
getStartupState()539     public @StartupState int getStartupState() {
540         return mStartupState;
541     }
542 
543     /**
544      * Monotonic elapsed time persisted across reboots.
545      *
546      * @hide
547      */
getMonotonicCreationTimeMs()548     public long getMonotonicCreationTimeMs() {
549         return mMonotonicCreationTimeMs;
550     }
551 
552     /**
553      * The process id.
554      *
555      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
556      */
getPid()557     public int getPid() {
558         return mPid;
559     }
560 
561     /**
562      * The kernel user identifier of the process, most of the time the system uses this to do access
563      * control checks. It's typically the uid of the package where the component is running from,
564      * except the case of isolated process, where this field identifies the kernel user identifier
565      * that this process is actually running with, while the {@link #getPackageUid} identifies the
566      * kernel user identifier that is assigned at the package installation time.
567      *
568      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
569      */
getRealUid()570     public int getRealUid() {
571         return mRealUid;
572     }
573 
574     /**
575      * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the
576      * package installation time.
577      *
578      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
579      */
getPackageUid()580     public int getPackageUid() {
581         return mPackageUid;
582     }
583 
584     /**
585      * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and
586      * {@link #getPackageUid}, if an external service has the {@link
587      * android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set to <code>
588      * true</code> and was bound with the flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}
589      * - in this case, this field here will be the kernel user identifier of the external service
590      * provider.
591      *
592      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
593      */
getDefiningUid()594     public int getDefiningUid() {
595         return mDefiningUid;
596     }
597 
598     /**
599      * Name of first package running in this process;
600      *
601      * @hide
602      */
getPackageName()603     public String getPackageName() {
604         return mPackageName;
605     }
606 
607     /**
608      * The actual process name it was running with.
609      *
610      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
611      */
getProcessName()612     public @NonNull String getProcessName() {
613         return mProcessName;
614     }
615 
616     /**
617      * The reason code of what triggered the process's start.
618      *
619      * Start reason provides granular reasoning on why the app is being started. Start reason should
620      * not be used for distinguishing between the component the app is being started for as some
621      * reasons may overlap with multiple components, see {@link #getStartComponent} for this
622      * functionality instead.
623      *
624      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
625      */
getReason()626     public @StartReason int getReason() {
627         return mReason;
628     }
629 
630     /**
631      * Various clock monotonic timestamps in nanoseconds throughout the startup process.
632      *
633      * <p class="note"> Note: different timestamps will be available for different values of
634      * {@link #getStartupState}:
635      *
636      * (Subsequent rows contain all timestamps of proceding states.)
637      *
638      * For {@link #STARTUP_STATE_STARTED}, timestamp {@link #START_TIMESTAMP_LAUNCH} will be
639      * available.
640      * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available.
641      * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps
642      * {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, {@link #START_TIMESTAMP_BIND_APPLICATION},
643      * and {@link #START_TIMESTAMP_FIRST_FRAME} will additionally be available.
644      *
645      * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is
646      * dependant on devloper calling {@link Activity#reportFullyDrawn}.
647      * </p>
648      */
getStartupTimestamps()649     public @NonNull Map<Integer, Long> getStartupTimestamps() {
650         if (mStartupTimestampsNs == null) {
651             mStartupTimestampsNs = new ArrayMap<Integer, Long>();
652         }
653         return mStartupTimestampsNs;
654     }
655 
656     /**
657      * The state of the app at startup.
658      *
659      * <p class="note"> Note: field will be set for {@link #getStartupState} value
660      * {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}. Not guaranteed for other states.</p>
661      */
getStartType()662     public @StartType int getStartType() {
663         return mStartType;
664     }
665 
666     /**
667      * The intent used to launch the application.
668      *
669      * <p class="note"> Note: Intent is stripped and does not include extras.</p>
670      *
671      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
672      */
673     @SuppressLint("IntentBuilderName")
674     @Nullable
getIntent()675     public Intent getIntent() {
676         return mStartIntent;
677     }
678 
679     /**
680      * An instruction on how the activity should be launched. There are five modes that work in
681      * conjunction with activity flags in Intent objects to determine what should happen when the
682      * activity is called upon to handle an intent.
683      *
684      * Modes:
685      * {@link #LAUNCH_MODE_STANDARD}
686      * {@link #LAUNCH_MODE_SINGLE_TOP}
687      * {@link #LAUNCH_MODE_SINGLE_INSTANCE}
688      * {@link #LAUNCH_MODE_SINGLE_TASK}
689      * {@link #LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK}
690      *
691      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
692      */
getLaunchMode()693     public @LaunchMode int getLaunchMode() {
694         return mLaunchMode;
695     }
696 
697     /**
698      * Informs whether this is the first process launch for an app since it was
699      * {@link ApplicationInfo#FLAG_STOPPED force-stopped} for some reason.
700      * This allows the app to know if it should re-register for any alarms, jobs and other callbacks
701      * that were cleared when the app was force-stopped.
702      *
703      * @return {@code true} if this is the first process launch of the app after having been
704      *      stopped, {@code false} otherwise.
705      */
706     @FlaggedApi(android.content.pm.Flags.FLAG_STAY_STOPPED)
wasForceStopped()707     public boolean wasForceStopped() {
708         return mWasForceStopped;
709     }
710 
711     /**
712      * The component type that was being started which triggered the start.
713      *
714      * Start component should be used to accurately distinguish between the 4 component types:
715      * activity, service, broadcast, and content provider. This can be useful for optimizing
716      * startup flow by enabling the caller to only load the necessary dependencies for a specific
717      * component type. For more granular information on why the app is being started, see
718      * {@link #getReason}.
719      *
720      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
721      */
722     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
getStartComponent()723     public @StartComponent int getStartComponent() {
724         return mStartComponent;
725     }
726 
727     @Override
describeContents()728     public int describeContents() {
729         return 0;
730     }
731 
732     // LINT.IfChange(write_parcel)
733     @Override
writeToParcel(@onNull Parcel dest, int flags)734     public void writeToParcel(@NonNull Parcel dest, int flags) {
735         dest.writeInt(mStartupState);
736         dest.writeInt(mPid);
737         dest.writeInt(mRealUid);
738         dest.writeInt(mPackageUid);
739         dest.writeInt(mDefiningUid);
740         dest.writeString(mPackageName);
741         dest.writeString(mProcessName);
742         dest.writeInt(mReason);
743         dest.writeInt(mStartupTimestampsNs == null ? 0 : mStartupTimestampsNs.size());
744         if (mStartupTimestampsNs != null) {
745             for (int i = 0; i < mStartupTimestampsNs.size(); i++) {
746                 dest.writeInt(mStartupTimestampsNs.keyAt(i));
747                 dest.writeLong(mStartupTimestampsNs.valueAt(i));
748             }
749         }
750         dest.writeInt(mStartType);
751         dest.writeParcelable(mStartIntent, flags);
752         dest.writeInt(mLaunchMode);
753         dest.writeBoolean(mWasForceStopped);
754         dest.writeLong(mMonotonicCreationTimeMs);
755         dest.writeInt(mStartComponent);
756     }
757     // LINT.ThenChange(:read_parcel)
758 
759     /** @hide */
ApplicationStartInfo(long monotonicCreationTimeMs)760     public ApplicationStartInfo(long monotonicCreationTimeMs) {
761         mMonotonicCreationTimeMs = monotonicCreationTimeMs;
762     }
763 
764     /** @hide */
ApplicationStartInfo(ApplicationStartInfo other)765     public ApplicationStartInfo(ApplicationStartInfo other) {
766         mStartupState = other.mStartupState;
767         mPid = other.mPid;
768         mRealUid = other.mRealUid;
769         mPackageUid = other.mPackageUid;
770         mDefiningUid = other.mDefiningUid;
771         mPackageName = other.mPackageName;
772         mProcessName = other.mProcessName;
773         mReason = other.mReason;
774         mStartupTimestampsNs = other.mStartupTimestampsNs;
775         mStartType = other.mStartType;
776         mStartIntent = other.mStartIntent;
777         mLaunchMode = other.mLaunchMode;
778         mWasForceStopped = other.mWasForceStopped;
779         mMonotonicCreationTimeMs = other.mMonotonicCreationTimeMs;
780         mStartComponent = other.mStartComponent;
781     }
782 
783     /** @hide */
784     // LINT.IfChange(read_parcel)
785     @VisibleForTesting
ApplicationStartInfo(@onNull Parcel in)786     public ApplicationStartInfo(@NonNull Parcel in) {
787         mStartupState = in.readInt();
788         mPid = in.readInt();
789         mRealUid = in.readInt();
790         mPackageUid = in.readInt();
791         mDefiningUid = in.readInt();
792         mPackageName = intern(in.readString());
793         mProcessName = intern(in.readString());
794         mReason = in.readInt();
795         int starupTimestampCount = in.readInt();
796         for (int i = 0; i < starupTimestampCount; i++) {
797             int key = in.readInt();
798             long val = in.readLong();
799             addStartupTimestamp(key, val);
800         }
801         mStartType = in.readInt();
802         mStartIntent =
803                 in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class);
804         mLaunchMode = in.readInt();
805         mWasForceStopped = in.readBoolean();
806         mMonotonicCreationTimeMs = in.readLong();
807         mStartComponent = in.readInt();
808     }
809     // LINT.ThenChange(:write_parcel)
810 
intern(@ullable String source)811     private static String intern(@Nullable String source) {
812         return source != null ? source.intern() : null;
813     }
814 
815     public @NonNull static final Creator<ApplicationStartInfo> CREATOR =
816             new Creator<ApplicationStartInfo>() {
817                 @Override
818                 public ApplicationStartInfo createFromParcel(Parcel in) {
819                     return new ApplicationStartInfo(in);
820                 }
821 
822                 @Override
823                 public ApplicationStartInfo[] newArray(int size) {
824                     return new ApplicationStartInfo[size];
825                 }
826             };
827 
828     private static final String PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS = "timestamps";
829     private static final String PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP = "timestamp";
830     private static final String PROTO_SERIALIZER_ATTRIBUTE_KEY = "key";
831     private static final String PROTO_SERIALIZER_ATTRIBUTE_TS = "ts";
832     private static final String PROTO_SERIALIZER_ATTRIBUTE_INTENT = "intent";
833 
834     /**
835      * Write to a protocol buffer output stream. Protocol buffer message definition at {@link
836      * android.app.ApplicationStartInfoProto}
837      *
838      * @param proto Stream to write the ApplicationStartInfo object to.
839      * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message
840      * @hide
841      */
842     // LINT.IfChange(write_proto)
writeToProto(ProtoOutputStream proto, long fieldId, ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream, TypedXmlSerializer typedXmlSerializer)843     public void writeToProto(ProtoOutputStream proto, long fieldId,
844             ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream,
845             TypedXmlSerializer typedXmlSerializer) throws IOException {
846         final long token = proto.start(fieldId);
847         proto.write(ApplicationStartInfoProto.PID, mPid);
848         proto.write(ApplicationStartInfoProto.REAL_UID, mRealUid);
849         proto.write(ApplicationStartInfoProto.PACKAGE_UID, mPackageUid);
850         proto.write(ApplicationStartInfoProto.DEFINING_UID, mDefiningUid);
851         proto.write(ApplicationStartInfoProto.PROCESS_NAME, mProcessName);
852         proto.write(ApplicationStartInfoProto.STARTUP_STATE, mStartupState);
853         proto.write(ApplicationStartInfoProto.REASON, mReason);
854         if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) {
855             byteArrayOutputStream = new ByteArrayOutputStream();
856             objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
857             typedXmlSerializer = Xml.resolveSerializer(objectOutputStream);
858             typedXmlSerializer.startDocument(null, true);
859             typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS);
860             for (int i = 0; i < mStartupTimestampsNs.size(); i++) {
861                 typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP);
862                 typedXmlSerializer.attributeInt(null, PROTO_SERIALIZER_ATTRIBUTE_KEY,
863                         mStartupTimestampsNs.keyAt(i));
864                 typedXmlSerializer.attributeLong(null, PROTO_SERIALIZER_ATTRIBUTE_TS,
865                         mStartupTimestampsNs.valueAt(i));
866                 typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP);
867             }
868             typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS);
869             typedXmlSerializer.endDocument();
870             proto.write(ApplicationStartInfoProto.STARTUP_TIMESTAMPS,
871                     byteArrayOutputStream.toByteArray());
872             objectOutputStream.close();
873         }
874         proto.write(ApplicationStartInfoProto.START_TYPE, mStartType);
875         if (mStartIntent != null) {
876             byteArrayOutputStream = new ByteArrayOutputStream();
877             objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
878             typedXmlSerializer = Xml.resolveSerializer(objectOutputStream);
879             typedXmlSerializer.startDocument(null, true);
880             typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT);
881             mStartIntent.saveToXml(typedXmlSerializer);
882             typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT);
883             typedXmlSerializer.endDocument();
884             proto.write(ApplicationStartInfoProto.START_INTENT,
885                     byteArrayOutputStream.toByteArray());
886             objectOutputStream.close();
887         }
888         proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode);
889         proto.write(ApplicationStartInfoProto.WAS_FORCE_STOPPED, mWasForceStopped);
890         proto.write(ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS, mMonotonicCreationTimeMs);
891         proto.write(ApplicationStartInfoProto.START_COMPONENT, mStartComponent);
892         proto.end(token);
893     }
894     // LINT.ThenChange(:read_proto)
895 
896     /**
897      * Read from a protocol buffer input stream. Protocol buffer message definition at {@link
898      * android.app.ApplicationStartInfoProto}
899      *
900      * @param proto Stream to read the ApplicationStartInfo object from.
901      * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message
902      * @hide
903      */
904     // LINT.IfChange(read_proto)
readFromProto(ProtoInputStream proto, long fieldId, ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream, TypedXmlPullParser typedXmlPullParser)905     public void readFromProto(ProtoInputStream proto, long fieldId,
906             ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream,
907             TypedXmlPullParser typedXmlPullParser)
908             throws IOException, WireTypeMismatchException, ClassNotFoundException {
909         final long token = proto.start(fieldId);
910         while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
911             switch (proto.getFieldNumber()) {
912                 case (int) ApplicationStartInfoProto.PID:
913                     mPid = proto.readInt(ApplicationStartInfoProto.PID);
914                     break;
915                 case (int) ApplicationStartInfoProto.REAL_UID:
916                     mRealUid = proto.readInt(ApplicationStartInfoProto.REAL_UID);
917                     break;
918                 case (int) ApplicationStartInfoProto.PACKAGE_UID:
919                     mPackageUid = proto.readInt(ApplicationStartInfoProto.PACKAGE_UID);
920                     break;
921                 case (int) ApplicationStartInfoProto.DEFINING_UID:
922                     mDefiningUid = proto.readInt(ApplicationStartInfoProto.DEFINING_UID);
923                     break;
924                 case (int) ApplicationStartInfoProto.PROCESS_NAME:
925                     mProcessName = intern(proto.readString(ApplicationStartInfoProto.PROCESS_NAME));
926                     break;
927                 case (int) ApplicationStartInfoProto.STARTUP_STATE:
928                     mStartupState = proto.readInt(ApplicationStartInfoProto.STARTUP_STATE);
929                     break;
930                 case (int) ApplicationStartInfoProto.REASON:
931                     mReason = proto.readInt(ApplicationStartInfoProto.REASON);
932                     break;
933                 case (int) ApplicationStartInfoProto.STARTUP_TIMESTAMPS:
934                     byteArrayInputStream = new ByteArrayInputStream(proto.readBytes(
935                             ApplicationStartInfoProto.STARTUP_TIMESTAMPS));
936                     objectInputStream = new ObjectInputStream(byteArrayInputStream);
937                     mStartupTimestampsNs = new ArrayMap<Integer, Long>();
938                     try {
939                         typedXmlPullParser = Xml.resolvePullParser(objectInputStream);
940                         XmlUtils.beginDocument(typedXmlPullParser,
941                                 PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS);
942                         int depth = typedXmlPullParser.getDepth();
943                         while (XmlUtils.nextElementWithin(typedXmlPullParser, depth)) {
944                             if (PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP.equals(
945                                     typedXmlPullParser.getName())) {
946                                 int key = typedXmlPullParser.getAttributeInt(null,
947                                         PROTO_SERIALIZER_ATTRIBUTE_KEY);
948                                 long ts = typedXmlPullParser.getAttributeLong(null,
949                                         PROTO_SERIALIZER_ATTRIBUTE_TS);
950                                 mStartupTimestampsNs.put(key, ts);
951                             }
952                         }
953                     } catch (XmlPullParserException e) {
954                         // Timestamps lost
955                     }
956                     objectInputStream.close();
957                     break;
958                 case (int) ApplicationStartInfoProto.START_TYPE:
959                     mStartType = proto.readInt(ApplicationStartInfoProto.START_TYPE);
960                     break;
961                 case (int) ApplicationStartInfoProto.START_INTENT:
962                     byteArrayInputStream = new ByteArrayInputStream(proto.readBytes(
963                             ApplicationStartInfoProto.START_INTENT));
964                     objectInputStream = new ObjectInputStream(byteArrayInputStream);
965                     try {
966                         typedXmlPullParser = Xml.resolvePullParser(objectInputStream);
967                         XmlUtils.beginDocument(typedXmlPullParser,
968                                 PROTO_SERIALIZER_ATTRIBUTE_INTENT);
969                         mStartIntent = Intent.restoreFromXml(typedXmlPullParser);
970                     } catch (XmlPullParserException e) {
971                         // Intent lost
972                     }
973                     objectInputStream.close();
974                     break;
975                 case (int) ApplicationStartInfoProto.LAUNCH_MODE:
976                     mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE);
977                     break;
978                 case (int) ApplicationStartInfoProto.WAS_FORCE_STOPPED:
979                     mWasForceStopped = proto.readBoolean(
980                             ApplicationStartInfoProto.WAS_FORCE_STOPPED);
981                     break;
982                 case (int) ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS:
983                     mMonotonicCreationTimeMs = proto.readLong(
984                             ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS);
985                     break;
986                 case (int) ApplicationStartInfoProto.START_COMPONENT:
987                     mStartComponent = proto.readInt(ApplicationStartInfoProto.START_COMPONENT);
988                     break;
989             }
990         }
991         proto.end(token);
992     }
993     // LINT.ThenChange(:write_proto)
994 
995     /** @hide */
dump(@onNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, @NonNull SimpleDateFormat sdf)996     public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix,
997             @NonNull SimpleDateFormat sdf) {
998         StringBuilder sb = new StringBuilder();
999         sb.append(prefix)
1000                 .append("ApplicationStartInfo ").append(seqSuffix).append(':')
1001                 .append('\n')
1002                 .append(" monotonicCreationTimeMs=").append(mMonotonicCreationTimeMs)
1003                 .append('\n')
1004                 .append(" pid=").append(mPid)
1005                 .append(" realUid=").append(mRealUid)
1006                 .append(" packageUid=").append(mPackageUid)
1007                 .append(" definingUid=").append(mDefiningUid)
1008                 .append(" user=").append(UserHandle.getUserId(mPackageUid))
1009                 .append('\n')
1010                 .append(" package=").append(mPackageName)
1011                 .append(" process=").append(mProcessName)
1012                 .append(" startupState=").append(mStartupState)
1013                 .append(" reason=").append(reasonToString(mReason))
1014                 .append(" startType=").append(startTypeToString(mStartType))
1015                 .append(" launchMode=").append(mLaunchMode)
1016                 .append(" wasForceStopped=").append(mWasForceStopped);
1017         if (Flags.appStartInfoComponent()) {
1018             sb.append(" startComponent=").append(startComponentToString(mStartComponent));
1019         }
1020         sb.append('\n');
1021         if (mStartIntent != null) {
1022             sb.append(" intent=").append(mStartIntent.toString())
1023                 .append('\n');
1024         }
1025         if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) {
1026             sb.append(" timestamps: ");
1027             for (int i = 0; i < mStartupTimestampsNs.size(); i++) {
1028                 sb.append(mStartupTimestampsNs.keyAt(i)).append("=").append(mStartupTimestampsNs
1029                         .valueAt(i)).append(" ");
1030             }
1031             sb.append('\n');
1032         }
1033         pw.print(sb.toString());
1034     }
1035 
reasonToString(@tartReason int reason)1036     private static String reasonToString(@StartReason int reason) {
1037         return switch (reason) {
1038             case START_REASON_ALARM -> "ALARM";
1039             case START_REASON_BACKUP -> "BACKUP";
1040             case START_REASON_BOOT_COMPLETE -> "BOOT COMPLETE";
1041             case START_REASON_BROADCAST -> "BROADCAST";
1042             case START_REASON_CONTENT_PROVIDER -> "CONTENT PROVIDER";
1043             case START_REASON_JOB -> "JOB";
1044             case START_REASON_LAUNCHER -> "LAUNCHER";
1045             case START_REASON_LAUNCHER_RECENTS -> "LAUNCHER RECENTS";
1046             case START_REASON_OTHER -> "OTHER";
1047             case START_REASON_PUSH -> "PUSH";
1048             case START_REASON_SERVICE -> "SERVICE";
1049             case START_REASON_START_ACTIVITY -> "START ACTIVITY";
1050             default -> "";
1051         };
1052     }
1053 
startTypeToString(@tartType int startType)1054     private static String startTypeToString(@StartType int startType) {
1055         return switch (startType) {
1056             case START_TYPE_UNSET -> "UNSET";
1057             case START_TYPE_COLD -> "COLD";
1058             case START_TYPE_WARM -> "WARM";
1059             case START_TYPE_HOT -> "HOT";
1060             default -> "";
1061         };
1062     }
1063 
1064     @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT)
1065     private static String startComponentToString(@StartComponent int startComponent) {
1066         return switch (startComponent) {
1067             case START_COMPONENT_ACTIVITY -> "ACTIVITY";
1068             case START_COMPONENT_BROADCAST -> "BROADCAST";
1069             case START_COMPONENT_CONTENT_PROVIDER -> "CONTENT PROVIDER";
1070             case START_COMPONENT_SERVICE -> "SERVICE";
1071             case START_COMPONENT_OTHER -> "OTHER";
1072             default -> "";
1073         };
1074     }
1075 
1076     /** @hide */
1077     @Override
1078     public boolean equals(@Nullable Object other) {
1079         if (other == null || !(other instanceof ApplicationStartInfo)) {
1080             return false;
1081         }
1082 
1083         final ApplicationStartInfo o = (ApplicationStartInfo) other;
1084 
1085         boolean intentEquals = true;
1086         if (android.content.flags.Flags.intentSaveToXmlPackage()) {
1087             if (mStartIntent == null) {
1088                 intentEquals = o.mStartIntent == null;
1089             } else {
1090                 intentEquals = mStartIntent.filterEquals(o.mStartIntent);
1091             }
1092         }
1093 
1094         return mPid == o.mPid
1095                 && mRealUid == o.mRealUid
1096                 && mPackageUid == o.mPackageUid
1097                 && mDefiningUid == o.mDefiningUid
1098                 && mReason == o.mReason
1099                 && mStartupState == o.mStartupState
1100                 && mStartType == o.mStartType
1101                 && mLaunchMode == o.mLaunchMode
1102                 && TextUtils.equals(mPackageName, o.mPackageName)
1103                 && TextUtils.equals(mProcessName, o.mProcessName)
1104                 && timestampsEquals(o)
1105                 && mWasForceStopped == o.mWasForceStopped
1106                 && mMonotonicCreationTimeMs == o.mMonotonicCreationTimeMs
1107                 && mStartComponent == o.mStartComponent
1108                 && intentEquals;
1109     }
1110 
1111     @Override
1112     public int hashCode() {
1113         return Objects.hash(mPid, mRealUid, mPackageUid, mDefiningUid, mReason, mStartupState,
1114                 mStartType, mLaunchMode, mPackageName, mProcessName, mStartupTimestampsNs,
1115                 mMonotonicCreationTimeMs, mStartComponent,
1116                 android.content.flags.Flags.intentSaveToXmlPackage() ? mStartIntent : null);
1117     }
1118 
1119     private boolean timestampsEquals(@NonNull ApplicationStartInfo other) {
1120         if (mStartupTimestampsNs == null && other.mStartupTimestampsNs == null) {
1121             return true;
1122         }
1123         if (mStartupTimestampsNs == null || other.mStartupTimestampsNs == null) {
1124             return false;
1125         }
1126         return mStartupTimestampsNs.equals(other.mStartupTimestampsNs);
1127     }
1128 }
1129