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.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SuppressLint;
23 import android.content.Intent;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 
27 import java.lang.annotation.ElementType;
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.lang.annotation.Target;
31 import java.util.HashMap;
32 import java.util.Map;
33 
34 /**
35  * Provide information related to a processes startup.
36  *
37  * @hide
38  */
39 public final class ApplicationStartInfo implements Parcelable {
40 
41     /**
42      * State indicating process startup has started. Some information is available in
43      * {@link ApplicationStartInfo} and more will be added.
44      */
45     public static final int STARTUP_STATE_STARTED = 0;
46 
47     /**
48      * State indicating process startup has failed. Startup information in
49      * {@link ApplicationStartInfo} is incomplete, but no more will be added.
50      */
51     public static final int STARTUP_STATE_ERROR = 1;
52 
53     /**
54      * State indicating process startup has made it to first frame draw. Startup
55      * information in {@link ApplicationStartInfo} is complete with potential exception
56      * of fully drawn timestamp which is not guaranteed to be set.
57      */
58     public static final int STARTUP_STATE_FIRST_FRAME_DRAWN = 2;
59 
60     /** Process started due to alarm. */
61     public static final int START_REASON_ALARM = 0;
62 
63     /** Process started to run backup. */
64     public static final int START_REASON_BACKUP = 1;
65 
66     /** Process started due to boot complete. */
67     public static final int START_REASON_BOOT_COMPLETE = 2;
68 
69     /**  Process started due to broadcast received. */
70     public static final int START_REASON_BROADCAST = 3;
71 
72     /** Process started due to access of ContentProvider */
73     public static final int START_REASON_CONTENT_PROVIDER = 4;
74 
75     /** * Process started to run scheduled job. */
76     public static final int START_REASON_JOB = 5;
77 
78     /** Process started due to click app icon or widget from launcher. */
79     public static final int START_REASON_LAUNCHER = 6;
80 
81     /** Process started not for any of the listed reasons. */
82     public static final int START_REASON_OTHER = 7;
83 
84     /** Process started due to push message. */
85     public static final int START_REASON_PUSH = 8;
86 
87     /** Process started to resume activity. */
88     public static final int START_REASON_RESUMED_ACTIVITY = 9;
89 
90     /** Process service started. */
91     public static final int START_REASON_SERVICE = 10;
92 
93     /** Process started due to Activity started for any reason not explicitly listed. */
94     public static final int START_REASON_START_ACTIVITY = 11;
95 
96     /** Process started from scratch. */
97     public static final int START_TYPE_COLD = 0;
98 
99     /** Process retained minimally SavedInstanceState. */
100     public static final int START_TYPE_WARM = 1;
101 
102     /** Process brought back to foreground. */
103     public static final int START_TYPE_HOT = 2;
104 
105     /**
106      * Default. The system always creates a new instance of the activity in the target task and
107      * routes the intent to it.
108      */
109     public static final int LAUNCH_MODE_STANDARD = 0;
110 
111     /**
112      * If an instance of the activity already exists at the top of the target task, the system
113      * routes the intent to that instance through a call to its onNewIntent() method, rather than
114      * creating a new instance of the activity.
115      */
116     public static final int LAUNCH_MODE_SINGLE_TOP = 1;
117 
118     /**
119      * The system creates the activity at the root of a new task or locates the activity on an
120      * existing task with the same affinity. If an instance of the activity already exists and is at
121      * the root of the task, the system routes the intent to existing instance through a call to its
122      * onNewIntent() method, rather than creating a new one.
123      */
124     public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2;
125 
126     /**
127      * Same as "singleTask", except that the system doesn't launch any other activities into the
128      * task holding the instance. The activity is always the single and only member of its task.
129      */
130     public static final int LAUNCH_MODE_SINGLE_TASK = 3;
131 
132     /**
133      * The activity can only be running as the root activity of the task, the first activity that
134      * created the task, and therefore there will only be one instance of this activity in a task;
135      * but activity can be instantiated multiple times in different tasks.
136      */
137     public static final int LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK = 4;
138 
139     /** Clock monotonic timestamp of launch started. */
140     public static final int START_TIMESTAMP_LAUNCH = 0;
141 
142     /** Clock monotonic timestamp of finish java classloading. */
143     public static final int START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE = 1;
144 
145     /** Clock monotonic timestamp of Application onCreate called. */
146     public static final int START_TIMESTAMP_APPLICATION_ONCREATE = 2;
147 
148     /** Clock monotonic timestamp of bindApplication called. */
149     public static final int START_TIMESTAMP_BIND_APPLICATION = 3;
150 
151     /** Clock monotonic timestamp of first frame drawn. */
152     public static final int START_TIMESTAMP_FIRST_FRAME = 4;
153 
154     /** Clock monotonic timestamp of reportFullyDrawn called by application. */
155     public static final int START_TIMESTAMP_FULLY_DRAWN = 5;
156 
157     /**
158      * @see #getStartupState
159      */
160     private @StartupState int mStartupState;
161 
162     /**
163      * @see #getPid
164      */
165     private int mPid;
166 
167     /**
168      * @see #getRealUid
169      */
170     private int mRealUid;
171 
172     /**
173      * @see #getPackageUid
174      */
175     private int mPackageUid;
176 
177     /**
178      * @see #getDefiningUid
179      */
180     private int mDefiningUid;
181 
182     /**
183      * @see #getProcessName
184      */
185     private String mProcessName;
186 
187     /**
188      * @see #getReason
189      */
190     private @StartReason int mReason;
191 
192     /**
193      * @see #getStartupTimestamps
194      */
195     private Map<@StartupTimestamp Integer, Long> mStartupTimestampsNs;
196 
197     /**
198      * @see #getStartType
199      */
200     private @StartType int mStartType;
201 
202     /**
203      * @see #getStartIntent
204      */
205     private Intent mStartIntent;
206 
207     /**
208      * @see #getLaunchMode
209      */
210     private @LaunchMode int mLaunchMode;
211 
212     /**
213      * @hide *
214      */
215     @IntDef(
216             prefix = {"STARTUP_STATE_"},
217             value = {
218                 STARTUP_STATE_STARTED,
219                 STARTUP_STATE_ERROR,
220                 STARTUP_STATE_FIRST_FRAME_DRAWN,
221             })
222     @Retention(RetentionPolicy.SOURCE)
223     public @interface StartupState {}
224 
225     /**
226      * @hide *
227      */
228     @IntDef(
229             prefix = {"START_REASON_"},
230             value = {
231                 START_REASON_ALARM,
232                 START_REASON_BACKUP,
233                 START_REASON_BOOT_COMPLETE,
234                 START_REASON_BROADCAST,
235                 START_REASON_CONTENT_PROVIDER,
236                 START_REASON_JOB,
237                 START_REASON_LAUNCHER,
238                 START_REASON_OTHER,
239                 START_REASON_PUSH,
240                 START_REASON_RESUMED_ACTIVITY,
241                 START_REASON_SERVICE,
242                 START_REASON_START_ACTIVITY,
243             })
244     @Retention(RetentionPolicy.SOURCE)
245     public @interface StartReason {}
246 
247     /**
248      * @hide *
249      */
250     @IntDef(
251             prefix = {"START_TYPE_"},
252             value = {
253                 START_TYPE_COLD,
254                 START_TYPE_WARM,
255                 START_TYPE_HOT,
256             })
257     @Retention(RetentionPolicy.SOURCE)
258     public @interface StartType {}
259 
260     /**
261      * @hide *
262      */
263     @IntDef(
264             prefix = {"LAUNCH_MODE_"},
265             value = {
266                 LAUNCH_MODE_STANDARD,
267                 LAUNCH_MODE_SINGLE_TOP,
268                 LAUNCH_MODE_SINGLE_INSTANCE,
269                 LAUNCH_MODE_SINGLE_TASK,
270                 LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK,
271             })
272     @Retention(RetentionPolicy.SOURCE)
273     public @interface LaunchMode {}
274 
275     /**
276      * @hide *
277      */
278     @IntDef(
279             prefix = {"START_TIMESTAMP_"},
280             value = {
281                 START_TIMESTAMP_LAUNCH,
282                 START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE,
283                 START_TIMESTAMP_APPLICATION_ONCREATE,
284                 START_TIMESTAMP_BIND_APPLICATION,
285                 START_TIMESTAMP_FULLY_DRAWN,
286             })
287     @Retention(RetentionPolicy.SOURCE)
288     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
289     public @interface StartupTimestamp {}
290 
291     /**
292      * @see #getStartupState
293      * @hide
294      */
setStartupState(final @StartupState int startupState)295     public void setStartupState(final @StartupState int startupState) {
296         mStartupState = startupState;
297     }
298 
299     /**
300      * @see #getPid
301      * @hide
302      */
setPid(final int pid)303     public void setPid(final int pid) {
304         mPid = pid;
305     }
306 
307     /**
308      * @see #getRealUid
309      * @hide
310      */
setRealUid(final int uid)311     public void setRealUid(final int uid) {
312         mRealUid = uid;
313     }
314 
315     /**
316      * @see #getPackageUid
317      * @hide
318      */
setPackageUid(final int uid)319     public void setPackageUid(final int uid) {
320         mPackageUid = uid;
321     }
322 
323     /**
324      * @see #getDefiningUid
325      * @hide
326      */
setDefiningUid(final int uid)327     public void setDefiningUid(final int uid) {
328         mDefiningUid = uid;
329     }
330 
331     /**
332      * @see #getProcessName
333      * @hide
334      */
setProcessName(final String processName)335     public void setProcessName(final String processName) {
336         mProcessName = intern(processName);
337     }
338 
339     /**
340      * @see #getReason
341      * @hide
342      */
setReason(@tartReason int reason)343     public void setReason(@StartReason int reason) {
344         mReason = reason;
345     }
346 
347     /**
348      * @see #getStartupTimestamps
349      * @hide
350      */
addStartupTimestamp(@tartupTimestamp int key, long timestampNs)351     public void addStartupTimestamp(@StartupTimestamp int key, long timestampNs) {
352         if (mStartupTimestampsNs == null) {
353             mStartupTimestampsNs = new HashMap<@StartupTimestamp Integer, Long>();
354         }
355         mStartupTimestampsNs.put(key, timestampNs);
356     }
357 
358     /**
359      * @see #getStartType
360      * @hide
361      */
setStartType(@tartType int startType)362     public void setStartType(@StartType int startType) {
363         mStartType = startType;
364     }
365 
366     /**
367      * @see #getStartIntent
368      * @hide
369      */
setIntent(Intent startIntent)370     public void setIntent(Intent startIntent) {
371         mStartIntent = startIntent;
372     }
373 
374     /**
375      * @see #getLaunchMode
376      * @hide
377      */
setLaunchMode(@aunchMode int launchMode)378     public void setLaunchMode(@LaunchMode int launchMode) {
379         mLaunchMode = launchMode;
380     }
381 
382     /**
383      * Current state of startup.
384      *
385      * Can be used to determine whether the object will have additional fields added as it may be
386      * queried before all data is collected.
387      *
388      * <p class="note"> Note: field will always be set and available.</p>
389      */
getStartupState()390     public @StartupState int getStartupState() {
391         return mStartupState;
392     }
393 
394     /**
395      * The process id.
396      *
397      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
398      */
getPid()399     public int getPid() {
400         return mPid;
401     }
402 
403     /**
404      * The kernel user identifier of the process, most of the time the system uses this to do access
405      * control checks. It's typically the uid of the package where the component is running from,
406      * except the case of isolated process, where this field identifies the kernel user identifier
407      * that this process is actually running with, while the {@link #getPackageUid} identifies the
408      * kernel user identifier that is assigned at the package installation time.
409      *
410      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
411      */
getRealUid()412     public int getRealUid() {
413         return mRealUid;
414     }
415 
416     /**
417      * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the
418      * package installation time.
419      *
420      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
421      */
getPackageUid()422     public int getPackageUid() {
423         return mPackageUid;
424     }
425 
426     /**
427      * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and
428      * {@link #getPackageUid}, if an external service has the {@link
429      * android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set to <code>
430      * true</code> and was bound with the flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}
431      * - in this case, this field here will be the kernel user identifier of the external service
432      * provider.
433      *
434      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
435      */
getDefiningUid()436     public int getDefiningUid() {
437         return mDefiningUid;
438     }
439 
440     /**
441      * The actual process name it was running with.
442      *
443      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
444      */
getProcessName()445     public @NonNull String getProcessName() {
446         return mProcessName;
447     }
448 
449     /**
450      * The reason code of what triggered the process's start.
451      *
452      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
453      */
getReason()454     public @StartReason int getReason() {
455         return mReason;
456     }
457 
458     /**
459      * Various clock monotonic timestamps in nanoseconds throughout the startup process.
460      *
461      * <p class="note"> Note: different timestamps will be available for different values of
462      * {@link #getStartupState}:
463      *
464      * (Subsequent rows contain all timestamps of proceding states.)
465      *
466      * For {@link #STARTUP_STATE_STARTED}, timestamp {@link #START_TIMESTAMP_LAUNCH} will be
467      * available.
468      * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available.
469      * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps
470      * {@link #START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE}, {@link #START_TIMESTAMP_APPLICATION_ONCREATE},
471      * {@link #START_TIMESTAMP_BIND_APPLICATION}, and {@link #START_TIMESTAMP_FIRST_FRAME} will
472      * additionally be available.
473      *
474      * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is
475      * dependant on devloper calling {@link Activity#reportFullyDrawn}.
476      * </p>
477      */
getStartupTimestamps()478     public @NonNull Map<@StartupTimestamp Integer, Long> getStartupTimestamps() {
479         if (mStartupTimestampsNs == null) {
480             mStartupTimestampsNs = new HashMap<@StartupTimestamp Integer, Long>();
481         }
482         return mStartupTimestampsNs;
483     }
484 
485     /**
486      * The state of the app at startup.
487      *
488      * <p class="note"> Note: field will be set for {@link #getStartupState} value
489      * {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}. Not guaranteed for other states.</p>
490      */
getStartType()491     public @StartType int getStartType() {
492         return mStartType;
493     }
494 
495     /**
496      * The intent used to launch the application.
497      *
498      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
499      */
500     @SuppressLint("IntentBuilderName")
501     @Nullable
getIntent()502     public Intent getIntent() {
503         return mStartIntent;
504     }
505 
506     /**
507      * An instruction on how the activity should be launched. There are five modes that work in
508      * conjunction with activity flags in Intent objects to determine what should happen when the
509      * activity is called upon to handle an intent.
510      *
511      * Modes:
512      * {@link #LAUNCH_MODE_STANDARD}
513      * {@link #LAUNCH_MODE_SINGLE_TOP}
514      * {@link #LAUNCH_MODE_SINGLE_INSTANCE}
515      * {@link #LAUNCH_MODE_SINGLE_TASK}
516      * {@link #LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK}
517      *
518      * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
519      */
getLaunchMode()520     public @LaunchMode int getLaunchMode() {
521         return mLaunchMode;
522     }
523 
524     @Override
describeContents()525     public int describeContents() {
526         return 0;
527     }
528 
529     @Override
writeToParcel(@onNull Parcel dest, int flags)530     public void writeToParcel(@NonNull Parcel dest, int flags) {
531         dest.writeInt(mStartupState);
532         dest.writeInt(mPid);
533         dest.writeInt(mRealUid);
534         dest.writeInt(mPackageUid);
535         dest.writeInt(mDefiningUid);
536         dest.writeString(mProcessName);
537         dest.writeInt(mReason);
538         dest.writeInt(mStartupTimestampsNs.size());
539         for (@StartupTimestamp int key : mStartupTimestampsNs.keySet()) {
540             dest.writeInt(key);
541             dest.writeLong(mStartupTimestampsNs.get(key));
542         }
543         dest.writeInt(mStartType);
544         dest.writeParcelable(mStartIntent, flags);
545         dest.writeInt(mLaunchMode);
546     }
547 
548     /** @hide */
ApplicationStartInfo()549     public ApplicationStartInfo() {}
550 
551     /** @hide */
ApplicationStartInfo(ApplicationStartInfo other)552     public ApplicationStartInfo(ApplicationStartInfo other) {
553         mStartupState = other.mStartupState;
554         mPid = other.mPid;
555         mRealUid = other.mRealUid;
556         mPackageUid = other.mPackageUid;
557         mDefiningUid = other.mDefiningUid;
558         mProcessName = other.mProcessName;
559         mReason = other.mReason;
560         mStartupTimestampsNs = other.mStartupTimestampsNs;
561         mStartType = other.mStartType;
562         mStartIntent = other.mStartIntent;
563         mLaunchMode = other.mLaunchMode;
564     }
565 
ApplicationStartInfo(@onNull Parcel in)566     private ApplicationStartInfo(@NonNull Parcel in) {
567         mStartupState = in.readInt();
568         mPid = in.readInt();
569         mRealUid = in.readInt();
570         mPackageUid = in.readInt();
571         mDefiningUid = in.readInt();
572         mProcessName = intern(in.readString());
573         mReason = in.readInt();
574         int starupTimestampCount = in.readInt();
575         for (int i = 0; i < starupTimestampCount; i++) {
576             int key = in.readInt();
577             long val = in.readLong();
578             addStartupTimestamp(key, val);
579         }
580         mStartType = in.readInt();
581         mStartIntent =
582                 in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class);
583         mLaunchMode = in.readInt();
584     }
585 
intern(@ullable String source)586     private static String intern(@Nullable String source) {
587         return source != null ? source.intern() : null;
588     }
589 
590     public @NonNull static final Creator<ApplicationStartInfo> CREATOR =
591             new Creator<ApplicationStartInfo>() {
592                 @Override
593                 public ApplicationStartInfo createFromParcel(Parcel in) {
594                     return new ApplicationStartInfo(in);
595                 }
596 
597                 @Override
598                 public ApplicationStartInfo[] newArray(int size) {
599                     return new ApplicationStartInfo[size];
600                 }
601             };
602 }
603