summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/app/ApplicationExitInfo.java174
-rw-r--r--core/proto/android/app/appexit_enums.proto240
-rw-r--r--core/proto/android/app/appexitinfo.proto146
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java60
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java14
-rw-r--r--services/core/java/com/android/server/am/AppExitInfoTracker.java1
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java6
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java34
9 files changed, 493 insertions, 187 deletions
diff --git a/api/current.txt b/api/current.txt
index 02b87342329c..f5135b2349b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4572,14 +4572,17 @@ package android.app {
field public static final int REASON_ANR = 6; // 0x6
field public static final int REASON_CRASH = 4; // 0x4
field public static final int REASON_CRASH_NATIVE = 5; // 0x5
+ field public static final int REASON_DEPENDENCY_DIED = 12; // 0xc
field public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9; // 0x9
field public static final int REASON_EXIT_SELF = 1; // 0x1
field public static final int REASON_INITIALIZATION_FAILURE = 7; // 0x7
field public static final int REASON_LOW_MEMORY = 3; // 0x3
- field public static final int REASON_OTHER = 10; // 0xa
+ field public static final int REASON_OTHER = 13; // 0xd
field public static final int REASON_PERMISSION_CHANGE = 8; // 0x8
field public static final int REASON_SIGNALED = 2; // 0x2
field public static final int REASON_UNKNOWN = 0; // 0x0
+ field public static final int REASON_USER_REQUESTED = 10; // 0xa
+ field public static final int REASON_USER_STOPPED = 11; // 0xb
}
public final class AsyncNotedAppOp implements android.os.Parcelable {
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index c55453e94960..5df3257f2444 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -121,11 +122,30 @@ public final class ApplicationExitInfo implements Parcelable {
public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9;
/**
- * Application process was killed by the system for various other reasons,
- * for example, the application package got disabled by the user;
- * {@link #getDescription} will specify the cause given by the system.
+ * 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.
*/
- public static final int REASON_OTHER = 10;
+ 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 kills subreason is unknown.
@@ -202,6 +222,105 @@ public final class ApplicationExitInfo implements Parcelable {
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;
+
+ // 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 {@link #getPid}
*/
private int mPid;
@@ -254,7 +373,7 @@ public final class ApplicationExitInfo implements Parcelable {
/**
* @see {@link #getTimestamp}
*/
- private long mTimestamp;
+ private @CurrentTimeMillisLong long mTimestamp;
/**
* @see {@link #getDescription}
@@ -293,6 +412,9 @@ public final class ApplicationExitInfo implements Parcelable {
REASON_INITIALIZATION_FAILURE,
REASON_PERMISSION_CHANGE,
REASON_EXCESSIVE_RESOURCE_USAGE,
+ REASON_USER_REQUESTED,
+ REASON_USER_STOPPED,
+ REASON_DEPENDENCY_DIED,
REASON_OTHER,
})
@Retention(RetentionPolicy.SOURCE)
@@ -308,6 +430,16 @@ public final class ApplicationExitInfo implements Parcelable {
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,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SubReason {}
@@ -403,7 +535,7 @@ public final class ApplicationExitInfo implements Parcelable {
* The timestamp of the process's death, in milliseconds since the epoch,
* as returned by {@link System#currentTimeMillis System.currentTimeMillis()}.
*/
- public long getTimestamp() {
+ public @CurrentTimeMillisLong long getTimestamp() {
return mTimestamp;
}
@@ -564,7 +696,7 @@ public final class ApplicationExitInfo implements Parcelable {
*
* @hide
*/
- public void setTimestamp(final long timestamp) {
+ public void setTimestamp(final @CurrentTimeMillisLong long timestamp) {
mTimestamp = timestamp;
}
@@ -656,6 +788,8 @@ public final class ApplicationExitInfo implements Parcelable {
mRss = other.mRss;
mTimestamp = other.mTimestamp;
mDescription = other.mDescription;
+ mPackageName = other.mPackageName;
+ mPackageList = other.mPackageList;
}
private ApplicationExitInfo(@NonNull Parcel in) {
@@ -748,6 +882,12 @@ public final class ApplicationExitInfo implements Parcelable {
return "PERMISSION CHANGE";
case REASON_EXCESSIVE_RESOURCE_USAGE:
return "EXCESSIVE RESOURCE USAGE";
+ case REASON_USER_REQUESTED:
+ return "USER REQUESTED";
+ case REASON_USER_STOPPED:
+ return "USER STOPPED";
+ case REASON_DEPENDENCY_DIED:
+ return "DEPENDENCY DIED";
case REASON_OTHER:
return "OTHER KILLS BY SYSTEM";
default:
@@ -772,6 +912,26 @@ public final class ApplicationExitInfo implements Parcelable {
return "MEMORY PRESSURE";
case SUBREASON_EXCESSIVE_CPU:
return "EXCESSIVE CPU USAGE";
+ case SUBREASON_SYSTEM_UPDATE_DONE:
+ return "SYSTEM UPDATE_DONE";
+ case SUBREASON_KILL_ALL_FG:
+ return "KILL ALL FG";
+ case SUBREASON_KILL_ALL_BG_EXCEPT:
+ return "KILL ALL BG EXCEPT";
+ case SUBREASON_KILL_UID:
+ return "KILL UID";
+ case SUBREASON_KILL_PID:
+ return "KILL PID";
+ case SUBREASON_INVALID_START:
+ return "INVALID START";
+ case SUBREASON_INVALID_STATE:
+ return "INVALID STATE";
+ case SUBREASON_IMPERCEPTIBLE:
+ return "IMPERCEPTIBLE";
+ case SUBREASON_REMOVE_LRU:
+ return "REMOVE LRU";
+ case SUBREASON_ISOLATED_NOT_NEEDED:
+ return "ISOLATED NOT NEEDED";
default:
return "UNKNOWN";
}
diff --git a/core/proto/android/app/appexit_enums.proto b/core/proto/android/app/appexit_enums.proto
new file mode 100644
index 000000000000..491e1dc203b5
--- /dev/null
+++ b/core/proto/android/app/appexit_enums.proto
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option java_multiple_files = true;
+
+package android.app;
+
+/**
+ * The reason code that why app process is killed.
+ */
+enum AppExitReasonCode {
+ /**
+ * Application process died due to unknown reason.
+ */
+ REASON_UNKNOWN = 0;
+
+ /**
+ * Application process exit normally by itself, for example,
+ * via {@link android.os.Process#exit}; {@link #status} will specify the exit code.
+ *
+ * <p>Applications should normally not do this, as the system has a better knowledge
+ * in terms of process management.</p>
+ */
+ REASON_EXIT_SELF = 1;
+
+ /**
+ * Application process died due to the result of an OS signal; for example,
+ * {@link android.os.Process#SIGNAL_KILL}; {@link #status} will specify the signum.
+ */
+ 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.
+ */
+ REASON_LOW_MEMORY = 3;
+
+ /**
+ * Application process died because of an unhandled exception in Java code.
+ */
+ REASON_CRASH = 4;
+
+ /**
+ * Application process died because it's crashed due to a native code crash.
+ */
+ REASON_CRASH_NATIVE = 5;
+
+ /**
+ * Application process was killed due to being unresponsive (ANR).
+ */
+ REASON_ANR = 6;
+
+ /**
+ * Application process was killed because it took too long to attach to the system
+ * during the start.
+ */
+ REASON_INITIALIZATION_FAILURE = 7;
+
+ /**
+ * 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.
+ */
+ REASON_PERMISSION_CHANGE = 8;
+
+ /**
+ * Application process was killed by the activity manager due to excessive resource usage.
+ */
+ 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 swiped away the application from Recents.
+ */
+ REASON_USER_REQUESTED = 10;
+
+ /**
+ * Application process was killed, because the user they are running as on devices
+ * with mutlple users, was stopped.
+ */
+ 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.
+ */
+ REASON_DEPENDENCY_DIED = 12;
+
+ /**
+ * Application process was killed by the system for various other reasons,
+ * for example, the application package got disabled by the user;
+ * {@link #description} will specify the cause given by the system.
+ */
+ REASON_OTHER = 13;
+}
+
+/**
+ * The supplemental reason code that why app process is killed
+ */
+enum AppExitSubReasonCode {
+ /**
+ * Application process kills subReason is unknown.
+ */
+ SUBREASON_UNKNOWN = 0;
+
+ /**
+ * Application process was killed because user quit it on the "wait for debugger" dialog.
+ */
+ SUBREASON_WAIT_FOR_DEBUGGER = 1;
+
+ /**
+ * Application process was killed by the activity manager because there were too many cached
+ * processes.
+ */
+ SUBREASON_TOO_MANY_CACHED = 2;
+
+ /**
+ * Application process was killed by the activity manager because there were too many empty
+ * processes.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ SUBREASON_MEMORY_PRESSURE = 6;
+
+ /**
+ * Application process was killed by the activity manager due to excessive CPU usage.
+ */
+ SUBREASON_EXCESSIVE_CPU = 7;
+
+ /**
+ * System update has done (so the system update process should be killed).
+ */
+ SUBREASON_SYSTEM_UPDATE_DONE = 8;
+
+ /**
+ * Kill all foreground services, for now it only occurs when enabling the quiet
+ * mode for the managed profile.
+ */
+ 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.
+ */
+ SUBREASON_KILL_ALL_BG_EXCEPT = 10;
+
+ /**
+ * The process associated with the UID was explicitly killed, for example,
+ * it could be because of permission changes.
+ */
+ SUBREASON_KILL_UID = 11;
+
+ /**
+ * The process was explicitly killed with its PID, typically because of
+ * the low memory for surfaces.
+ */
+ SUBREASON_KILL_PID = 12;
+
+ /**
+ * The start of the process was invalid.
+ */
+ SUBREASON_INVALID_START = 13;
+
+ /**
+ * The process was killed because it's in an invalid state, typically
+ * it's triggered from SHELL.
+ */
+ SUBREASON_INVALID_STATE = 14;
+
+ /**
+ * The process was killed when it's imperceptible to user, because it was
+ * in a bad state.
+ */
+ SUBREASON_IMPERCEPTIBLE = 15;
+
+ /**
+ * The process was killed because it's being moved out from LRU list.
+ */
+ SUBREASON_REMOVE_LRU = 16;
+
+ /**
+ * The process was killed because it's isolated and was in a cached state.
+ */
+ SUBREASON_ISOLATED_NOT_NEEDED = 17;
+}
+
+/**
+ * The relative importance level that the system places on a process.
+ * Keep sync with the definitions in
+ * {@link android.app.ActivityManager.RunningAppProcessInfo}
+ */
+enum Importance {
+ option allow_alias = true;
+
+ IMPORTANCE_FOREGROUND = 100;
+ IMPORTANCE_FOREGROUND_SERVICE = 125;
+ IMPORTANCE_TOP_SLEEPING_PRE_28 = 150;
+ IMPORTANCE_VISIBLE = 200;
+ IMPORTANCE_PERCEPTIBLE_PRE_26 = 130;
+ IMPORTANCE_PERCEPTIBLE = 230;
+ IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
+ IMPORTANCE_SERVICE = 300;
+ IMPORTANCE_TOP_SLEEPING = 325;
+ IMPORTANCE_CANT_SAVE_STATE = 350;
+ IMPORTANCE_CACHED = 400;
+ IMPORTANCE_BACKGROUND = 400;
+ IMPORTANCE_EMPTY = 500;
+ IMPORTANCE_GONE = 1000;
+}
diff --git a/core/proto/android/app/appexitinfo.proto b/core/proto/android/app/appexitinfo.proto
index 6a4922000805..66173f60bfd5 100644
--- a/core/proto/android/app/appexitinfo.proto
+++ b/core/proto/android/app/appexitinfo.proto
@@ -20,6 +20,7 @@ option java_multiple_files = true;
package android.app;
import "frameworks/base/core/proto/android/privacy.proto";
+import "frameworks/base/core/proto/android/app/appexit_enums.proto";
/**
* An android.app.ApplicationExitInfo object.
@@ -33,150 +34,9 @@ message ApplicationExitInfoProto {
optional int32 defining_uid = 4;
optional string process_name = 5;
optional int32 connection_group = 6;
-
- enum ReasonCode {
- /**
- * Application process died due to unknown reason.
- */
- REASON_UNKNOWN = 0;
-
- /**
- * Application process exit normally by itself, for example,
- * via {@link android.os.Process#exit}; {@link #status} will specify the exit code.
- *
- * <p>Applications should normally not do this, as the system has a better knowledge
- * in terms of process management.</p>
- */
- REASON_EXIT_SELF = 1;
-
- /**
- * Application process died due to the result of an OS signal; for example,
- * {@link android.os.Process#SIGNAL_KILL}; {@link #status} will specify the signum.
- */
- 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.
- */
- REASON_LOW_MEMORY = 3;
-
- /**
- * Application process died because of an unhandled exception in Java code.
- */
- REASON_CRASH = 4;
-
- /**
- * Application process died because it's crashed due to a native code crash.
- */
- REASON_CRASH_NATIVE = 5;
-
- /**
- * Application process was killed due to being unresponsive (ANR).
- */
- REASON_ANR = 6;
-
- /**
- * Application process was killed because it took too long to attach to the system
- * during the start.
- */
- REASON_INITIALIZATION_FAILURE = 7;
-
- /**
- * 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.
- */
- REASON_PERMISSION_CHANGE = 8;
-
- /**
- * Application process was killed by the activity manager due to excessive resource usage.
- */
- REASON_EXCESSIVE_RESOURCE_USAGE = 9;
-
- /**
- * Application process was killed by the system for various other reasons,
- * for example, the application package got disabled by the user;
- * {@link #description} will specify the cause given by the system.
- */
- REASON_OTHER = 10;
-
- }
- optional ReasonCode reason = 7;
-
- enum SubReason {
- /**
- * Application process kills subReason is unknown.
- */
- SUBREASON_UNKNOWN = 0;
-
- /**
- * Application process was killed because user quit it on the "wait for debugger" dialog.
- */
- SUBREASON_WAIT_FOR_DEBUGGER = 1;
-
- /**
- * Application process was killed by the activity manager because there were too many cached
- * processes.
- */
- SUBREASON_TOO_MANY_CACHED = 2;
-
- /**
- * Application process was killed by the activity manager because there were too many empty
- * processes.
- */
- 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.
- */
- 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.
- */
- 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.
- */
- SUBREASON_MEMORY_PRESSURE = 6;
-
- /**
- * Application process was killed by the activity manager due to excessive CPU usage.
- */
- SUBREASON_EXCESSIVE_CPU = 7;
- }
-
- optional SubReason sub_reason = 8;
-
+ optional AppExitReasonCode reason = 7;
+ optional AppExitSubReasonCode sub_reason = 8;
optional int32 status = 9;
-
- enum Importance {
- option allow_alias = true;
- /**
- * Keep sync with the definitions in
- * {@link android.app.ActivityManager.RunningAppProcessInfo}
- */
- IMPORTANCE_FOREGROUND = 100;
- IMPORTANCE_FOREGROUND_SERVICE = 125;
- IMPORTANCE_TOP_SLEEPING_PRE_28 = 150;
- IMPORTANCE_VISIBLE = 200;
- IMPORTANCE_PERCEPTIBLE_PRE_26 = 130;
- IMPORTANCE_PERCEPTIBLE = 230;
- IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
- IMPORTANCE_SERVICE = 300;
- IMPORTANCE_TOP_SLEEPING = 325;
- IMPORTANCE_CANT_SAVE_STATE = 350;
- IMPORTANCE_CACHED = 400;
- IMPORTANCE_BACKGROUND = 400;
- IMPORTANCE_EMPTY = 500;
- IMPORTANCE_GONE = 1000;
- }
-
optional Importance importance = 10;
optional int64 pss = 11;
optional int64 rss = 12;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fbcb0102eb47..9058ac451455 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -81,6 +81,8 @@ import static android.os.Process.removeAllProcessGroups;
import static android.os.Process.sendSignal;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
+import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
+import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
@@ -4243,7 +4245,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (this) {
mProcessList.killPackageProcessesLocked(packageName, appId, targetUserId,
- ProcessList.SERVICE_ADJ, "kill background");
+ ProcessList.SERVICE_ADJ, ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN, "kill background");
}
}
} finally {
@@ -4269,7 +4272,10 @@ public class ActivityManagerService extends IActivityManager.Stub
// because this method is also used to simulate low memory.
mAllowLowerMemLevel = true;
mProcessList.killPackageProcessesLocked(null /* packageName */, -1 /* appId */,
- UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ, "kill all background");
+ UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ,
+ ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "kill all background");
doLowMemReportIfNeededLocked(null);
}
@@ -4757,6 +4763,9 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean didSomething = mProcessList.killPackageProcessesLocked(packageName, appId, userId,
ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
evenPersistent, true /* setRemoved */,
+ packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
+ : ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
packageName == null ? ("stop user " + userId) : ("stop " + packageName));
didSomething |=
@@ -4820,7 +4829,10 @@ public class ActivityManagerService extends IActivityManager.Stub
@GuardedBy("this")
private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
cleanupAppInLaunchingProvidersLocked(app, true);
- mProcessList.removeProcessLocked(app, false, true, "timeout publishing content providers");
+ mProcessList.removeProcessLocked(app, false, true,
+ ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "timeout publishing content providers");
}
@GuardedBy("this")
@@ -4925,7 +4937,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (pid > 0 && pid != MY_PID) {
killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
- mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
+ mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
ApplicationExitInfo.SUBREASON_UNKNOWN, "attach failed");
} else {
try {
@@ -9054,7 +9066,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
int adj = proc.setAdj;
if (adj >= worstType && !proc.killedByAm) {
- proc.kill(reason, ApplicationExitInfo.REASON_OTHER, true);
+ proc.kill(reason, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_PID, true);
killed = true;
}
}
@@ -9068,10 +9081,17 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
try {
+ boolean permissionChange = KILL_APP_REASON_PERMISSIONS_REVOKED.equals(reason)
+ || KILL_APP_REASON_GIDS_CHANGED.equals(reason);
mProcessList.killPackageProcessesLocked(null /* packageName */, appId, userId,
ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
true /* callerWillRestart */, true /* doit */, true /* evenPersistent */,
- false /* setRemoved */, reason != null ? reason : "kill uid");
+ false /* setRemoved */,
+ permissionChange ? ApplicationExitInfo.REASON_PERMISSION_CHANGE
+ : ApplicationExitInfo.REASON_OTHER,
+ permissionChange ? ApplicationExitInfo.SUBREASON_UNKNOWN
+ : ApplicationExitInfo.SUBREASON_KILL_UID,
+ reason != null ? reason : "kill uid");
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -9396,7 +9416,10 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
- mProcessList.removeProcessLocked(proc, true, false, "system update done");
+ mProcessList.removeProcessLocked(proc, true, false,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_SYSTEM_UPDATE_DONE,
+ "system update done");
}
}
@@ -14400,7 +14423,8 @@ public class ActivityManagerService extends IActivityManager.Stub
+ cpr.name.flattenToShortString()
+ " in dying proc " + (proc != null ? proc.processName : "??")
+ " (adj " + (proc != null ? proc.setAdj : "??") + ")",
- ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.REASON_DEPENDENCY_DIED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
true);
}
} else if (capp.thread != null && conn.provider.provider != null) {
@@ -15892,7 +15916,10 @@ public class ActivityManagerService extends IActivityManager.Stub
-1);
mProcessList.killPackageProcessesLocked(ssp,
UserHandle.getAppId(extraUid),
- userId, ProcessList.INVALID_ADJ, "change " + ssp);
+ userId, ProcessList.INVALID_ADJ,
+ ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "change " + ssp);
}
cleanupDisabledPackageComponentsLocked(ssp, userId,
intent.getStringArrayExtra(
@@ -18622,7 +18649,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final int N = procs.size();
for (int i = 0; i < N; i++) {
- mProcessList.removeProcessLocked(procs.get(i), false, true, "kill all fg");
+ mProcessList.removeProcessLocked(procs.get(i), false, true,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_ALL_FG,
+ "kill all fg");
}
}
}
@@ -18844,7 +18874,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final ProcessRecord pr = (ProcessRecord) wpc.mOwner;
if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
&& pr.curReceivers.isEmpty()) {
- pr.kill("remove task", ApplicationExitInfo.REASON_OTHER, true);
+ pr.kill("remove task", ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN, true);
} else {
// We delay killing processes that are not in the background or running a
// receiver.
@@ -18861,7 +18892,7 @@ public class ActivityManagerService extends IActivityManager.Stub
true /* keepIfLarge */);
if (proc != null) {
mProcessList.removeProcessLocked(proc, false /* callerWillRestart */,
- true /* allowRestart */, reason);
+ true /* allowRestart */, ApplicationExitInfo.REASON_OTHER, reason);
}
}
}
@@ -19547,7 +19578,10 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized(this) {
mProcessList.killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid),
- userId, ProcessList.FOREGROUND_APP_ADJ, "dep: " + packageName);
+ userId, ProcessList.FOREGROUND_APP_ADJ,
+ ApplicationExitInfo.REASON_DEPENDENCY_DIED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "dep: " + packageName);
}
} finally {
Binder.restoreCallingIdentity(callingId);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 789f7199948d..b1fc0296518b 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -395,7 +395,7 @@ class AppErrors {
() -> {
synchronized (mService) {
killAppImmediateLocked(p, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE,
"forced", "killed for invalid state");
}
},
@@ -510,8 +510,8 @@ class AppErrors {
stopReportingCrashesLocked(r);
}
if (res == AppErrorDialog.RESTART) {
- mService.mProcessList.removeProcessLocked(r, false, true, "crash",
- ApplicationExitInfo.REASON_CRASH);
+ mService.mProcessList.removeProcessLocked(r, false, true,
+ ApplicationExitInfo.REASON_CRASH, "crash");
if (taskId != INVALID_TASK_ID) {
try {
mService.startActivityFromRecents(taskId,
@@ -529,8 +529,8 @@ class AppErrors {
// Kill it with fire!
mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
if (!r.isPersistent()) {
- mService.mProcessList.removeProcessLocked(r, false, false, "crash",
- ApplicationExitInfo.REASON_CRASH);
+ mService.mProcessList.removeProcessLocked(r, false, false,
+ ApplicationExitInfo.REASON_CRASH, "crash");
mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
}
} finally {
@@ -747,8 +747,8 @@ class AppErrors {
// Don't let services in this process be restarted and potentially
// annoy the user repeatedly. Unless it is persistent, since those
// processes run critical code.
- mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash",
- ApplicationExitInfo.REASON_CRASH);
+ mService.mProcessList.removeProcessLocked(app, false, tryAgain,
+ ApplicationExitInfo.REASON_CRASH, "crash");
mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
if (!showBackground) {
return false;
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index cba6b92bf440..a09aa64476c1 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -348,6 +348,7 @@ public final class AppExitInfoTracker {
} else {
// always override the existing info since we are now more informational.
info.setReason(raw.getReason());
+ info.setSubReason(raw.getSubReason());
info.setStatus(0);
info.setTimestamp(System.currentTimeMillis());
info.setDescription(raw.getDescription());
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index e7b467adf487..aa37b4accc40 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -840,7 +840,8 @@ public final class OomAdjuster {
// definition not re-use the same process again, and it is
// good to avoid having whatever code was running in them
// left sitting around after no longer needed.
- app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER, true);
+ app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
} else {
// Keeping this process, update its uid.
updateAppUidRecLocked(app);
@@ -2166,7 +2167,8 @@ public final class OomAdjuster {
}
if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
- app.kill(app.waitingToKill, ApplicationExitInfo.REASON_OTHER, true);
+ app.kill(app.waitingToKill, ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN, true);
success = false;
} else {
int processGroup;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3a5447edfdf0..a9d18e05e350 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2378,7 +2378,7 @@ public final class ProcessList {
killProcessQuiet(pid);
Process.killProcessGroup(app.uid, app.pid);
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNKNOWN, reason);
+ ApplicationExitInfo.SUBREASON_INVALID_START, reason);
return false;
}
mService.mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
@@ -2463,7 +2463,7 @@ public final class ProcessList {
killProcessQuiet(app.pid);
ProcessList.killProcessGroup(app.uid, app.pid);
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNKNOWN, "hasn't been killed");
+ ApplicationExitInfo.SUBREASON_REMOVE_LRU, "hasn't been killed");
} else {
app.pendingStart = false;
}
@@ -2481,10 +2481,11 @@ public final class ProcessList {
@GuardedBy("mService")
boolean killPackageProcessesLocked(String packageName, int appId, int userId, int minOomAdj,
- String reason) {
+ int reasonCode, int subReason, String reason) {
return killPackageProcessesLocked(packageName, appId, userId, minOomAdj,
false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
- false /* evenPersistent */, false /* setRemoved */, reason);
+ false /* evenPersistent */, false /* setRemoved */, reasonCode,
+ subReason, reason);
}
@GuardedBy("mService")
@@ -2517,7 +2518,8 @@ public final class ProcessList {
@GuardedBy("mService")
final boolean killPackageProcessesLocked(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
- boolean doit, boolean evenPersistent, boolean setRemoved, String reason) {
+ boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode,
+ int subReason, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<>();
// Remove all processes this package may have touched: all with the
@@ -2589,7 +2591,8 @@ public final class ProcessList {
int N = procs.size();
for (int i=0; i<N; i++) {
- removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
+ removeProcessLocked(procs.get(i), callerWillRestart, allowRestart,
+ reasonCode, subReason, reason);
}
killAppZygotesLocked(packageName, appId, userId, false /* force */);
mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
@@ -2598,13 +2601,14 @@ public final class ProcessList {
@GuardedBy("mService")
boolean removeProcessLocked(ProcessRecord app,
- boolean callerWillRestart, boolean allowRestart, String reason) {
- return removeProcessLocked(app, callerWillRestart, allowRestart, reason,
- ApplicationExitInfo.REASON_OTHER);
+ boolean callerWillRestart, boolean allowRestart, int reasonCode, String reason) {
+ return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode,
+ ApplicationExitInfo.SUBREASON_UNKNOWN, reason);
}
- boolean removeProcessLocked(ProcessRecord app,
- boolean callerWillRestart, boolean allowRestart, String reason, int reasonCode) {
+ @GuardedBy("mService")
+ boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart,
+ boolean allowRestart, int reasonCode, int subReason, String reason) {
final String name = app.processName;
final int uid = app.uid;
if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES,
@@ -2640,7 +2644,7 @@ public final class ProcessList {
needRestart = true;
}
}
- app.kill(reason, reasonCode, true);
+ app.kill(reason, reasonCode, subReason, true);
mService.handleAppDiedLocked(app, willRestart, allowRestart);
if (willRestart) {
removeLruProcessLocked(app);
@@ -2838,7 +2842,8 @@ public final class ProcessList {
final int N = procs.size();
for (int i = 0; i < N; i++) {
- removeProcessLocked(procs.get(i), false, true, "kill all background except");
+ removeProcessLocked(procs.get(i), false, true, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_ALL_BG_EXCEPT, "kill all background except");
}
}
@@ -4004,7 +4009,8 @@ public final class ProcessList {
return false;
}
- app.kill(reason, ApplicationExitInfo.REASON_OTHER, true);
+ app.kill(reason, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_IMPERCEPTIBLE, true);
if (!app.isolated) {
mLastProcessKillTimes.put(app.processName, app.uid, SystemClock.uptimeMillis());