Loading core/java/android/os/Process.java +12 −0 Original line number Original line Diff line number Diff line Loading @@ -1462,6 +1462,18 @@ public class Process { */ */ public static final native int killProcessGroup(int uid, int pid); public static final native int killProcessGroup(int uid, int pid); /** * Freeze the cgroup for the given UID. * This cgroup may contain child cgroups which will also be frozen. If this cgroup or its * children contain processes with Binder interfaces, those interfaces should be frozen before * the cgroup to avoid blocking synchronous callers indefinitely. * * @param uid The UID to be frozen * @param freeze true = freeze; false = unfreeze * @hide */ public static final native void freezeCgroupUid(int uid, boolean freeze); /** /** * Remove all process groups. Expected to be called when ActivityManager * Remove all process groups. Expected to be called when ActivityManager * is restarted. * is restarted. Loading core/jni/android_util_Process.cpp +15 −0 Original line number Original line Diff line number Diff line Loading @@ -1252,6 +1252,20 @@ static jint android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, j return fd; return fd; } } void android_os_Process_freezeCgroupUID(JNIEnv* env, jobject clazz, jint uid, jboolean freeze) { bool success = true; if (freeze) { success = SetUserProfiles(uid, {"Frozen"}); } else { success = SetUserProfiles(uid, {"Unfrozen"}); } if (!success) { jniThrowRuntimeException(env, "Could not apply user profile"); } } static const JNINativeMethod methods[] = { static const JNINativeMethod methods[] = { {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName}, {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName}, {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName}, {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName}, Loading Loading @@ -1293,6 +1307,7 @@ static const JNINativeMethod methods[] = { {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup}, {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup}, {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups}, {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups}, {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen}, {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen}, {"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID}, }; }; int register_android_os_Process(JNIEnv* env) int register_android_os_Process(JNIEnv* env) Loading services/core/java/com/android/server/am/CachedAppOptimizer.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,8 @@ public final class CachedAppOptimizer { private static final String ATRACE_COMPACTION_TRACK = "Compaction"; private static final String ATRACE_COMPACTION_TRACK = "Compaction"; private static final int FREEZE_BINDER_TIMEOUT_MS = 100; // Defaults for phenotype flags. // Defaults for phenotype flags. @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false; @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false; @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true; @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true; Loading Loading @@ -927,11 +929,13 @@ public final class CachedAppOptimizer { * @param pid the target pid for which binder transactions are to be frozen * @param pid the target pid for which binder transactions are to be frozen * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze * binder for the specificed pid. * binder for the specificed pid. * @param timeoutMs the timeout in milliseconds to wait for the binder interface to freeze * before giving up. * * * @throws RuntimeException in case a flush/freeze operation could not complete successfully. * @throws RuntimeException in case a flush/freeze operation could not complete successfully. * @return 0 if success, or -EAGAIN indicating there's pending transaction. * @return 0 if success, or -EAGAIN indicating there's pending transaction. */ */ private static native int freezeBinder(int pid, boolean freeze); public static native int freezeBinder(int pid, boolean freeze, int timeoutMs); /** /** * Retrieves binder freeze info about a process. * Retrieves binder freeze info about a process. Loading Loading @@ -1298,7 +1302,7 @@ public final class CachedAppOptimizer { long freezeTime = opt.getFreezeUnfreezeTime(); long freezeTime = opt.getFreezeUnfreezeTime(); try { try { freezeBinder(pid, false); freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS); } catch (RuntimeException e) { } catch (RuntimeException e) { Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName + ". Killing it"); + ". Killing it"); Loading Loading @@ -1930,7 +1934,7 @@ public final class CachedAppOptimizer { // Freeze binder interface before the process, to flush any // Freeze binder interface before the process, to flush any // transactions that might be pending. // transactions that might be pending. try { try { if (freezeBinder(pid, true) != 0) { if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) { rescheduleFreeze(proc, "outstanding txns"); rescheduleFreeze(proc, "outstanding txns"); return; return; } } Loading services/core/java/com/android/server/am/ProcessList.java +60 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static android.os.Process.getFreeMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.killProcessQuiet; import static android.os.Process.killProcessQuiet; import static android.os.Process.startWebView; import static android.os.Process.startWebView; import static android.system.OsConstants.*; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK; Loading Loading @@ -2705,6 +2706,50 @@ public final class ProcessList { } } } } private static boolean freezePackageCgroup(int packageUID, boolean freeze) { try { Process.freezeCgroupUid(packageUID, freeze); } catch (RuntimeException e) { final String logtxt = freeze ? "freeze" : "unfreeze"; Slog.e(TAG, "Unable to " + logtxt + " cgroup uid: " + packageUID + ": " + e); return false; } return true; } private static void freezeBinderAndPackageCgroup(ArrayList<Pair<ProcessRecord, Boolean>> procs, int packageUID) { // Freeze all binder processes under the target UID (whose cgroup is about to be frozen). // Since we're going to kill these, we don't need to unfreze them later. // The procs list may not include all processes under the UID cgroup, but unincluded // processes (forks) should not be Binder users. int N = procs.size(); for (int i = 0; i < N; i++) { final int uid = procs.get(i).first.uid; final int pid = procs.get(i).first.getPid(); int nRetries = 0; // We only freeze the cgroup of the target package, so we do not need to freeze the // Binder interfaces of dependant processes in other UIDs. if (pid > 0 && uid == packageUID) { try { int rc; do { rc = CachedAppOptimizer.freezeBinder(pid, true, 10 /* timeout_ms */); } while (rc == -EAGAIN && nRetries++ < 1); if (rc != 0) Slog.e(TAG, "Unable to freeze binder for " + pid + ": " + rc); } catch (RuntimeException e) { Slog.e(TAG, "Unable to freeze binder for " + pid + ": " + e); } } } // We freeze the entire UID (parent) cgroup so that newly-specialized processes also freeze // despite being added to a new child cgroup. The cgroups of package dependant processes are // not frozen, since it's possible this would freeze processes with no dependency on the // package being killed here. freezePackageCgroup(packageUID, true); } @GuardedBy({"mService", "mProcLock"}) @GuardedBy({"mService", "mProcLock"}) boolean killPackageProcessesLSP(String packageName, int appId, boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, Loading Loading @@ -2757,7 +2802,7 @@ public final class ProcessList { boolean shouldAllowRestart = false; boolean shouldAllowRestart = false; // If no package is specified, we call all processes under the // If no package is specified, we call all processes under the // give user id. // given user id. if (packageName == null) { if (packageName == null) { if (userId != UserHandle.USER_ALL && app.userId != userId) { if (userId != UserHandle.USER_ALL && app.userId != userId) { continue; continue; Loading Loading @@ -2800,14 +2845,18 @@ public final class ProcessList { } } } } final int packageUID = UserHandle.getUid(userId, appId); freezeBinderAndPackageCgroup(procs, packageUID); int N = procs.size(); int N = procs.size(); for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { final Pair<ProcessRecord, Boolean> proc = procs.get(i); final Pair<ProcessRecord, Boolean> proc = procs.get(i); removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, reasonCode, subReason, reason); reasonCode, subReason, reason, false /* async */); } } killAppZygotesLocked(packageName, appId, userId, false /* force */); killAppZygotesLocked(packageName, appId, userId, false /* force */); mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END); mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END); freezePackageCgroup(packageUID, false); return N > 0; return N > 0; } } Loading @@ -2815,12 +2864,19 @@ public final class ProcessList { boolean removeProcessLocked(ProcessRecord app, boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, String reason) { boolean callerWillRestart, boolean allowRestart, int reasonCode, String reason) { return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, reason); ApplicationExitInfo.SUBREASON_UNKNOWN, reason, true); } } @GuardedBy("mService") @GuardedBy("mService") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, int subReason, String reason) { boolean allowRestart, int reasonCode, int subReason, String reason) { return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, subReason, reason, true); } @GuardedBy("mService") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, int subReason, String reason, boolean async) { final String name = app.processName; final String name = app.processName; final int uid = app.uid; final int uid = app.uid; if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, Loading Loading @@ -2857,7 +2913,7 @@ public final class ProcessList { needRestart = true; needRestart = true; } } } } app.killLocked(reason, reasonCode, subReason, true); app.killLocked(reason, reasonCode, subReason, true, async); mService.handleAppDiedLocked(app, pid, willRestart, allowRestart, mService.handleAppDiedLocked(app, pid, willRestart, allowRestart, false /* fromBinderDied */); false /* fromBinderDied */); if (willRestart) { if (willRestart) { Loading services/core/java/com/android/server/am/ProcessRecord.java +16 −3 Original line number Original line Diff line number Diff line Loading @@ -1057,18 +1057,30 @@ class ProcessRecord implements WindowProcessListener { @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, boolean noisy) { void killLocked(String reason, @Reason int reasonCode, boolean noisy) { killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy); killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy, true); } } @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { boolean noisy) { killLocked(reason, reason, reasonCode, subReason, noisy); killLocked(reason, reason, reasonCode, subReason, noisy, true); } } @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, String description, @Reason int reasonCode, void killLocked(String reason, String description, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { @SubReason int subReason, boolean noisy) { killLocked(reason, description, reasonCode, subReason, noisy, true); } @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy, boolean asyncKPG) { killLocked(reason, reason, reasonCode, subReason, noisy, asyncKPG); } @GuardedBy("mService") void killLocked(String reason, String description, @Reason int reasonCode, @SubReason int subReason, boolean noisy, boolean asyncKPG) { if (!mKilledByAm) { if (!mKilledByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (reasonCode == ApplicationExitInfo.REASON_ANR if (reasonCode == ApplicationExitInfo.REASON_ANR Loading @@ -1085,7 +1097,8 @@ class ProcessRecord implements WindowProcessListener { EventLog.writeEvent(EventLogTags.AM_KILL, EventLog.writeEvent(EventLogTags.AM_KILL, userId, mPid, processName, mState.getSetAdj(), reason); userId, mPid, processName, mState.getSetAdj(), reason); Process.killProcessQuiet(mPid); Process.killProcessQuiet(mPid); ProcessList.killProcessGroup(uid, mPid); if (asyncKPG) ProcessList.killProcessGroup(uid, mPid); else Process.killProcessGroup(uid, mPid); } else { } else { mPendingStart = false; mPendingStart = false; } } Loading Loading
core/java/android/os/Process.java +12 −0 Original line number Original line Diff line number Diff line Loading @@ -1462,6 +1462,18 @@ public class Process { */ */ public static final native int killProcessGroup(int uid, int pid); public static final native int killProcessGroup(int uid, int pid); /** * Freeze the cgroup for the given UID. * This cgroup may contain child cgroups which will also be frozen. If this cgroup or its * children contain processes with Binder interfaces, those interfaces should be frozen before * the cgroup to avoid blocking synchronous callers indefinitely. * * @param uid The UID to be frozen * @param freeze true = freeze; false = unfreeze * @hide */ public static final native void freezeCgroupUid(int uid, boolean freeze); /** /** * Remove all process groups. Expected to be called when ActivityManager * Remove all process groups. Expected to be called when ActivityManager * is restarted. * is restarted. Loading
core/jni/android_util_Process.cpp +15 −0 Original line number Original line Diff line number Diff line Loading @@ -1252,6 +1252,20 @@ static jint android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, j return fd; return fd; } } void android_os_Process_freezeCgroupUID(JNIEnv* env, jobject clazz, jint uid, jboolean freeze) { bool success = true; if (freeze) { success = SetUserProfiles(uid, {"Frozen"}); } else { success = SetUserProfiles(uid, {"Unfrozen"}); } if (!success) { jniThrowRuntimeException(env, "Could not apply user profile"); } } static const JNINativeMethod methods[] = { static const JNINativeMethod methods[] = { {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName}, {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName}, {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName}, {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName}, Loading Loading @@ -1293,6 +1307,7 @@ static const JNINativeMethod methods[] = { {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup}, {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup}, {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups}, {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups}, {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen}, {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen}, {"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID}, }; }; int register_android_os_Process(JNIEnv* env) int register_android_os_Process(JNIEnv* env) Loading
services/core/java/com/android/server/am/CachedAppOptimizer.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,8 @@ public final class CachedAppOptimizer { private static final String ATRACE_COMPACTION_TRACK = "Compaction"; private static final String ATRACE_COMPACTION_TRACK = "Compaction"; private static final int FREEZE_BINDER_TIMEOUT_MS = 100; // Defaults for phenotype flags. // Defaults for phenotype flags. @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false; @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false; @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true; @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true; Loading Loading @@ -927,11 +929,13 @@ public final class CachedAppOptimizer { * @param pid the target pid for which binder transactions are to be frozen * @param pid the target pid for which binder transactions are to be frozen * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze * binder for the specificed pid. * binder for the specificed pid. * @param timeoutMs the timeout in milliseconds to wait for the binder interface to freeze * before giving up. * * * @throws RuntimeException in case a flush/freeze operation could not complete successfully. * @throws RuntimeException in case a flush/freeze operation could not complete successfully. * @return 0 if success, or -EAGAIN indicating there's pending transaction. * @return 0 if success, or -EAGAIN indicating there's pending transaction. */ */ private static native int freezeBinder(int pid, boolean freeze); public static native int freezeBinder(int pid, boolean freeze, int timeoutMs); /** /** * Retrieves binder freeze info about a process. * Retrieves binder freeze info about a process. Loading Loading @@ -1298,7 +1302,7 @@ public final class CachedAppOptimizer { long freezeTime = opt.getFreezeUnfreezeTime(); long freezeTime = opt.getFreezeUnfreezeTime(); try { try { freezeBinder(pid, false); freezeBinder(pid, false, FREEZE_BINDER_TIMEOUT_MS); } catch (RuntimeException e) { } catch (RuntimeException e) { Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName + ". Killing it"); + ". Killing it"); Loading Loading @@ -1930,7 +1934,7 @@ public final class CachedAppOptimizer { // Freeze binder interface before the process, to flush any // Freeze binder interface before the process, to flush any // transactions that might be pending. // transactions that might be pending. try { try { if (freezeBinder(pid, true) != 0) { if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) { rescheduleFreeze(proc, "outstanding txns"); rescheduleFreeze(proc, "outstanding txns"); return; return; } } Loading
services/core/java/com/android/server/am/ProcessList.java +60 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static android.os.Process.getFreeMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.killProcessQuiet; import static android.os.Process.killProcessQuiet; import static android.os.Process.startWebView; import static android.os.Process.startWebView; import static android.system.OsConstants.*; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK; Loading Loading @@ -2705,6 +2706,50 @@ public final class ProcessList { } } } } private static boolean freezePackageCgroup(int packageUID, boolean freeze) { try { Process.freezeCgroupUid(packageUID, freeze); } catch (RuntimeException e) { final String logtxt = freeze ? "freeze" : "unfreeze"; Slog.e(TAG, "Unable to " + logtxt + " cgroup uid: " + packageUID + ": " + e); return false; } return true; } private static void freezeBinderAndPackageCgroup(ArrayList<Pair<ProcessRecord, Boolean>> procs, int packageUID) { // Freeze all binder processes under the target UID (whose cgroup is about to be frozen). // Since we're going to kill these, we don't need to unfreze them later. // The procs list may not include all processes under the UID cgroup, but unincluded // processes (forks) should not be Binder users. int N = procs.size(); for (int i = 0; i < N; i++) { final int uid = procs.get(i).first.uid; final int pid = procs.get(i).first.getPid(); int nRetries = 0; // We only freeze the cgroup of the target package, so we do not need to freeze the // Binder interfaces of dependant processes in other UIDs. if (pid > 0 && uid == packageUID) { try { int rc; do { rc = CachedAppOptimizer.freezeBinder(pid, true, 10 /* timeout_ms */); } while (rc == -EAGAIN && nRetries++ < 1); if (rc != 0) Slog.e(TAG, "Unable to freeze binder for " + pid + ": " + rc); } catch (RuntimeException e) { Slog.e(TAG, "Unable to freeze binder for " + pid + ": " + e); } } } // We freeze the entire UID (parent) cgroup so that newly-specialized processes also freeze // despite being added to a new child cgroup. The cgroups of package dependant processes are // not frozen, since it's possible this would freeze processes with no dependency on the // package being killed here. freezePackageCgroup(packageUID, true); } @GuardedBy({"mService", "mProcLock"}) @GuardedBy({"mService", "mProcLock"}) boolean killPackageProcessesLSP(String packageName, int appId, boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, Loading Loading @@ -2757,7 +2802,7 @@ public final class ProcessList { boolean shouldAllowRestart = false; boolean shouldAllowRestart = false; // If no package is specified, we call all processes under the // If no package is specified, we call all processes under the // give user id. // given user id. if (packageName == null) { if (packageName == null) { if (userId != UserHandle.USER_ALL && app.userId != userId) { if (userId != UserHandle.USER_ALL && app.userId != userId) { continue; continue; Loading Loading @@ -2800,14 +2845,18 @@ public final class ProcessList { } } } } final int packageUID = UserHandle.getUid(userId, appId); freezeBinderAndPackageCgroup(procs, packageUID); int N = procs.size(); int N = procs.size(); for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { final Pair<ProcessRecord, Boolean> proc = procs.get(i); final Pair<ProcessRecord, Boolean> proc = procs.get(i); removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, reasonCode, subReason, reason); reasonCode, subReason, reason, false /* async */); } } killAppZygotesLocked(packageName, appId, userId, false /* force */); killAppZygotesLocked(packageName, appId, userId, false /* force */); mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END); mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END); freezePackageCgroup(packageUID, false); return N > 0; return N > 0; } } Loading @@ -2815,12 +2864,19 @@ public final class ProcessList { boolean removeProcessLocked(ProcessRecord app, boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, String reason) { boolean callerWillRestart, boolean allowRestart, int reasonCode, String reason) { return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, reason); ApplicationExitInfo.SUBREASON_UNKNOWN, reason, true); } } @GuardedBy("mService") @GuardedBy("mService") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, int subReason, String reason) { boolean allowRestart, int reasonCode, int subReason, String reason) { return removeProcessLocked(app, callerWillRestart, allowRestart, reasonCode, subReason, reason, true); } @GuardedBy("mService") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, int reasonCode, int subReason, String reason, boolean async) { final String name = app.processName; final String name = app.processName; final int uid = app.uid; final int uid = app.uid; if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, Loading Loading @@ -2857,7 +2913,7 @@ public final class ProcessList { needRestart = true; needRestart = true; } } } } app.killLocked(reason, reasonCode, subReason, true); app.killLocked(reason, reasonCode, subReason, true, async); mService.handleAppDiedLocked(app, pid, willRestart, allowRestart, mService.handleAppDiedLocked(app, pid, willRestart, allowRestart, false /* fromBinderDied */); false /* fromBinderDied */); if (willRestart) { if (willRestart) { Loading
services/core/java/com/android/server/am/ProcessRecord.java +16 −3 Original line number Original line Diff line number Diff line Loading @@ -1057,18 +1057,30 @@ class ProcessRecord implements WindowProcessListener { @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, boolean noisy) { void killLocked(String reason, @Reason int reasonCode, boolean noisy) { killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy); killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy, true); } } @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { boolean noisy) { killLocked(reason, reason, reasonCode, subReason, noisy); killLocked(reason, reason, reasonCode, subReason, noisy, true); } } @GuardedBy("mService") @GuardedBy("mService") void killLocked(String reason, String description, @Reason int reasonCode, void killLocked(String reason, String description, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { @SubReason int subReason, boolean noisy) { killLocked(reason, description, reasonCode, subReason, noisy, true); } @GuardedBy("mService") void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy, boolean asyncKPG) { killLocked(reason, reason, reasonCode, subReason, noisy, asyncKPG); } @GuardedBy("mService") void killLocked(String reason, String description, @Reason int reasonCode, @SubReason int subReason, boolean noisy, boolean asyncKPG) { if (!mKilledByAm) { if (!mKilledByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (reasonCode == ApplicationExitInfo.REASON_ANR if (reasonCode == ApplicationExitInfo.REASON_ANR Loading @@ -1085,7 +1097,8 @@ class ProcessRecord implements WindowProcessListener { EventLog.writeEvent(EventLogTags.AM_KILL, EventLog.writeEvent(EventLogTags.AM_KILL, userId, mPid, processName, mState.getSetAdj(), reason); userId, mPid, processName, mState.getSetAdj(), reason); Process.killProcessQuiet(mPid); Process.killProcessQuiet(mPid); ProcessList.killProcessGroup(uid, mPid); if (asyncKPG) ProcessList.killProcessGroup(uid, mPid); else Process.killProcessGroup(uid, mPid); } else { } else { mPendingStart = false; mPendingStart = false; } } Loading