Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ef8f5e1 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Add support to provide app its own ANR stack trace" into rvc-dev

parents f6567d2e 56006fd5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -4049,6 +4049,7 @@ package android.app {
    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 @Deprecated public void restartPackage(String);
    method public void setProcessStateSummary(@Nullable byte[]);
    method public static void setVrThread(int);
    method public void setWatchHeapLimit(long);
    field public static final String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
@@ -4561,12 +4562,14 @@ package android.app {
    method public int getPackageUid();
    method public int getPid();
    method @NonNull public String getProcessName();
    method @Nullable public byte[] getProcessStateSummary();
    method public long getPss();
    method public int getRealUid();
    method public int getReason();
    method public long getRss();
    method public int getStatus();
    method public long getTimestamp();
    method @Nullable public java.io.InputStream getTraceInputStream() throws java.io.IOException;
    method @NonNull public android.os.UserHandle getUserHandle();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationExitInfo> CREATOR;
+30 −1
Original line number Diff line number Diff line
@@ -3628,11 +3628,40 @@ public class ActivityManager {
        }
    }

    /**
     * Set custom state data for this process. It will be included in the record of
     * {@link ApplicationExitInfo} on the death of the current calling process; the new process
     * of the app can retrieve this state data by calling
     * {@link ApplicationExitInfo#getProcessStateSummary} on the record returned by
     * {@link #getHistoricalProcessExitReasons}.
     *
     * <p> This would be useful for the calling app to save its stateful data: if it's
     * killed later for any reason, the new process of the app can know what the
     * previous process of the app was doing. For instance, you could use this to encode
     * the current level in a game, or a set of features/experiments that were enabled. Later you
     * could analyze under what circumstances the app tends to crash or use too much memory.
     * However, it's not suggested to rely on this to restore the applications previous UI state
     * or so, it's only meant for analyzing application healthy status.</p>
     *
     * <p> System might decide to throttle the calls to this API; so call this API in a reasonable
     * manner, excessive calls to this API could result a {@link java.lang.RuntimeException}.
     * </p>
     *
     * @param state The state data
     */
    public void setProcessStateSummary(@Nullable byte[] state) {
        try {
            getService().setProcessStateSummary(state);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /*
     * @return Whether or not the low memory kill will be reported in
     * {@link #getHistoricalProcessExitReasons}.
     *
     * @see {@link ApplicationExitInfo#REASON_LOW_MEMORY}
     * @see ApplicationExitInfo#REASON_LOW_MEMORY
     */
    public static boolean isLowMemoryKillReportSupported() {
        return SystemProperties.getBoolean("persist.sys.lmk.reportkills", false);
+170 −35
Original line number Diff line number Diff line
@@ -23,7 +23,9 @@ 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;
@@ -31,12 +33,17 @@ 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.
@@ -321,85 +328,105 @@ public final class ApplicationExitInfo implements Parcelable {
    // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.

    /**
     * @see {@link #getPid}
     * @see #getPid
     */
    private int mPid;

    /**
     * @see {@link #getRealUid}
     * @see #getRealUid
     */
    private int mRealUid;

    /**
     * @see {@link #getPackageUid}
     * @see #getPackageUid
     */
    private int mPackageUid;

    /**
     * @see {@link #getDefiningUid}
     * @see #getDefiningUid
     */
    private int mDefiningUid;

    /**
     * @see {@link #getProcessName}
     * @see #getProcessName
     */
    private String mProcessName;

    /**
     * @see {@link #getReason}
     * @see #getReason
     */
    private @Reason int mReason;

    /**
     * @see {@link #getStatus}
     * @see #getStatus
     */
    private int mStatus;

    /**
     * @see {@link #getImportance}
     * @see #getImportance
     */
    private @Importance int mImportance;

    /**
     * @see {@link #getPss}
     * @see #getPss
     */
    private long mPss;

    /**
     * @see {@link #getRss}
     * @see #getRss
     */
    private long mRss;

    /**
     * @see {@link #getTimestamp}
     * @see #getTimestamp
     */
    private @CurrentTimeMillisLong long mTimestamp;

    /**
     * @see {@link #getDescription}
     * @see #getDescription
     */
    private @Nullable String mDescription;

    /**
     * @see {@link #getSubReason}
     * @see #getSubReason
     */
    private @SubReason int mSubReason;

    /**
     * @see {@link #getConnectionGroup}
     * @see #getConnectionGroup
     */
    private int mConnectionGroup;

    /**
     * @see {@link #getPackageName}
     * @see #getPackageName
     */
    private String mPackageName;

    /**
     * @see {@link #getPackageList}
     * @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;

    /** @hide */
    @IntDef(prefix = { "REASON_" }, value = {
        REASON_UNKNOWN,
@@ -556,6 +583,54 @@ public final class ApplicationExitInfo implements Parcelable {
        return UserHandle.of(UserHandle.getUserId(mRealUid));
    }

    /**
     * Return the state data set by calling {@link ActivityManager#setProcessStateSummary}
     * 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.
     *
     * @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) {
            return null;
        }
        try {
            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}.
     *
@@ -569,7 +644,7 @@ public final class ApplicationExitInfo implements Parcelable {

    /**
     * The connection group this process belongs to, if there is any.
     * @see {@link android.content.Context#updateServiceGroup}.
     * @see android.content.Context#updateServiceGroup
     *
     * For internal use only.
     *
@@ -582,8 +657,6 @@ public final class ApplicationExitInfo implements Parcelable {
    /**
     * Name of first package running in this process;
     *
     * For system internal use only, will not retain across processes.
     *
     * @hide
     */
    public String getPackageName() {
@@ -602,7 +675,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getPid}
     * @see #getPid
     *
     * @hide
     */
@@ -611,7 +684,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getRealUid}
     * @see #getRealUid
     *
     * @hide
     */
@@ -620,7 +693,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getPackageUid}
     * @see #getPackageUid
     *
     * @hide
     */
@@ -629,7 +702,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getDefiningUid}
     * @see #getDefiningUid
     *
     * @hide
     */
@@ -638,7 +711,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getProcessName}
     * @see #getProcessName
     *
     * @hide
     */
@@ -647,7 +720,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getReason}
     * @see #getReason
     *
     * @hide
     */
@@ -656,7 +729,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getStatus}
     * @see #getStatus
     *
     * @hide
     */
@@ -665,7 +738,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getImportance}
     * @see #getImportance
     *
     * @hide
     */
