/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.icu.text.SimpleDateFormat; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Xml; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; import android.util.proto.WireTypeMismatchException; import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Map; import java.util.Objects; /** * Describes information related to an application process's startup. * *
* Many aspects concerning why and how an applications process was started are valuable for apps * both for logging and for potential behavior changes. Reason for process start, start type, * start times, throttling, and other useful diagnostic data can be obtained from * {@link ApplicationStartInfo} records. *
*/ @FlaggedApi(Flags.FLAG_APP_START_INFO) public final class ApplicationStartInfo implements Parcelable { /** * State indicating process startup has started. Some information is available in * {@link ApplicationStartInfo} and more will be added. */ public static final int STARTUP_STATE_STARTED = 0; /** * State indicating process startup has failed. Startup information in * {@link ApplicationStartInfo} is incomplete, but no more will be added. */ public static final int STARTUP_STATE_ERROR = 1; /** * State indicating process startup has made it to first frame draw. Startup * information in {@link ApplicationStartInfo} is complete with potential exception * of fully drawn timestamp which is not guaranteed to be set. */ public static final int STARTUP_STATE_FIRST_FRAME_DRAWN = 2; /** Process started due to alarm. */ public static final int START_REASON_ALARM = 0; /** Process started to run backup. */ public static final int START_REASON_BACKUP = 1; /** Process started due to boot complete. */ public static final int START_REASON_BOOT_COMPLETE = 2; /** Process started due to broadcast received. */ public static final int START_REASON_BROADCAST = 3; /** Process started due to access of ContentProvider */ public static final int START_REASON_CONTENT_PROVIDER = 4; /** * Process started to run scheduled job. */ public static final int START_REASON_JOB = 5; /** Process started due to click app icon or widget from launcher. */ public static final int START_REASON_LAUNCHER = 6; /** Process started from launcher recents. */ public static final int START_REASON_LAUNCHER_RECENTS = 7; /** Process started not for any of the listed reasons. */ public static final int START_REASON_OTHER = 8; /** Process started due to push message. */ public static final int START_REASON_PUSH = 9; /** Process service started. */ public static final int START_REASON_SERVICE = 10; /** Process started due to Activity started for any reason not explicitly listed. */ public static final int START_REASON_START_ACTIVITY = 11; /** Start type not yet set. */ public static final int START_TYPE_UNSET = 0; /** Process started from scratch. */ public static final int START_TYPE_COLD = 1; /** Process retained minimally SavedInstanceState. */ public static final int START_TYPE_WARM = 2; /** Process brought back to foreground. */ public static final int START_TYPE_HOT = 3; /** * Default. The system always creates a new instance of the activity in the target task and * routes the intent to it. */ public static final int LAUNCH_MODE_STANDARD = 0; /** * If an instance of the activity already exists at the top of the target task, the system * routes the intent to that instance through a call to its onNewIntent() method, rather than * creating a new instance of the activity. */ public static final int LAUNCH_MODE_SINGLE_TOP = 1; /** * The system creates the activity at the root of a new task or locates the activity on an * existing task with the same affinity. If an instance of the activity already exists and is at * the root of the task, the system routes the intent to existing instance through a call to its * onNewIntent() method, rather than creating a new one. */ public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2; /** * Same as "singleTask", except that the system doesn't launch any other activities into the * task holding the instance. The activity is always the single and only member of its task. */ public static final int LAUNCH_MODE_SINGLE_TASK = 3; /** * The activity can only be running as the root activity of the task, the first activity that * created the task, and therefore there will only be one instance of this activity in a task; * but activity can be instantiated multiple times in different tasks. */ public static final int LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK = 4; /** The end of the range, beginning with 0, reserved for system timestamps.*/ public static final int START_TIMESTAMP_RESERVED_RANGE_SYSTEM = 20; /** The beginning of the range reserved for developer supplied timestamps.*/ public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START = START_TIMESTAMP_RESERVED_RANGE_SYSTEM + 1; /** The end of the range reserved for developer supplied timestamps.*/ public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER = 30; /** Clock monotonic timestamp of launch started. */ public static final int START_TIMESTAMP_LAUNCH = 0; /** Clock monotonic timestamp of process fork. */ public static final int START_TIMESTAMP_FORK = 1; /** Clock monotonic timestamp of Application onCreate called. */ public static final int START_TIMESTAMP_APPLICATION_ONCREATE = 2; /** Clock monotonic timestamp of bindApplication called. */ public static final int START_TIMESTAMP_BIND_APPLICATION = 3; /** Clock monotonic timestamp of first frame drawn. */ public static final int START_TIMESTAMP_FIRST_FRAME = 4; /** Clock monotonic timestamp of reportFullyDrawn called by application. */ public static final int START_TIMESTAMP_FULLY_DRAWN = 5; /** Clock monotonic timestamp of initial renderthread frame. */ public static final int START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME = 6; /** Clock monotonic timestamp of surfaceflinger composition complete. */ public static final int START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE = 7; /** * @see #getStartupState */ private @StartupState int mStartupState; /** * @see #getPid */ private int mPid; /** * @see #getRealUid */ private int mRealUid; /** * @see #getPackageUid */ private int mPackageUid; /** * @see #getDefiningUid */ private int mDefiningUid; /** * @see #getPackageName */ private String mPackageName; /** * @see #getProcessName */ private String mProcessName; /** * @see #getReason */ private @StartReason int mReason; /** * @see #getStartupTimestamps */ private ArrayMapNote: field will always be set and available.
*/ public @StartupState int getStartupState() { return mStartupState; } /** * The process id. * *Note: field will be set for any {@link #getStartupState} value.
*/ public int getPid() { return mPid; } /** * The kernel user identifier of the process, most of the time the system uses this to do access * control checks. It's typically the uid of the package where the component is running from, * except the case of isolated process, where this field identifies the kernel user identifier * that this process is actually running with, while the {@link #getPackageUid} identifies the * kernel user identifier that is assigned at the package installation time. * *Note: field will be set for any {@link #getStartupState} value.
*/ public int getRealUid() { return mRealUid; } /** * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the * package installation time. * *Note: field will be set for any {@link #getStartupState} value.
*/ public int getPackageUid() { return mPackageUid; } /** * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and * {@link #getPackageUid}, if an external service has the {@link * android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set to
* true
and was bound with the flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}
* - in this case, this field here will be the kernel user identifier of the external service
* provider.
*
* Note: field will be set for any {@link #getStartupState} value.
*/ public int getDefiningUid() { return mDefiningUid; } /** * Name of first package running in this process; * * @hide */ public String getPackageName() { return mPackageName; } /** * The actual process name it was running with. * *Note: field will be set for any {@link #getStartupState} value.
*/ public @NonNull String getProcessName() { return mProcessName; } /** * The reason code of what triggered the process's start. * *Note: field will be set for any {@link #getStartupState} value.
*/ public @StartReason int getReason() { return mReason; } /** * Various clock monotonic timestamps in nanoseconds throughout the startup process. * *Note: different timestamps will be available for different values of * {@link #getStartupState}: * * (Subsequent rows contain all timestamps of proceding states.) * * For {@link #STARTUP_STATE_STARTED}, timestamp {@link #START_TIMESTAMP_LAUNCH} will be * available. * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available. * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps * {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, {@link #START_TIMESTAMP_BIND_APPLICATION}, * and {@link #START_TIMESTAMP_FIRST_FRAME} will additionally be available. * * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is * dependant on devloper calling {@link Activity#reportFullyDrawn}. *
*/ public @NonNull MapNote: field will be set for {@link #getStartupState} value * {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}. Not guaranteed for other states.
*/ public @StartType int getStartType() { return mStartType; } /** * The intent used to launch the application. * *Note: Intent is stripped and does not include extras.
* *Note: field will be set for any {@link #getStartupState} value.
*/ @SuppressLint("IntentBuilderName") @Nullable public Intent getIntent() { return mStartIntent; } /** * An instruction on how the activity should be launched. There are five modes that work in * conjunction with activity flags in Intent objects to determine what should happen when the * activity is called upon to handle an intent. * * Modes: * {@link #LAUNCH_MODE_STANDARD} * {@link #LAUNCH_MODE_SINGLE_TOP} * {@link #LAUNCH_MODE_SINGLE_INSTANCE} * {@link #LAUNCH_MODE_SINGLE_TASK} * {@link #LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK} * *Note: field will be set for any {@link #getStartupState} value.
*/ public @LaunchMode int getLaunchMode() { return mLaunchMode; } /** * Informs whether this is the first process launch for an app since it was * {@link ApplicationInfo#FLAG_STOPPED force-stopped} for some reason. * This allows the app to know if it should re-register for any alarms, jobs and other callbacks * that were cleared when the app was force-stopped. * * @return {@code true} if this is the first process launch of the app after having been * stopped, {@code false} otherwise. */ @FlaggedApi(android.content.pm.Flags.FLAG_STAY_STOPPED) public boolean wasForceStopped() { return mWasForceStopped; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mStartupState); dest.writeInt(mPid); dest.writeInt(mRealUid); dest.writeInt(mPackageUid); dest.writeInt(mDefiningUid); dest.writeString(mPackageName); dest.writeString(mProcessName); dest.writeInt(mReason); dest.writeInt(mStartupTimestampsNs == null ? 0 : mStartupTimestampsNs.size()); if (mStartupTimestampsNs != null) { for (int i = 0; i < mStartupTimestampsNs.size(); i++) { dest.writeInt(mStartupTimestampsNs.keyAt(i)); dest.writeLong(mStartupTimestampsNs.valueAt(i)); } } dest.writeInt(mStartType); dest.writeParcelable(mStartIntent, flags); dest.writeInt(mLaunchMode); dest.writeBoolean(mWasForceStopped); } /** @hide */ public ApplicationStartInfo() {} /** @hide */ public ApplicationStartInfo(ApplicationStartInfo other) { mStartupState = other.mStartupState; mPid = other.mPid; mRealUid = other.mRealUid; mPackageUid = other.mPackageUid; mDefiningUid = other.mDefiningUid; mPackageName = other.mPackageName; mProcessName = other.mProcessName; mReason = other.mReason; mStartupTimestampsNs = other.mStartupTimestampsNs; mStartType = other.mStartType; mStartIntent = other.mStartIntent; mLaunchMode = other.mLaunchMode; mWasForceStopped = other.mWasForceStopped; } private ApplicationStartInfo(@NonNull Parcel in) { mStartupState = in.readInt(); mPid = in.readInt(); mRealUid = in.readInt(); mPackageUid = in.readInt(); mDefiningUid = in.readInt(); mPackageName = intern(in.readString()); mProcessName = intern(in.readString()); mReason = in.readInt(); int starupTimestampCount = in.readInt(); for (int i = 0; i < starupTimestampCount; i++) { int key = in.readInt(); long val = in.readLong(); addStartupTimestamp(key, val); } mStartType = in.readInt(); mStartIntent = in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class); mLaunchMode = in.readInt(); mWasForceStopped = in.readBoolean(); } private static String intern(@Nullable String source) { return source != null ? source.intern() : null; } public @NonNull static final Creator