Merge "Add ApplicationStartInfo API and objects"

This commit is contained in:
Yisroel Forta
2023-02-14 03:17:22 +00:00
committed by Android (Google) Code Review
9 changed files with 914 additions and 0 deletions

View File

@@ -4614,6 +4614,7 @@ package android.app {
method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
method @NonNull public java.util.List<android.app.ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String, @IntRange(from=0) int, @IntRange(from=0) int);
method @NonNull public java.util.List<android.app.ApplicationStartInfo> getHistoricalProcessStartReasons(@IntRange(from=0) int);
method public int getLargeMemoryClass();
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
@@ -4639,7 +4640,9 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) public void killBackgroundProcesses(String);
method @RequiresPermission(android.Manifest.permission.REORDER_TASKS) public void moveTaskToFront(int, int);
method @RequiresPermission(android.Manifest.permission.REORDER_TASKS) public void moveTaskToFront(int, int, android.os.Bundle);
method public void removeApplicationStartInfoCompleteListener();
method @Deprecated public void restartPackage(String);
method public void setApplicationStartInfoCompleteListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.ApplicationStartInfoCompleteListener);
method public void setProcessStateSummary(@Nullable byte[]);
method public static void setVrThread(int);
method public void setWatchHeapLimit(long);
@@ -4662,6 +4665,10 @@ package android.app {
method public void startActivity(android.content.Context, android.content.Intent, android.os.Bundle);
}
public static interface ActivityManager.ApplicationStartInfoCompleteListener {
method public void onApplicationStartInfoComplete(@NonNull android.app.ApplicationStartInfo);
}
public static class ActivityManager.MemoryInfo implements android.os.Parcelable {
ctor public ActivityManager.MemoryInfo();
method public int describeContents();
@@ -5221,6 +5228,52 @@ package android.app {
field public static final int REASON_USER_STOPPED = 11; // 0xb
}
public final class ApplicationStartInfo implements android.os.Parcelable {
method public int describeContents();
method public int getDefiningUid();
method @Nullable public android.content.Intent getIntent();
method public int getLaunchMode();
method public int getPackageUid();
method public int getPid();
method @NonNull public String getProcessName();
method public int getRealUid();
method public int getReason();
method public int getStartType();
method public int getStartupState();
method @NonNull public java.util.Map<java.lang.Integer,java.lang.Long> getStartupTimestamps();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationStartInfo> CREATOR;
field public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2; // 0x2
field public static final int LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK = 4; // 0x4
field public static final int LAUNCH_MODE_SINGLE_TASK = 3; // 0x3
field public static final int LAUNCH_MODE_SINGLE_TOP = 1; // 0x1
field public static final int LAUNCH_MODE_STANDARD = 0; // 0x0
field public static final int STARTUP_STATE_ERROR = 1; // 0x1
field public static final int STARTUP_STATE_FIRST_FRAME_DRAWN = 2; // 0x2
field public static final int STARTUP_STATE_STARTED = 0; // 0x0
field public static final int START_REASON_ALARM = 0; // 0x0
field public static final int START_REASON_BACKUP = 1; // 0x1
field public static final int START_REASON_BOOT_COMPLETE = 2; // 0x2
field public static final int START_REASON_BROADCAST = 3; // 0x3
field public static final int START_REASON_CONTENT_PROVIDER = 4; // 0x4
field public static final int START_REASON_JOB = 5; // 0x5
field public static final int START_REASON_LAUNCHER = 6; // 0x6
field public static final int START_REASON_OTHER = 7; // 0x7
field public static final int START_REASON_PUSH = 8; // 0x8
field public static final int START_REASON_RESUMED_ACTIVITY = 9; // 0x9
field public static final int START_REASON_SERVICE = 10; // 0xa
field public static final int START_REASON_START_ACTIVITY = 11; // 0xb
field public static final int START_TIMESTAMP_APPLICATION_ONCREATE = 2; // 0x2
field public static final int START_TIMESTAMP_BIND_APPLICATION = 3; // 0x3
field public static final int START_TIMESTAMP_FIRST_FRAME = 4; // 0x4
field public static final int START_TIMESTAMP_FULLY_DRAWN = 5; // 0x5
field public static final int START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE = 1; // 0x1
field public static final int START_TIMESTAMP_LAUNCH = 0; // 0x0
field public static final int START_TYPE_COLD = 0; // 0x0
field public static final int START_TYPE_HOT = 2; // 0x2
field public static final int START_TYPE_WARM = 1; // 0x1
}
public final class AsyncNotedAppOp implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String getAttributionTag();

View File

@@ -525,6 +525,7 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String);
method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public static int getCurrentUser();
method @NonNull @RequiresPermission(android.Manifest.permission.DUMP) public java.util.List<android.app.ApplicationStartInfo> getExternalHistoricalProcessStartReasons(@NonNull String, @IntRange(from=0) int);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String);
method @NonNull public java.util.Collection<java.util.Locale> getSupportedLocales();
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);