@@ -674,7 +747,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getPss}
     * @see #getPss
     *
     * @hide
     */
@@ -683,7 +756,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getRss}
     * @see #getRss
     *
     * @hide
     */
@@ -692,7 +765,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getTimestamp}
     * @see #getTimestamp
     *
     * @hide
     */
@@ -701,7 +774,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getDescription}
     * @see #getDescription
     *
     * @hide
     */
@@ -710,7 +783,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getSubReason}
     * @see #getSubReason
     *
     * @hide
     */
@@ -719,7 +792,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getConnectionGroup}
     * @see #getConnectionGroup
     *
     * @hide
     */
@@ -728,7 +801,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getPackageName}
     * @see #getPackageName
     *
     * @hide
     */
@@ -737,7 +810,7 @@ public final class ApplicationExitInfo implements Parcelable {
    }

    /**
     * @see {@link #getPackageList}
     * @see #getPackageList
     *
     * @hide
     */
@@ -745,6 +818,33 @@ public final class ApplicationExitInfo implements Parcelable {
        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;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -757,6 +857,7 @@ public final class ApplicationExitInfo implements Parcelable {
        dest.writeInt(mPackageUid);
        dest.writeInt(mDefiningUid);
        dest.writeString(mProcessName);
        dest.writeString(mPackageName);
        dest.writeInt(mConnectionGroup);
        dest.writeInt(mReason);
        dest.writeInt(mSubReason);
@@ -766,6 +867,13 @@ public final class ApplicationExitInfo implements Parcelable {
        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);
        }
    }

    /** @hide */
