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

Commit acd04189 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "ActivityManager: kill frozen processes receiving sync transactions" into rvc-qpr-dev

parents 4336e7ca 5b5fdb80
Loading
Loading
Loading
Loading
+52 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;

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 @@ public final class CachedAppOptimizer {
    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.
@@ -493,6 +498,15 @@ public final class CachedAppOptimizer {
     */
    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
     */
@@ -729,6 +743,37 @@ public final class CachedAppOptimizer {
            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 @@ public final class CachedAppOptimizer {
            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) {
+29 −1
Original line number Diff line number Diff line
@@ -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 void com_android_server_am_CachedAppOptimizer_freezeBinder(
    }
}

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)