View File

@@ -3675,6 +3675,123 @@ public class ActivityManager {
}
}
/**
* Return a list of {@link ApplicationStartInfo} records containing the information about the
* most recent app startups.
*
* <p class="note"> Note: System stores this historical information in a ring buffer and only
* the most recent records will be returned. </p>
*
* @param maxNum The maximum number of results to be returned; a value of 0
* means to ignore this parameter and return all matching records. If fewer
* records exist, all existing records will be returned.
*
* @return a list of {@link ApplicationStartInfo} records matching the criteria, sorted in
* the order from most recent to least recent.
*/
@NonNull
public List<ApplicationStartInfo> getHistoricalProcessStartReasons(
@IntRange(from = 0) int maxNum) {
try {
ParceledListSlice<ApplicationStartInfo> startInfos = getService()
.getHistoricalProcessStartReasons(null, maxNum, mContext.getUserId());
return startInfos == null ? Collections.emptyList() : startInfos.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return a list of {@link ApplicationStartInfo} records containing the information about the
* most recent app startups.
*
* <p class="note"> Note: System stores this historical information in a ring buffer and only
* the most recent records will be returned. </p>
*
* @param packageName Package name for which app startups to receive.
* @param maxNum The maximum number of results to be returned; a value of 0
* means to ignore this parameter and return all matching records. If fewer
* records exist, all existing records will be returned.
*
* @return a list of {@link ApplicationStartInfo} records matching the criteria, sorted in
* the order from most recent to least recent.
*
* @hide
*/
@NonNull
@SystemApi
@RequiresPermission(Manifest.permission.DUMP)
public List<ApplicationStartInfo> getExternalHistoricalProcessStartReasons(
@NonNull String packageName, @IntRange(from = 0) int maxNum) {
try {
ParceledListSlice<ApplicationStartInfo> startInfos = getService()
.getHistoricalProcessStartReasons(packageName, maxNum, mContext.getUserId());
return startInfos == null ? Collections.emptyList() : startInfos.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Callback to receive {@link ApplicationStartInfo} object once recording of startup related
* metrics is complete.
* Use with {@link #setApplicationStartInfoCompleteListener}.
*/
public interface ApplicationStartInfoCompleteListener {
/** {@link ApplicationStartInfo} is complete, no more info will be added. */
void onApplicationStartInfoComplete(@NonNull ApplicationStartInfo applicationStartInfo);
}
/**
* Sets a callback to be notified when the {@link ApplicationStartInfo} records of this startup
* are complete.
*
* <p class="note"> Note: callback will not wait for {@link Activity#reportFullyDrawn} to occur.
* Timestamp for fully drawn may be added after callback occurs. Set callback after invoking
* {@link Activity#reportFullyDrawn} if timestamp for fully drawn is required.</p>
*
* <p class="note"> Note: if start records have already been retrieved, the callback will be
* invoked immediately on the specified executor with the previously resolved AppStartInfo.</p>
*
* <p class="note"> Note: callback is asynchronous and should be made from a background thread.
* </p>
*
* @param executor The executor on which the listener should be called.
* @param listener Callback to be called when collection of {@link ApplicationStartInfo} is
* complete. Will replace existing listener if one is already attached.
*
* @throws IllegalArgumentException if executor or listener are null.
*/
public void setApplicationStartInfoCompleteListener(@NonNull final Executor executor,
@NonNull final ApplicationStartInfoCompleteListener listener) {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(listener, "listener cannot be null");
IApplicationStartInfoCompleteListener callback =
new IApplicationStartInfoCompleteListener.Stub() {
@Override
public void onApplicationStartInfoComplete(ApplicationStartInfo applicationStartInfo) {
executor.execute(() ->
listener.onApplicationStartInfoComplete(applicationStartInfo));
}
};
try {
getService().setApplicationStartInfoCompleteListener(callback, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Removes the callback set by {@link #setApplicationStartInfoCompleteListener} if there is one.
*/
public void removeApplicationStartInfoCompleteListener() {
try {
getService().removeApplicationStartInfoCompleteListener(mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return a list of {@link ApplicationExitInfo} records containing the reasons for the most
* recent app deaths.

View File

@@ -0,0 +1,19 @@
/*
* 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;
parcelable ApplicationStartInfo;

View File

@@ -0,0 +1,598 @@
/*
* 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.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.Map;
/** Provide information related to a processes startup. */
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 not for any of the listed reasons. */
public static final int START_REASON_OTHER = 7;
/** Process started due to push message. */
public static final int START_REASON_PUSH = 8;
/** Process started to resume activity. */
public static final int START_REASON_RESUMED_ACTIVITY = 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;
/** Process started from scratch. */
public static final int START_TYPE_COLD = 0;
/** Process retained minimally SavedInstanceState. */
public static final int START_TYPE_WARM = 1;
/** Process brought back to foreground. */
public static final int START_TYPE_HOT = 2;
/**
* 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;
/** Clock monotonic timestamp of launch started. */
public static final int START_TIMESTAMP_LAUNCH = 0;
/** Clock monotonic timestamp of finish java classloading. */
public static final int START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE = 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;
/**
* @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 #getProcessName
*/
private String mProcessName;
/**
* @see #getReason
*/
private @StartReason int mReason;
/**
* @see #getStartupTimestamps
*/
private Map<@StartupTimestamp Integer, Long> mStartupTimestampsNs;
/**
* @see #getStartType
*/
private @StartType int mStartType;
/**
* @see #getStartIntent
*/
private Intent mStartIntent;
/**
* @see #getLaunchMode
*/
private @LaunchMode int mLaunchMode;
/**
* @hide *
*/
@IntDef(
prefix = {"STARTUP_STATE_"},
value = {
STARTUP_STATE_STARTED,
STARTUP_STATE_ERROR,
STARTUP_STATE_FIRST_FRAME_DRAWN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StartupState {}
/**
* @hide *
*/
@IntDef(
prefix = {"START_REASON_"},
value = {
START_REASON_ALARM,
START_REASON_BACKUP,
START_REASON_BOOT_COMPLETE,
START_REASON_BROADCAST,
START_REASON_CONTENT_PROVIDER,
START_REASON_JOB,
START_REASON_LAUNCHER,
START_REASON_OTHER,
START_REASON_PUSH,
START_REASON_RESUMED_ACTIVITY,
START_REASON_SERVICE,
START_REASON_START_ACTIVITY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StartReason {}
/**
* @hide *
*/
@IntDef(
prefix = {"START_TYPE_"},
value = {
START_TYPE_COLD,
START_TYPE_WARM,
START_TYPE_HOT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StartType {}
/**
* @hide *
*/
@IntDef(
prefix = {"LAUNCH_MODE_"},
value = {
LAUNCH_MODE_STANDARD,
LAUNCH_MODE_SINGLE_TOP,
LAUNCH_MODE_SINGLE_INSTANCE,
LAUNCH_MODE_SINGLE_TASK,
LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LaunchMode {}
/**
* @hide *
*/
@IntDef(
prefix = {"START_TIMESTAMP_"},
value = {
START_TIMESTAMP_LAUNCH,
START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE,
START_TIMESTAMP_APPLICATION_ONCREATE,
START_TIMESTAMP_BIND_APPLICATION,
START_TIMESTAMP_FULLY_DRAWN,
})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface StartupTimestamp {}
/**
* @see #getStartupState
* @hide
*/
public void setStartupState(final @StartupState int startupState) {
mStartupState = startupState;
}
/**
* @see #getPid
* @hide
*/
public void setPid(final int pid) {
mPid = pid;
}
/**
* @see #getRealUid
* @hide
*/
public void setRealUid(final int uid) {
mRealUid = uid;
}
/**
* @see #getPackageUid
* @hide
*/
public void setPackageUid(final int uid) {
mPackageUid = uid;
}
/**
* @see #getDefiningUid
* @hide
*/
public void setDefiningUid(final int uid) {
mDefiningUid = uid;
}
/**
* @see #getProcessName
* @hide
*/
public void setProcessName(final String processName) {
mProcessName = intern(processName);
}
/**
* @see #getReason
* @hide
*/
public void setReason(@StartReason int reason) {
mReason = reason;
}
/**
* @see #getStartupTimestamps
* @hide
*/
public void addStartupTimestamp(@StartupTimestamp int key, long timestampNs) {
if (mStartupTimestampsNs == null) {
mStartupTimestampsNs = new HashMap<@StartupTimestamp Integer, Long>();
}
mStartupTimestampsNs.put(key, timestampNs);
}
/**
* @see #getStartType
* @hide
*/
public void setStartType(@StartType int startType) {
mStartType = startType;
}
/**
* @see #getStartIntent
* @hide
*/
public void setIntent(Intent startIntent) {
mStartIntent = startIntent;
}
/**
* @see #getLaunchMode
* @hide
*/
public void setLaunchMode(@LaunchMode int launchMode) {
mLaunchMode = launchMode;
}
/**
* Current state of startup.
*
* Can be used to determine whether the object will have additional fields added as it may be
* queried before all data is collected.
*
* <p class="note"> Note: field will always be set and available.</p>
*/
public @StartupState int getStartupState() {
return mStartupState;
}
/**
* The process id.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
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.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
public int getRealUid() {
return mRealUid;
}
/**
* Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the
* package installation time.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
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 <code>
* true</code> 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.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
public int getDefiningUid() {
return mDefiningUid;
}
/**
* The actual process name it was running with.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
public @NonNull String getProcessName() {
return mProcessName;
}
/**
* The reason code of what triggered the process's start.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
public @StartReason int getReason() {
return mReason;
}
/**
* Various clock monotonic timestamps in nanoseconds throughout the startup process.
*
* <p class="note"> 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_JAVA_CLASSLOADING_COMPLETE}, {@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}.
* </p>
*/
public @NonNull Map<@StartupTimestamp Integer, Long> getStartupTimestamps() {
if (mStartupTimestampsNs == null) {
mStartupTimestampsNs = new HashMap<@StartupTimestamp Integer, Long>();
}
return mStartupTimestampsNs;
}
/**
* The state of the app at startup.
*
* <p class="note"> Note: field will be set for {@link #getStartupState} value
* {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}. Not guaranteed for other states.</p>
*/
public @StartType int getStartType() {
return mStartType;
}
/**
* The intent used to launch the application.
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
@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}
*
* <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p>
*/
public @LaunchMode int getLaunchMode() {
return mLaunchMode;
}
@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(mProcessName);
dest.writeInt(mReason);
dest.writeInt(mStartupTimestampsNs.size());
for (@StartupTimestamp int key : mStartupTimestampsNs.keySet()) {
dest.writeInt(key);
dest.writeLong(mStartupTimestampsNs.get(key));
}
dest.writeInt(mStartType);
dest.writeParcelable(mStartIntent, flags);
dest.writeInt(mLaunchMode);
}
/** @hide */
public ApplicationStartInfo() {}
/** @hide */
public ApplicationStartInfo(ApplicationStartInfo other) {
mStartupState = other.mStartupState;
mPid = other.mPid;
mRealUid = other.mRealUid;
mPackageUid = other.mPackageUid;
mDefiningUid = other.mDefiningUid;
mProcessName = other.mProcessName;
mReason = other.mReason;
mStartupTimestampsNs = other.mStartupTimestampsNs;
mStartType = other.mStartType;
mStartIntent = other.mStartIntent;
mLaunchMode = other.mLaunchMode;
}
private ApplicationStartInfo(@NonNull Parcel in) {
mStartupState = in.readInt();
mPid = in.readInt();
mRealUid = in.readInt();
mPackageUid = in.readInt();
mDefiningUid = in.readInt();
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();
}
private static String intern(@Nullable String source) {
return source != null ? source.intern() : null;
}
public @NonNull static final Creator<ApplicationStartInfo> CREATOR =
new Creator<ApplicationStartInfo>() {
@Override
public ApplicationStartInfo createFromParcel(Parcel in) {
return new ApplicationStartInfo(in);
}
@Override
public ApplicationStartInfo[] newArray(int size) {
return new ApplicationStartInfo[size];
}
};
}

View File

@@ -19,10 +19,12 @@ package android.app;
import android.app.ActivityManager;
import android.app.ActivityManager.PendingIntentInfo;
import android.app.ActivityTaskManager;
import android.app.ApplicationStartInfo;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.app.ContentProviderHolder;
import android.app.GrantedUriPermission;
import android.app.IApplicationStartInfoCompleteListener;
import android.app.IApplicationThread;
import android.app.IActivityController;
import android.app.IAppTask;
@@ -633,6 +635,45 @@ interface IActivityManager {
*/
void appNotResponding(String reason);
/**
* Return a list of {@link ApplicationStartInfo} records.
*
* <p class="note"> Note: System stores historical information in a ring buffer, older
* records would be overwritten by newer records. </p>
*
* @param packageName Optional, an empty value means match all packages belonging to the
* caller's UID. If this package belongs to another UID, you must hold
* {@link android.Manifest.permission#DUMP} in order to retrieve it.
* @param maxNum Optional, the maximum number of results should be returned; A value of 0
* means to ignore this parameter and return all matching records
* @param userId The userId in the multi-user environment.
*
* @return a list of {@link ApplicationStartInfo} records with the matching criteria, sorted in
* the order from most recent to least recent.
*/
ParceledListSlice<ApplicationStartInfo> getHistoricalProcessStartReasons(String packageName,
int maxNum, int userId);
/**
* Sets a callback for {@link ApplicationStartInfo} upon completion of collecting startup data.
*
* <p class="note"> Note: completion of startup is no guaranteed and as such this callback may not occur.</p>
*
* @param listener A listener to for the callback upon completion of startup data collection.
* @param userId The userId in the multi-user environment.
*/
void setApplicationStartInfoCompleteListener(IApplicationStartInfoCompleteListener listener,
int userId);
/**
* Removes callback for {@link ApplicationStartInfo} upon completion of collecting startup data.
*
* @param userId The userId in the multi-user environment.
*/
void removeApplicationStartInfoCompleteListener(int userId);
/**
* Return a list of {@link ApplicationExitInfo} records.
*

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2021 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.app.ApplicationStartInfo;
/**
* Notify the client when compilation of app start info is complete.
* Will not be called in case of an error that disrupts startup.
* @param applicationStartInfo the completed ApplicationStartInfo object.
*
* @hide
*/
interface IApplicationStartInfoCompleteListener {
void onApplicationStartInfoComplete(in ApplicationStartInfo applicationStartInfo);
}

View File

@@ -260,6 +260,10 @@ final class ActivityManagerConstants extends ContentObserver {
*/
private static final String KEY_LOW_SWAP_THRESHOLD_PERCENT = "low_swap_threshold_percent";
/** Default value for mFlagApplicationStartInfoEnabled. Defaults to false. */
private static final String KEY_DEFAULT_APPLICATION_START_INFO_ENABLED =
"enable_app_start_info";
/**
* Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
* Settings.Global. This allows it to be set experimentally unless it has been
@@ -550,6 +554,9 @@ final class ActivityManagerConstants extends ContentObserver {
// Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
volatile boolean mFlagActivityStartsLoggingEnabled;
// Indicates whether ApplicationStartInfo is enabled.
volatile boolean mFlagApplicationStartInfoEnabled;
// Indicates whether the background activity starts is enabled.
// Controlled by Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED.
// If not set explicitly the default is controlled by DeviceConfig.
@@ -996,6 +1003,9 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_MAX_CACHED_PROCESSES:
updateMaxCachedProcesses();
break;
case KEY_DEFAULT_APPLICATION_START_INFO_ENABLED:
updateApplicationStartInfoEnabled();
break;
case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
updateBackgroundActivityStarts();
break;
@@ -1390,6 +1400,14 @@ final class ActivityManagerConstants extends ContentObserver {
Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 1) == 1;
}
private void updateApplicationStartInfoEnabled() {
mFlagApplicationStartInfoEnabled =
DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_DEFAULT_APPLICATION_START_INFO_ENABLED,
/*defaultValue*/ false);
}
private void updateBackgroundActivityStarts() {
mFlagBackgroundActivityStartsEnabled = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1970,6 +1988,10 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println(mFgToBgFgsGraceDuration);
pw.print(" "); pw.print(KEY_FGS_START_FOREGROUND_TIMEOUT); pw.print("=");
pw.println(mFgsStartForegroundTimeoutMs);
pw.print(" ");
pw.print(KEY_DEFAULT_APPLICATION_START_INFO_ENABLED);
pw.print("=");
pw.println(mFlagApplicationStartInfoEnabled);
pw.print(" "); pw.print(KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED); pw.print("=");
pw.println(mFlagBackgroundActivityStartsEnabled);
pw.print(" "); pw.print(KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED);

View File

@@ -184,6 +184,7 @@ import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.app.ApplicationStartInfo;
import android.app.ApplicationThreadConstants;
import android.app.BackgroundStartPrivileges;
import android.app.BroadcastOptions;
@@ -192,6 +193,7 @@ import android.app.ContentProviderHolder;
import android.app.ForegroundServiceDelegationOptions;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IApplicationStartInfoCompleteListener;
import android.app.IApplicationThread;
import android.app.IForegroundServiceObserver;
import android.app.IInstrumentationWatcher;
@@ -9451,6 +9453,37 @@ public class ActivityManagerService extends IActivityManager.Stub
return retList;
}
@Override
public ParceledListSlice<ApplicationStartInfo> getHistoricalProcessStartReasons(
String packageName, int maxNum, int userId) {
if (!mConstants.mFlagApplicationStartInfoEnabled) {
return new ParceledListSlice<ApplicationStartInfo>(
new ArrayList<ApplicationStartInfo>());
}
enforceNotIsolatedCaller("getHistoricalProcessStartReasons");
final ArrayList<ApplicationStartInfo> results = new ArrayList<ApplicationStartInfo>();
return new ParceledListSlice<ApplicationStartInfo>(results);
}
@Override
public void setApplicationStartInfoCompleteListener(
IApplicationStartInfoCompleteListener listener, int userId) {
if (!mConstants.mFlagApplicationStartInfoEnabled) {
return;
}
enforceNotIsolatedCaller("setApplicationStartInfoCompleteListener");
}
@Override
public void removeApplicationStartInfoCompleteListener(int userId) {
if (!mConstants.mFlagApplicationStartInfoEnabled) {
return;
}
enforceNotIsolatedCaller("removeApplicationStartInfoCompleteListener");
}
@Override
public ParceledListSlice<ApplicationExitInfo> getHistoricalProcessExitReasons(
String packageName, int pid, int maxNum, int userId) {