Merge "ActivityManager: kill frozen processes receiving sync transactions" into rvc-qpr-dev am: acd04189d9 am: 00523e6c27
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12568351
Change-Id: Ic904787a426b3ebf10f037544aa8a706529b3ab9
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 9660389..8112bb8 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -22,6 +22,7 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.app.ApplicationExitInfo;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
@@ -132,11 +133,15 @@
static final int REPORT_UNFREEZE_MSG = 4;
//TODO:change this static definition into a configurable flag.
- static final int FREEZE_TIMEOUT_MS = 500;
+ static final int FREEZE_TIMEOUT_MS = 10000;
static final int DO_FREEZE = 1;
static final int REPORT_UNFREEZE = 2;
+ // Bitfield values for sync/async transactions reveived by frozen processes
+ static final int SYNC_RECEIVED_WHILE_FROZEN = 1;
+ static final int ASYNC_RECEIVED_WHILE_FROZEN = 2;
+
/**
* This thread must be moved to the system background cpuset.
* If that doesn't happen, it's probably going to draw a lot of power.
@@ -494,6 +499,15 @@
private static native void freezeBinder(int pid, boolean freeze);
/**
+ * Retrieves binder freeze info about a process.
+ * @param pid the pid for which binder freeze info is to be retrieved.
+ *
+ * @throws RuntimeException if the operation could not complete successfully.
+ * @return a bit field reporting the binder freeze info for the process.
+ */
+ private static native int getBinderFreezeInfo(int pid);
+
+ /**
* Determines whether the freezer is supported by this system
*/
public static boolean isFreezerSupported() {
@@ -729,6 +743,37 @@
return;
}
+ boolean processKilled = false;
+
+ try {
+ int freezeInfo = getBinderFreezeInfo(app.pid);
+
+ if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {
+ Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ + " received sync transactions while frozen, killing");
+ app.kill("Sync transaction while in frozen state",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ processKilled = true;
+ }
+
+ if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) {
+ Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ + " received async transactions while frozen");
+ }
+ } catch (Exception e) {
+ Slog.d(TAG_AM, "Unable to query binder frozen info for pid " + app.pid + " "
+ + app.processName + ". Killing it. Exception: " + e);
+ app.kill("Unable to query binder frozen stats",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ processKilled = true;
+ }
+
+ if (processKilled) {
+ return;
+ }
+
long freezeTime = app.freezeUnfreezeTime;
try {
@@ -745,8 +790,12 @@
try {
freezeBinder(app.pid, false);
} catch (RuntimeException e) {
- // TODO: it might be preferable to kill the target pid in this case
- Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName);
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
+ + ". Killing it");
+ app.kill("Unable to unfreeze",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ return;
}
if (DEBUG_FREEZER) {
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 95d4ba7..678308a 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -36,6 +36,9 @@
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+#define SYNC_RECEIVED_WHILE_FROZEN (1)
+#define ASYNC_RECEIVED_WHILE_FROZEN (2)
+
namespace android {
// This performs per-process reclaim on all processes belonging to non-app UIDs.
@@ -99,12 +102,37 @@
}
}
+static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv *env,
+ jobject clazz, jint pid) {
+ bool syncReceived = false, asyncReceived = false;
+
+ int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived);
+
+ if (error < 0) {
+ jniThrowException(env, "java/lang/RuntimeException", strerror(error));
+ }
+
+ jint retVal = 0;
+
+ if(syncReceived) {
+ retVal |= SYNC_RECEIVED_WHILE_FROZEN;;
+ }
+
+ if(asyncReceived) {
+ retVal |= ASYNC_RECEIVED_WHILE_FROZEN;
+ }
+
+ return retVal;
+}
+
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"enableFreezerInternal", "(Z)V",
(void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal},
- {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}
+ {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
+ {"getBinderFreezeInfo", "(I)I",
+ (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo}
};
int register_android_server_am_CachedAppOptimizer(JNIEnv* env)