diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index d54452fb3004c..9039bbdf62cf0 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -781,7 +781,7 @@ public final class ApplicationExitInfo implements Parcelable { * @hide */ public void setProcessName(final String processName) { - mProcessName = processName; + mProcessName = intern(processName); } /** @@ -844,7 +844,7 @@ public final class ApplicationExitInfo implements Parcelable { * @hide */ public void setDescription(final String description) { - mDescription = description; + mDescription = intern(description); } /** @@ -871,7 +871,7 @@ public final class ApplicationExitInfo implements Parcelable { * @hide */ public void setPackageName(final String packageName) { - mPackageName = packageName; + mPackageName = intern(packageName); } /** @@ -1008,8 +1008,8 @@ public final class ApplicationExitInfo implements Parcelable { mRealUid = in.readInt(); mPackageUid = in.readInt(); mDefiningUid = in.readInt(); - mProcessName = in.readString(); - mPackageName = in.readString(); + mProcessName = intern(in.readString()); + mPackageName = intern(in.readString()); mConnectionGroup = in.readInt(); mReason = in.readInt(); mSubReason = in.readInt(); @@ -1018,7 +1018,7 @@ public final class ApplicationExitInfo implements Parcelable { mPss = in.readLong(); mRss = in.readLong(); mTimestamp = in.readLong(); - mDescription = in.readString(); + mDescription = intern(in.readString()); mState = in.createByteArray(); if (in.readInt() == 1) { mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder()); @@ -1029,6 +1029,10 @@ public final class ApplicationExitInfo implements Parcelable { } } + private static String intern(@Nullable String source) { + return source != null ? source.intern() : null; + } + public @NonNull static final Creator CREATOR = new Creator() { @Override @@ -1045,25 +1049,38 @@ public final class ApplicationExitInfo implements Parcelable { /** @hide */ public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, @NonNull SimpleDateFormat sdf) { - pw.println(prefix + "ApplicationExitInfo " + seqSuffix + ":"); - pw.println(prefix + " timestamp=" + sdf.format(new Date(mTimestamp))); - pw.println(prefix + " pid=" + mPid); - pw.println(prefix + " realUid=" + mRealUid); - pw.println(prefix + " packageUid=" + mPackageUid); - pw.println(prefix + " definingUid=" + mDefiningUid); - pw.println(prefix + " user=" + UserHandle.getUserId(mPackageUid)); - pw.println(prefix + " process=" + mProcessName); - pw.println(prefix + " reason=" + mReason + " (" + reasonCodeToString(mReason) + ")"); - pw.println(prefix + " subreason=" + mSubReason + " (" + subreasonToString(mSubReason) - + ")"); - pw.println(prefix + " status=" + mStatus); - pw.println(prefix + " importance=" + mImportance); - 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); + StringBuilder sb = new StringBuilder(); + sb.append(prefix) + .append("ApplicationExitInfo ").append(seqSuffix).append(':') + .append('\n'); + sb.append(prefix).append(' ') + .append(" timestamp=").append(sdf.format(new Date(mTimestamp))) + .append(" pid=").append(mPid) + .append(" realUid=").append(mRealUid) + .append(" packageUid=").append(mPackageUid) + .append(" definingUid=").append(mDefiningUid) + .append(" user=").append(UserHandle.getUserId(mPackageUid)) + .append('\n'); + sb.append(prefix).append(' ') + .append(" process=").append(mProcessName) + .append(" reason=").append(mReason) + .append(" (").append(reasonCodeToString(mReason)).append(")") + .append(" subreason=").append(mSubReason) + .append(" (").append(subreasonToString(mSubReason)).append(")") + .append(" status=").append(mStatus) + .append('\n'); + sb.append(prefix).append(' ') + .append(" importance=").append(mImportance) + .append(" pss="); + DebugUtils.sizeValueToString(mPss << 10, sb); + sb.append(" rss="); + DebugUtils.sizeValueToString(mRss << 10, sb); + sb.append(" description=").append(mDescription) + .append(" state=").append((ArrayUtils.isEmpty(mState) + ? "empty" : Integer.toString(mState.length) + " bytes")) + .append(" trace=").append(mTraceFile) + .append('\n'); + pw.print(sb.toString()); } @Override @@ -1228,7 +1245,7 @@ public final class ApplicationExitInfo implements Parcelable { mDefiningUid = proto.readInt(ApplicationExitInfoProto.DEFINING_UID); break; case (int) ApplicationExitInfoProto.PROCESS_NAME: - mProcessName = proto.readString(ApplicationExitInfoProto.PROCESS_NAME); + mProcessName = intern(proto.readString(ApplicationExitInfoProto.PROCESS_NAME)); break; case (int) ApplicationExitInfoProto.CONNECTION_GROUP: mConnectionGroup = proto.readInt(ApplicationExitInfoProto.CONNECTION_GROUP); @@ -1255,7 +1272,7 @@ public final class ApplicationExitInfo implements Parcelable { mTimestamp = proto.readLong(ApplicationExitInfoProto.TIMESTAMP); break; case (int) ApplicationExitInfoProto.DESCRIPTION: - mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION); + mDescription = intern(proto.readString(ApplicationExitInfoProto.DESCRIPTION)); break; case (int) ApplicationExitInfoProto.STATE: mState = proto.readBytes(ApplicationExitInfoProto.STATE); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index a6b265bd16bb8..dc9ecfeb29ea9 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1079,6 +1079,7 @@ public class OomAdjuster { } if ((numCached - numCachedExtraGroup) > cachedProcessLimit) { app.killLocked("cached #" + numCached, + "too many cached", ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, true); @@ -1089,6 +1090,7 @@ public class OomAdjuster { && app.getLastActivityTime() < oldTime) { app.killLocked("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.getLastActivityTime()) / 1000) + "s", + "empty for too long", ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_TRIM_EMPTY, true); @@ -1096,6 +1098,7 @@ public class OomAdjuster { numEmpty++; if (numEmpty > emptyProcessLimit) { app.killLocked("empty #" + numEmpty, + "too many empty", ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, true); diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index c573615d9f5e3..8ae1259ce4d1c 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -1003,6 +1003,12 @@ class ProcessRecord implements WindowProcessListener { @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { + killLocked(reason, reason, reasonCode, subReason, noisy); + } + + @GuardedBy("mService") + void killLocked(String reason, String description, @Reason int reasonCode, + @SubReason int subReason, boolean noisy) { if (!mKilledByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) { @@ -1011,7 +1017,7 @@ class ProcessRecord implements WindowProcessListener { + "): " + reason, info.uid); } if (mPid > 0) { - mService.mProcessList.noteAppKill(this, reasonCode, subReason, reason); + mService.mProcessList.noteAppKill(this, reasonCode, subReason, description); EventLog.writeEvent(EventLogTags.AM_KILL, userId, mPid, processName, mState.getSetAdj(), reason); Process.killProcessQuiet(mPid);