/* * 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.CurrentTimeMillisLong; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningAppProcessInfo.Importance; import android.icu.text.SimpleDateFormat; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; import android.util.DebugUtils; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; import android.util.proto.WireTypeMismatchException; import com.android.internal.util.ArrayUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; import java.util.Objects; import java.util.zip.GZIPInputStream; /** * Describes the information of an application process's death. * *
* Application process could die for many reasons, for example {@link #REASON_LOW_MEMORY} * when it was killed by the system because it was running low on memory. Reason * of the death can be retrieved via {@link #getReason}. Besides the reason, there are a few other * auxiliary APIs like {@link #getStatus} and {@link #getImportance} to help the caller with * additional diagnostic information. *
* */ public final class ApplicationExitInfo implements Parcelable { /** * Application process died due to unknown reason. */ public static final int REASON_UNKNOWN = 0; /** * Application process exit normally by itself, for example, * via {@link java.lang.System#exit}; {@link #getStatus} will specify the exit code. * *Applications should normally not do this, as the system has a better knowledge * in terms of process management.
*/ public static final int REASON_EXIT_SELF = 1; /** * Application process died due to the result of an OS signal; for example, * {@link android.system.OsConstants#SIGKILL}; {@link #getStatus} will specify the signal * number. */ public static final int REASON_SIGNALED = 2; /** * Application process was killed by the system low memory killer, meaning the system was * under memory pressure at the time of kill. * ** Not all devices support reporting {@link #REASON_LOW_MEMORY}; on a device with no such * support, when a process is killed due to memory pressure, the {@link #getReason} will return * {@link #REASON_SIGNALED} and {@link #getStatus} will return * the value {@link android.system.OsConstants#SIGKILL}. * * Application should use {@link android.app.ActivityManager#isLowMemoryKillReportSupported() * ActivityManager.isLowMemoryKillReportSupported()} to check * if the device supports reporting {@link #REASON_LOW_MEMORY} or not. *
*/ public static final int REASON_LOW_MEMORY = 3; /** * Application process died because of an unhandled exception in Java code. */ public static final int REASON_CRASH = 4; /** * Application process died because of a native code crash. */ public static final int REASON_CRASH_NATIVE = 5; /** * Application process was killed due to being unresponsive (ANR). */ public static final int REASON_ANR = 6; /** * Application process was killed because of initialization failure, * for example, it took too long to attach to the system during the start, * or there was an error during initialization. */ public static final int REASON_INITIALIZATION_FAILURE = 7; /** * Application process was killed due to a runtime permission change. */ public static final int REASON_PERMISSION_CHANGE = 8; /** * Application process was killed by the system due to excessive resource usage. */ public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9; /** * Application process was killed because of the user request, for example, * user clicked the "Force stop" button of the application in the Settings, * or removed the application away from Recents. ** Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, one of the uses of this * reason was to indicate that an app was killed due to it being updated or any of its component * states have changed without {@link android.content.pm.PackageManager#DONT_KILL_APP} */ public static final int REASON_USER_REQUESTED = 10; /** * Application process was killed, because the user it is running as on devices * with mutlple users, was stopped. */ public static final int REASON_USER_STOPPED = 11; /** * Application process was killed because its dependency was going away, for example, * a stable content provider connection's client will be killed if the provider is killed. */ public static final int REASON_DEPENDENCY_DIED = 12; /** * Application process was killed by the system for various other reasons which are * not by problems in apps and not actionable by apps, for example, the system just * finished updates; {@link #getDescription} will specify the cause given by the system. */ public static final int REASON_OTHER = 13; /** * Application process was killed by App Freezer, for example, because it receives * sync binder transactions while being frozen. */ public static final int REASON_FREEZER = 14; /** * Application process was killed because the app was disabled, or any of its * component states have changed without {@link android.content.pm.PackageManager#DONT_KILL_APP} *
* Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, * {@link #REASON_USER_REQUESTED} was used to indicate that an app was updated. */ public static final int REASON_PACKAGE_STATE_CHANGE = 15; /** * Application process was killed because it was updated. *
* Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
* {@link #REASON_USER_REQUESTED} was used to indicate that an app was updated.
*/
public static final int REASON_PACKAGE_UPDATED = 16;
/**
* Application process kills subreason is unknown.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_UNKNOWN = 0;
/**
* Application process was killed because user quit it on the "wait for debugger" dialog;
* this would be set when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_WAIT_FOR_DEBUGGER = 1;
/**
* Application process was killed by the activity manager because there were too many cached
* processes; this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_TOO_MANY_CACHED = 2;
/**
* Application process was killed by the activity manager because there were too many empty
* processes; this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_TOO_MANY_EMPTY = 3;
/**
* Application process was killed by the activity manager because there were too many cached
* processes and this process had been in empty state for a long time;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_TRIM_EMPTY = 4;
/**
* Application process was killed by the activity manager because system was on memory pressure
* and this process took large amount of cached memory;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_LARGE_CACHED = 5;
/**
* Application process was killed by the activity manager because the system was on low memory
* pressure for a significant amount of time since last idle;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_MEMORY_PRESSURE = 6;
/**
* Application process was killed by the activity manager due to excessive CPU usage;
* this would be set only when the reason is {@link #REASON_EXCESSIVE_RESOURCE_USAGE}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_EXCESSIVE_CPU = 7;
/**
* System update has done (so the system update process should be killed);
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_SYSTEM_UPDATE_DONE = 8;
/**
* Kill all foreground services, for now it only occurs when enabling the quiet
* mode for the managed profile;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_KILL_ALL_FG = 9;
/**
* All background processes except certain ones were killed, for now it only occurs
* when the density of the default display is changed;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_KILL_ALL_BG_EXCEPT = 10;
/**
* The process associated with the UID was explicitly killed, for example,
* it could be because of platform compatibility overrides;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_KILL_UID = 11;
/**
* The process was explicitly killed with its PID, typically because of
* the low memory for surfaces;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_KILL_PID = 12;
/**
* The start of the process was invalid;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_INVALID_START = 13;
/**
* The process was killed because it's in an invalid state, typically
* it's triggered from SHELL;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_INVALID_STATE = 14;
/**
* The process was killed when it's imperceptible to user, because it was
* in a bad state;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_IMPERCEPTIBLE = 15;
/**
* The process was killed because it's being moved out from LRU list;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_REMOVE_LRU = 16;
/**
* The process was killed because it's isolated and was in a cached state;
* this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_ISOLATED_NOT_NEEDED = 17;
/**
* The process was killed because it's in forced-app-standby state, and it's cached and
* its uid state is idle; this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_CACHED_IDLE_FORCED_APP_STANDBY = 18;
/**
* The process was killed because it fails to freeze/unfreeze binder
* or query binder frozen info while being frozen.
* this would be set only when the reason is {@link #REASON_FREEZER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_FREEZER_BINDER_IOCTL = 19;
/**
* The process was killed because it receives sync binder transactions
* while being frozen.
* this would be set only when the reason is {@link #REASON_FREEZER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_FREEZER_BINDER_TRANSACTION = 20;
/**
* The process was killed because of force-stop, it could be due to that
* the user clicked the "Force stop" button of the application in the Settings;
* this would be set only when the reason is {@link #REASON_USER_REQUESTED}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_FORCE_STOP = 21;
/**
* The process was killed because the user removed the application away from Recents;
* this would be set only when the reason is {@link #REASON_USER_REQUESTED}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_REMOVE_TASK = 22;
/**
* The process was killed because the user stopped the application from the task manager;
* this would be set only when the reason is {@link #REASON_USER_REQUESTED}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_STOP_APP = 23;
/**
* The process was killed because the user stopped the application from developer options,
* or via the adb shell commmand interface; this would be set only when the reason is
* {@link #REASON_USER_REQUESTED}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_KILL_BACKGROUND = 24;
/**
* The process was killed because of package update; this would be set only when the reason is
* {@link #REASON_USER_REQUESTED}.
*
* For internal use only.
*
* @deprecated starting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
* an app being killed due to a package update will have the reason
* {@link #REASON_PACKAGE_UPDATED}
*
* @hide
*/
public static final int SUBREASON_PACKAGE_UPDATE = 25;
/**
* The process was killed because of undelivered broadcasts; this would be set only when the
* reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_UNDELIVERED_BROADCAST = 26;
/**
* The process was killed because its associated SDK sandbox process (where it had loaded SDKs)
* had died; this would be set only when the reason is {@link #REASON_DEPENDENCY_DIED}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_SDK_SANDBOX_DIED = 27;
/**
* The process was killed because it was an SDK sandbox process that was either not usable or
* was no longer being used; this would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_SDK_SANDBOX_NOT_NEEDED = 28;
/**
* The process was killed because the binder proxy limit for system server was exceeded.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_EXCESSIVE_BINDER_OBJECTS = 29;
/**
* The process was killed by the [kernel] Out-of-memory (OOM) killer; this
* would be set only when the reason is {@link #REASON_LOW_MEMORY}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_OOM_KILL = 30;
/**
* The process was killed because its async kernel binder buffer is running out
* while being frozen.
* this would be set only when the reason is {@link #REASON_FREEZER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_FREEZER_BINDER_ASYNC_FULL = 31;
/**
* The process was killed because it was sending too many broadcasts while it is in the
* Cached state. This would be set only when the reason is {@link #REASON_OTHER}.
*
* For internal use only.
* @hide
*/
public static final int SUBREASON_EXCESSIVE_OUTGOING_BROADCASTS_WHILE_CACHED = 32;
// If there is any OEM code which involves additional app kill reasons, it should
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
/**
* @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 @Reason int mReason;
/**
* @see #getStatus
*/
private int mStatus;
/**
* @see #getImportance
*/
private @Importance int mImportance;
/**
* @see #getPss
*/
private long mPss;
/**
* @see #getRss
*/
private long mRss;
/**
* @see #getTimestamp
*/
private @CurrentTimeMillisLong long mTimestamp;
/**
* @see #getDescription
*/
private @Nullable String mDescription;
/**
* @see #getSubReason
*/
private @SubReason int mSubReason;
/**
* @see #getConnectionGroup
*/
private int mConnectionGroup;
/**
* @see #getPackageName
*/
private String mPackageName;
/**
* @see #getPackageList
*/
private String[] mPackageList;
/**
* @see #getProcessStateSummary
*/
private byte[] mState;
/**
* The file to the trace file in the storage;
*
* for system internal use only, will not retain across processes.
*
* @see #getTraceInputStream
*/
private File mTraceFile;
/**
* The Binder interface to retrieve the file descriptor to
* the trace file from the system.
*/
private IAppTraceRetriever mAppTraceRetriever;
/**
* ParcelFileDescriptor pointing to a native tombstone.
*
* @see #getTraceInputStream
*/
private IParcelFileDescriptorRetriever mNativeTombstoneRetriever;
/**
* Whether or not we've logged this into the statsd.
*
* for system internal use only, will not retain across processes.
*/
private boolean mLoggedInStatsd;
/**
* Whether or not this process hosts one or more foreground services.
*
* for system internal use only, will not retain across processes.
*/
private boolean mHasForegroundServices;
/** @hide */
@IntDef(prefix = { "REASON_" }, value = {
REASON_UNKNOWN,
REASON_EXIT_SELF,
REASON_SIGNALED,
REASON_LOW_MEMORY,
REASON_CRASH,
REASON_CRASH_NATIVE,
REASON_ANR,
REASON_INITIALIZATION_FAILURE,
REASON_PERMISSION_CHANGE,
REASON_EXCESSIVE_RESOURCE_USAGE,
REASON_USER_REQUESTED,
REASON_USER_STOPPED,
REASON_DEPENDENCY_DIED,
REASON_OTHER,
REASON_FREEZER,
REASON_PACKAGE_STATE_CHANGE,
REASON_PACKAGE_UPDATED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Reason {}
/** @hide */
@IntDef(prefix = { "SUBREASON_" }, value = {
SUBREASON_UNKNOWN,
SUBREASON_WAIT_FOR_DEBUGGER,
SUBREASON_TOO_MANY_CACHED,
SUBREASON_TOO_MANY_EMPTY,
SUBREASON_TRIM_EMPTY,
SUBREASON_LARGE_CACHED,
SUBREASON_MEMORY_PRESSURE,
SUBREASON_EXCESSIVE_CPU,
SUBREASON_SYSTEM_UPDATE_DONE,
SUBREASON_KILL_ALL_FG,
SUBREASON_KILL_ALL_BG_EXCEPT,
SUBREASON_KILL_UID,
SUBREASON_KILL_PID,
SUBREASON_INVALID_START,
SUBREASON_INVALID_STATE,
SUBREASON_IMPERCEPTIBLE,
SUBREASON_REMOVE_LRU,
SUBREASON_ISOLATED_NOT_NEEDED,
SUBREASON_FREEZER_BINDER_IOCTL,
SUBREASON_FREEZER_BINDER_TRANSACTION,
SUBREASON_FORCE_STOP,
SUBREASON_REMOVE_TASK,
SUBREASON_STOP_APP,
SUBREASON_KILL_BACKGROUND,
SUBREASON_PACKAGE_UPDATE,
SUBREASON_UNDELIVERED_BROADCAST,
SUBREASON_EXCESSIVE_BINDER_OBJECTS,
SUBREASON_OOM_KILL,
SUBREASON_FREEZER_BINDER_ASYNC_FULL,
SUBREASON_EXCESSIVE_OUTGOING_BROADCASTS_WHILE_CACHED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SubReason {}
/**
* The process id of the process that died.
*/
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.
*/
public int getRealUid() {
return mRealUid;
}
/**
* Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the
* package installation time.
*/
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.
*/
public int getDefiningUid() {
return mDefiningUid;
}
/**
* The actual process name it was running with.
*/
public @NonNull String getProcessName() {
return mProcessName;
}
/**
* The reason code of the process's death.
*/
public @Reason int getReason() {
return mReason;
}
/**
* The exit status argument of exit() if the application calls it, or the signal
* number if the application is signaled.
*/
public int getStatus() {
return mStatus;
}
/**
* The importance of the process that it used to have before the death.
*/
public @Importance int getImportance() {
return mImportance;
}
/**
* Last proportional set size of the memory that the process had used in kB.
*
*
Note: This is the value from last sampling on the process, * it's NOT the exact memory information prior to its death; and it'll be zero * if the process died before system had a chance to take the sample.
*/ public long getPss() { return mPss; } /** * Last resident set size of the memory that the process had used in kB. * *Note: This is the value from last sampling on the process, * it's NOT the exact memory information prior to its death; and it'll be zero * if the process died before system had a chance to take the sample.
*/ public long getRss() { return mRss; } /** * The timestamp of the process's death, in milliseconds since the epoch, * as returned by {@link java.lang.System#currentTimeMillis() System.currentTimeMillis()}. */ public @CurrentTimeMillisLong long getTimestamp() { return mTimestamp; } /** * The human readable description of the process's death, given by the system; could be null. * *Note: only intended to be human-readable and the system provides no * guarantees that the format is stable across devices or Android releases.
*/ public @Nullable String getDescription() { final StringBuilder sb = new StringBuilder(); if (mSubReason != SUBREASON_UNKNOWN) { sb.append("["); sb.append(subreasonToString(mSubReason)); sb.append("]"); } if (!TextUtils.isEmpty(mDescription)) { if (sb.length() > 0) { sb.append(" "); } sb.append(mDescription); } return sb.toString(); } /** * Return the user id of the record on a multi-user system. */ public @NonNull UserHandle getUserHandle() { return UserHandle.of(UserHandle.getUserId(mRealUid)); } /** * Return the state data set by calling * {@link android.app.ActivityManager#setProcessStateSummary(byte[]) * ActivityManager.setProcessStateSummary(byte[])} from the process before its death. * * @return The process-customized data * @see ActivityManager#setProcessStateSummary(byte[]) */ public @Nullable byte[] getProcessStateSummary() { return mState; } /** * Return the InputStream to the traces that was taken by the system * prior to the death of the process; typically it'll be available when * the reason is {@link #REASON_ANR}, though if the process gets an ANR * but recovers, and dies for another reason later, this trace will be included * in the record of {@link ApplicationExitInfo} still. Beginning with API 31, * tombstone traces will be returned for * {@link #REASON_CRASH_NATIVE}, with an InputStream containing a protobuf with * this schema. * Note that because these traces are kept in a separate global circular buffer, crashes may be * overwritten by newer crashes (including from other applications), so this may still return * null. * * @return The input stream to the traces that was taken by the system * prior to the death of the process. */ public @Nullable InputStream getTraceInputStream() throws IOException { if (mAppTraceRetriever == null && mNativeTombstoneRetriever == null) { return null; } try { if (mNativeTombstoneRetriever != null) { final ParcelFileDescriptor pfd = mNativeTombstoneRetriever.getPfd(); if (pfd == null) { return null; } return new ParcelFileDescriptor.AutoCloseInputStream(pfd); } else { final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor( mPackageName, mPackageUid, mPid); if (fd == null) { return null; } return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd)); } } catch (RemoteException e) { return null; } } /** * Similar to {@link #getTraceInputStream} but return the File object. * * For internal use only. * * @hide */ public @Nullable File getTraceFile() { return mTraceFile; } /** * A subtype reason in conjunction with {@link #mReason}. * * For internal use only. * * @hide */ public @SubReason int getSubReason() { return mSubReason; } /** * The connection group this process belongs to, if there is any. * @see android.content.Context#updateServiceGroup * * For internal use only. * * @hide */ public int getConnectionGroup() { return mConnectionGroup; } /** * Name of first package running in this process; * * @hide */ public String getPackageName() { return mPackageName; } /** * List of packages running in this process; * * For system internal use only, will not retain across processes. * * @hide */ public String[] getPackageList() { return mPackageList; } /** * @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(final @Reason int reason) { mReason = reason; } /** * @see #getStatus * * @hide */ public void setStatus(final int status) { mStatus = status; } /** * @see #getImportance * * @hide */ public void setImportance(final @Importance int importance) { mImportance = importance; } /** * @see #getPss * * @hide */ public void setPss(final long pss) { mPss = pss; } /** * @see #getRss * * @hide */ public void setRss(final long rss) { mRss = rss; } /** * @see #getTimestamp * * @hide */ public void setTimestamp(final @CurrentTimeMillisLong long timestamp) { mTimestamp = timestamp; } /** * @see #getDescription * * @hide */ public void setDescription(final String description) { mDescription = intern(description); } /** * @see #getSubReason * * @hide */ public void setSubReason(final @SubReason int subReason) { mSubReason = subReason; } /** * @see #getConnectionGroup * * @hide */ public void setConnectionGroup(final int connectionGroup) { mConnectionGroup = connectionGroup; } /** * @see #getPackageName * * @hide */ public void setPackageName(final String packageName) { mPackageName = intern(packageName); } /** * @see #getPackageList * * @hide */ public void setPackageList(final String[] packageList) { mPackageList = packageList; } /** * @see #getProcessStateSummary * * @hide */ public void setProcessStateSummary(final byte[] state) { mState = state; } /** * @see #getTraceFile * * @hide */ public void setTraceFile(final File traceFile) { mTraceFile = traceFile; } /** * @see #mAppTraceRetriever * * @hide */ public void setAppTraceRetriever(final IAppTraceRetriever retriever) { mAppTraceRetriever = retriever; } /** * @see mNativeTombstoneRetriever * * @hide */ public void setNativeTombstoneRetriever(final IParcelFileDescriptorRetriever retriever) { mNativeTombstoneRetriever = retriever; } /** * @see #mLoggedInStatsd * * @hide */ public boolean isLoggedInStatsd() { return mLoggedInStatsd; } /** * @see #mLoggedInStatsd * * @hide */ public void setLoggedInStatsd(boolean loggedInStatsd) { mLoggedInStatsd = loggedInStatsd; } /** * @see #mHasForegroundServices * * @hide */ public boolean hasForegroundServices() { return mHasForegroundServices; } /** * @see #mHasForegroundServices * * @hide */ public void setHasForegroundServices(boolean hasForegroundServices) { mHasForegroundServices = hasForegroundServices; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mPid); dest.writeInt(mRealUid); dest.writeInt(mPackageUid); dest.writeInt(mDefiningUid); dest.writeString(mProcessName); dest.writeString(mPackageName); dest.writeInt(mConnectionGroup); dest.writeInt(mReason); dest.writeInt(mSubReason); dest.writeInt(mStatus); dest.writeInt(mImportance); dest.writeLong(mPss); dest.writeLong(mRss); dest.writeLong(mTimestamp); dest.writeString(mDescription); dest.writeByteArray(mState); if (mAppTraceRetriever != null) { dest.writeInt(1); dest.writeStrongBinder(mAppTraceRetriever.asBinder()); } else { dest.writeInt(0); } if (mNativeTombstoneRetriever != null) { dest.writeInt(1); dest.writeStrongBinder(mNativeTombstoneRetriever.asBinder()); } else { dest.writeInt(0); } } /** @hide */ public ApplicationExitInfo() { } /** @hide */ public ApplicationExitInfo(ApplicationExitInfo other) { mPid = other.mPid; mRealUid = other.mRealUid; mPackageUid = other.mPackageUid; mDefiningUid = other.mDefiningUid; mProcessName = other.mProcessName; mPackageName = other.mPackageName; mConnectionGroup = other.mConnectionGroup; mReason = other.mReason; mStatus = other.mStatus; mSubReason = other.mSubReason; mImportance = other.mImportance; mPss = other.mPss; mRss = other.mRss; mTimestamp = other.mTimestamp; mDescription = other.mDescription; mPackageName = other.mPackageName; mPackageList = other.mPackageList; mState = other.mState; mTraceFile = other.mTraceFile; mAppTraceRetriever = other.mAppTraceRetriever; mNativeTombstoneRetriever = other.mNativeTombstoneRetriever; mLoggedInStatsd = other.mLoggedInStatsd; mHasForegroundServices = other.mHasForegroundServices; } private ApplicationExitInfo(@NonNull Parcel in) { mPid = in.readInt(); mRealUid = in.readInt(); mPackageUid = in.readInt(); mDefiningUid = in.readInt(); mProcessName = intern(in.readString()); mPackageName = intern(in.readString()); mConnectionGroup = in.readInt(); mReason = in.readInt(); mSubReason = in.readInt(); mStatus = in.readInt(); mImportance = in.readInt(); mPss = in.readLong(); mRss = in.readLong(); mTimestamp = in.readLong(); mDescription = intern(in.readString()); mState = in.createByteArray(); if (in.readInt() == 1) { mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder()); } if (in.readInt() == 1) { mNativeTombstoneRetriever = IParcelFileDescriptorRetriever.Stub.asInterface( in.readStrongBinder()); } } private static String intern(@Nullable String source) { return source != null ? source.intern() : null; } public @NonNull static final Creator