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

Commit 3857681e authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am a7e3a1e0: Merge "Include important native processes in watchdog stacks." into jb-dev

* commit 'a7e3a1e0':
  Include important native processes in watchdog stacks.
parents 8f3523b0 a7e3a1e0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1325,6 +1325,13 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
        }
    }

    /**
     * Have the stack traces of the given native process dumped to the
     * specified file.  Will be appended to the file.
     * @hide
     */
    public static native void dumpNativeBacktraceToFile(int pid, String file);

    /**
     * Return a String describing the calling method and location at a particular stack depth.
     * @param callStack the Thread stack 
+3 −0
Original line number Diff line number Diff line
@@ -933,6 +933,9 @@ public class Process {
    public static final native boolean parseProcLine(byte[] buffer, int startIndex, 
            int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats);

    /** @hide */
    public static final native int[] getPidsForCommands(String[] cmds);

    /**
     * Gets the total Pss value for a given process, in bytes.
     * 
+34 −0
Original line number Diff line number Diff line
@@ -17,8 +17,11 @@
#define LOG_TAG "android.os.Debug"
#include "JNIHelp.h"
#include "jni.h"
#include <utils/String8.h>
#include "utils/misc.h"
#include "cutils/debugger.h"

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -538,6 +541,35 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
}


static void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject clazz,
    jint pid, jstring fileName)
{
    if (fileName == NULL) {
        jniThrowNullPointerException(env, NULL);
        return;
    }
    const jchar* str = env->GetStringCritical(fileName, 0);
    String8 fileName8;
    if (str) {
        fileName8 = String8(str, env->GetStringLength(fileName));
        env->ReleaseStringCritical(fileName, str);
    }

    int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666);  /* -rw-rw-rw- */
    if (fd < 0) {
        fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
        return;
    }

    if (lseek(fd, 0, SEEK_END) < 0) {
        fprintf(stderr, "lseek: %s\n", strerror(errno));
    } else {
        dump_backtrace_to_file(pid, fd);
    }

    close(fd);
}

/*
 * JNI registration.
 */
@@ -569,6 +601,8 @@ static JNINativeMethod gMethods[] = {
            (void*)android_os_Debug_getProxyObjectCount },
    { "getBinderDeathObjectCount", "()I",
            (void*)android_os_Debug_getDeathObjectCount },
    { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
            (void*)android_os_Debug_dumpNativeBacktraceToFile },
};

int register_android_os_Debug(JNIEnv *env)
+88 −0
Original line number Diff line number Diff line
@@ -892,6 +892,93 @@ static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid)
    return pss * 1024;
}

jintArray android_os_Process_getPidsForCommands(JNIEnv* env, jobject clazz,
        jobjectArray commandNames)
{
    if (commandNames == NULL) {
        jniThrowNullPointerException(env, NULL);
        return NULL;
    }

    Vector<String8> commands;

    jsize count = env->GetArrayLength(commandNames);

    for (int i=0; i<count; i++) {
        jobject obj = env->GetObjectArrayElement(commandNames, i);
        if (obj != NULL) {
            const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
            if (str8 == NULL) {
                jniThrowNullPointerException(env, "Element in commandNames");
                return NULL;
            }
            commands.add(String8(str8));
            env->ReleaseStringUTFChars((jstring)obj, str8);
        } else {
            jniThrowNullPointerException(env, "Element in commandNames");
            return NULL;
        }
    }

    Vector<jint> pids;

    DIR *proc = opendir("/proc");
    if (proc == NULL) {
        fprintf(stderr, "/proc: %s\n", strerror(errno));
        return NULL;
    }

    struct dirent *d;
    while ((d = readdir(proc))) {
        int pid = atoi(d->d_name);
        if (pid <= 0) continue;

        char path[PATH_MAX];
        char data[PATH_MAX];
        snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);

        int fd = open(path, O_RDONLY);
        if (fd < 0) {
            continue;
        }
        const int len = read(fd, data, sizeof(data)-1);
        close(fd);

        if (len < 0) {
            continue;
        }
        data[len] = 0;

        for (int i=0; i<len; i++) {
            if (data[i] == ' ') {
                data[i] = 0;
                break;
            }
        }

        for (size_t i=0; i<commands.size(); i++) {
            if (commands[i] == data) {
                pids.add(pid);
                break;
            }
        }
    }

    closedir(proc);

    jintArray pidArray = env->NewIntArray(pids.size());
    if (pidArray == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return NULL;
    }

    if (pids.size() > 0) {
        env->SetIntArrayRegion(pidArray, 0, pids.size(), pids.array());
    }

    return pidArray;
}

static const JNINativeMethod methods[] = {
    {"myPid",       "()I", (void*)android_os_Process_myPid},
    {"myTid",       "()I", (void*)android_os_Process_myTid},
@@ -919,6 +1006,7 @@ static const JNINativeMethod methods[] = {
    {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
    {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
    {"getPss", "(I)J", (void*)android_os_Process_getPss},
    {"getPidsForCommands", "([Ljava/lang/String;)[I", (void*)android_os_Process_getPidsForCommands},
    //{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
};

+9 −2
Original line number Diff line number Diff line
@@ -67,6 +67,12 @@ public class Watchdog extends Thread {

    static final String REBOOT_ACTION = "com.android.service.Watchdog.REBOOT";

    static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
        "/system/bin/mediaserver",
        "/system/bin/sdcard",
        "/system/bin/surfaceflinger"
    };

    static Watchdog sWatchdog;

    /* This handler will be used to post message back onto the main thread */
@@ -414,7 +420,8 @@ public class Watchdog extends Thread {
                    // trace and wait another half.
                    ArrayList<Integer> pids = new ArrayList<Integer>();
                    pids.add(Process.myPid());
                    ActivityManagerService.dumpStackTraces(true, pids, null, null);
                    ActivityManagerService.dumpStackTraces(true, pids, null, null,
                            NATIVE_STACKS_OF_INTEREST);
                    waitedHalf = true;
                    continue;
                }
@@ -434,7 +441,7 @@ public class Watchdog extends Thread {
            // Pass !waitedHalf so that just in case we somehow wind up here without having
            // dumped the halfway stacks, we properly re-initialize the trace file.
            final File stack = ActivityManagerService.dumpStackTraces(
                    !waitedHalf, pids, null, null);
                    !waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);

            // Give some extra time to make sure the stack traces get written.
            // The system's been hanging for a minute, another second or two won't hurt much.
Loading