@@ -779,6 +887,7 @@ public final class ApplicationExitInfo implements Parcelable {
        mPackageUid = other.mPackageUid;
        mDefiningUid = other.mDefiningUid;
        mProcessName = other.mProcessName;
        mPackageName = other.mPackageName;
        mConnectionGroup = other.mConnectionGroup;
        mReason = other.mReason;
        mStatus = other.mStatus;
@@ -790,6 +899,9 @@ public final class ApplicationExitInfo implements Parcelable {
        mDescription = other.mDescription;
        mPackageName = other.mPackageName;
        mPackageList = other.mPackageList;
        mState = other.mState;
        mTraceFile = other.mTraceFile;
        mAppTraceRetriever = other.mAppTraceRetriever;
    }

    private ApplicationExitInfo(@NonNull Parcel in) {
@@ -798,6 +910,7 @@ public final class ApplicationExitInfo implements Parcelable {
        mPackageUid = in.readInt();
        mDefiningUid = in.readInt();
        mProcessName = in.readString();
        mPackageName = in.readString();
        mConnectionGroup = in.readInt();
        mReason = in.readInt();
        mSubReason = in.readInt();
@@ -807,6 +920,10 @@ public final class ApplicationExitInfo implements Parcelable {
        mRss = in.readLong();
        mTimestamp = in.readLong();
        mDescription = in.readString();
        mState = in.createByteArray();
        if (in.readInt() == 1) {
            mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder());
        }
    }

    public @NonNull static final Creator<ApplicationExitInfo> CREATOR =
@@ -839,6 +956,9 @@ public final class ApplicationExitInfo implements Parcelable {
        pw.print(prefix + "  pss="); DebugUtils.printSizeValue(pw, mPss << 10); pw.println();
        pw.print(prefix + "  rss="); DebugUtils.printSizeValue(pw, mRss << 10); pw.println();
        pw.println(prefix + "  description=" + mDescription);
        pw.println(prefix + "  state=" + (ArrayUtils.isEmpty(mState)
                ? "empty" : Integer.toString(mState.length) + " bytes"));
        pw.println(prefix + "  trace=" + mTraceFile);
    }

    @Override
@@ -859,6 +979,9 @@ public final class ApplicationExitInfo implements Parcelable {
        sb.append(" pss="); DebugUtils.sizeValueToString(mPss << 10, sb);
        sb.append(" rss="); DebugUtils.sizeValueToString(mRss << 10, sb);
        sb.append(" description=").append(mDescription);
        sb.append(" state=").append(ArrayUtils.isEmpty(mState)
                ? "empty" : Integer.toString(mState.length) + " bytes");
        sb.append(" trace=").append(mTraceFile);
        return sb.toString();
    }

@@ -961,6 +1084,9 @@ public final class ApplicationExitInfo implements Parcelable {
        proto.write(ApplicationExitInfoProto.RSS, mRss);
        proto.write(ApplicationExitInfoProto.TIMESTAMP, mTimestamp);
        proto.write(ApplicationExitInfoProto.DESCRIPTION, mDescription);
        proto.write(ApplicationExitInfoProto.STATE, mState);
        proto.write(ApplicationExitInfoProto.TRACE_FILE,
                mTraceFile == null ? null : mTraceFile.getAbsolutePath());
        proto.end(token);
    }

@@ -1019,6 +1145,15 @@ public final class ApplicationExitInfo implements Parcelable {
                case (int) ApplicationExitInfoProto.DESCRIPTION:
                    mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION);
                    break;
                case (int) ApplicationExitInfoProto.STATE:
                    mState = proto.readBytes(ApplicationExitInfoProto.STATE);
                    break;
                case (int) ApplicationExitInfoProto.TRACE_FILE:
                    final String path = proto.readString(ApplicationExitInfoProto.TRACE_FILE);
                    if (!TextUtils.isEmpty(path)) {
                        mTraceFile = new File(path);
                    }
                    break;
            }
        }
        proto.end(token);
+23 −0
Original line number Diff line number Diff line
@@ -652,4 +652,27 @@ interface IActivityManager {
     */
    void setActivityLocusContext(in ComponentName activity, in LocusId locusId,
            in IBinder appToken);

    /**
     * Set custom state data for this process. It will be included in the record of
     * {@link ApplicationExitInfo} on the death of the current calling process; the new process
     * of the app can retrieve this state data by calling
     * {@link ApplicationExitInfo#getProcessStateSummary} on the record returned by
     * {@link #getHistoricalProcessExitReasons}.
     *
     * <p> This would be useful for the calling app to save its stateful data: if it's
     * killed later for any reason, the new process of the app can know what the
     * previous process of the app was doing. For instance, you could use this to encode
     * the current level in a game, or a set of features/experiments that were enabled. Later you
     * could analyze under what circumstances the app tends to crash or use too much memory.
     * However, it's not suggested to rely on this to restore the applications previous UI state
     * or so, it's only meant for analyzing application healthy status.</p>
     *
     * <p> System might decide to throttle the calls to this API; so call this API in a reasonable
     * manner, excessive calls to this API could result a {@link java.lang.RuntimeException}.
     * </p>
     *
     * @param state The customized state data
     */
    void setProcessStateSummary(in byte[] state);
}
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.os.ParcelFileDescriptor;

/**
 * An interface that's to be used by {@link ApplicationExitInfo#getTraceFile()}
 * to retrieve the actual file descriptor to its trace file.
 *
 * @hide
 */
interface IAppTraceRetriever {
    /**
     * Retrieve the trace file with given packageName/uid/pid.
     *
     * @param packagename The target package name of the trace
     * @param uid The target UID of the trace
     * @param pid The target PID of the trace
     * @return The file descriptor to the trace file, or null if it's not found.
     */
    ParcelFileDescriptor getTraceFileDescriptor(in String packageName,
            int uid, int pid);
}
Loading