android_util_EventLog.cpp revision 78158db51029e7dbe160e60af0deb7594bec051d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h"
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h"
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h"
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "cutils/logger.h"
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
246916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor// The size of the tag number comes out of the payload size.
256916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
266916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gCollectionClass;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gCollectionAddID;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gEventClass;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gEventInitID;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gIntegerClass;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gIntegerValueID;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gListClass;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gListItemsID;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gLongClass;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gLongValueID;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gStringClass;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(int tag, int value)
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_util_EventLog_writeEvent_Integer(JNIEnv* env, jobject clazz,
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                     jint tag, jint value)
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android_btWriteLog(tag, EVENT_TYPE_INT, &value, sizeof(value));
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(long tag, long value)
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6095ff2401a9c6f0252aeedfa27ba0a9a5f0d7f55eJim Millerstatic jint android_util_EventLog_writeEvent_Long(JNIEnv* env, jobject clazz,
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                  jint tag, jlong value)
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android_btWriteLog(tag, EVENT_TYPE_LONG, &value, sizeof(value));
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
6862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor *  static native int writeEvent(int tag, String value)
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnorstatic jint android_util_EventLog_writeEvent_String(JNIEnv* env, jobject clazz,
7162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                                                    jint tag, jstring value) {
726916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor    uint8_t buf[MAX_EVENT_PAYLOAD];
7362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor
7462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    // Don't throw NPE -- I feel like it's sort of mean for a logging function
7562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    // to be all crashy if you pass in NULL -- but make the NULL value explicit.
7662136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
7762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    jint len = strlen(str);
7862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    const int max = sizeof(buf) - sizeof(len) - 2;  // Type byte, final newline
7962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    if (len > max) len = max;
8062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor
8162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    buf[0] = EVENT_TYPE_STRING;
8262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    memcpy(&buf[1], &len, sizeof(len));
8362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    memcpy(&buf[1 + sizeof(len)], str, len);
8462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    buf[1 + sizeof(len) + len] = '\n';
8562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor
8662136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    if (value != NULL) env->ReleaseStringUTFChars(value, str);
8762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    return android_bWriteLog(tag, buf, 2 + sizeof(len) + len);
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
9262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor *  static native int writeEvent(long tag, Object... value)
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
9462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnorstatic jint android_util_EventLog_writeEvent_Array(JNIEnv* env, jobject clazz,
9562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                                                   jint tag, jobjectArray value) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (value == NULL) {
9762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        return android_util_EventLog_writeEvent_String(env, clazz, tag, NULL);
9862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    }
9962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor
1006916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor    uint8_t buf[MAX_EVENT_PAYLOAD];
10162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    const size_t max = sizeof(buf) - 1;  // leave room for final newline
10262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    size_t pos = 2;  // Save room for type tag & array count
10362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor
10462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    jsize copied = 0, num = env->GetArrayLength(value);
1056916089e838662b41d902cd9a0d2560b04633ef9Dan Egnor    for (; copied < num && copied < 255; ++copied) {
10662136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        jobject item = env->GetObjectArrayElement(value, copied);
10762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
10862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            if (pos + 1 + sizeof(jint) > max) break;
10962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
11062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            jint len = strlen(str);
11162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
11262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            buf[pos++] = EVENT_TYPE_STRING;
11362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            memcpy(&buf[pos], &len, sizeof(len));
11462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            memcpy(&buf[pos + sizeof(len)], str, len);
11562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            pos += sizeof(len) + len;
11662136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
11762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        } else if (env->IsInstanceOf(item, gIntegerClass)) {
11862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            jint intVal = env->GetIntField(item, gIntegerValueID);
11962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            if (pos + 1 + sizeof(intVal) > max) break;
12062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            buf[pos++] = EVENT_TYPE_INT;
12162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            memcpy(&buf[pos], &intVal, sizeof(intVal));
12262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            pos += sizeof(intVal);
12362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        } else if (env->IsInstanceOf(item, gLongClass)) {
12462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            jlong longVal = env->GetLongField(item, gLongValueID);
12562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            if (pos + 1 + sizeof(longVal) > max) break;
12662136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            buf[pos++] = EVENT_TYPE_LONG;
12762136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            memcpy(&buf[pos], &longVal, sizeof(longVal));
12862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            pos += sizeof(longVal);
12962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        } else {
13062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            jniThrowException(env,
13162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                    "java/lang/IllegalArgumentException",
13262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                    "Invalid payload item type");
13362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor            return -1;
13462136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        }
13562136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor        env->DeleteLocalRef(item);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13862136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    buf[0] = EVENT_TYPE_LIST;
13962136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    buf[1] = copied;
14062136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    buf[pos++] = '\n';
14162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor    return android_bWriteLog(tag, buf, pos);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native void readEvents(int[] tags, Collection<Event> output)
14795ff2401a9c6f0252aeedfa27ba0a9a5f0d7f55eJim Miller *
14895ff2401a9c6f0252aeedfa27ba0a9a5f0d7f55eJim Miller *  Reads events from the event log, typically /dev/log/events
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz,
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                             jintArray tags,
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                             jobject out) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tags == NULL || out == NULL) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/NullPointerException", NULL);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd = open("/dev/" LOGGER_LOG_EVENTS, O_RDONLY | O_NONBLOCK);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0) {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowIOException(env, errno);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jsize tagLength = env->GetArrayLength(tags);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint *tagValues = env->GetIntArrayElements(tags, NULL);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t buf[LOGGER_ENTRY_MAX_LEN];
16878158db51029e7dbe160e60af0deb7594bec051dDan Egnor    struct timeval timeout = {0, 0};
16978158db51029e7dbe160e60af0deb7594bec051dDan Egnor    fd_set readset;
17078158db51029e7dbe160e60af0deb7594bec051dDan Egnor    FD_ZERO(&readset);
17178158db51029e7dbe160e60af0deb7594bec051dDan Egnor
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
17378158db51029e7dbe160e60af0deb7594bec051dDan Egnor        // Use a short select() to try to avoid problems hanging on read().
17478158db51029e7dbe160e60af0deb7594bec051dDan Egnor        // This means we block for 5ms at the end of the log -- oh well.
17578158db51029e7dbe160e60af0deb7594bec051dDan Egnor        timeout.tv_usec = 5000;
17678158db51029e7dbe160e60af0deb7594bec051dDan Egnor        FD_SET(fd, &readset);
17778158db51029e7dbe160e60af0deb7594bec051dDan Egnor        int r = select(fd + 1, &readset, NULL, NULL, &timeout);
17878158db51029e7dbe160e60af0deb7594bec051dDan Egnor        if (r == 0) {
17978158db51029e7dbe160e60af0deb7594bec051dDan Egnor            break;  // no more events
18078158db51029e7dbe160e60af0deb7594bec051dDan Egnor        } else if (r < 0 && errno == EINTR) {
18178158db51029e7dbe160e60af0deb7594bec051dDan Egnor            continue;  // interrupted by signal, try again
18278158db51029e7dbe160e60af0deb7594bec051dDan Egnor        } else if (r < 0) {
18378158db51029e7dbe160e60af0deb7594bec051dDan Egnor            jniThrowIOException(env, errno);  // Will throw on return
18478158db51029e7dbe160e60af0deb7594bec051dDan Egnor            break;
18578158db51029e7dbe160e60af0deb7594bec051dDan Egnor        }
18678158db51029e7dbe160e60af0deb7594bec051dDan Egnor
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int len = read(fd, buf, sizeof(buf));
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len == 0 || (len < 0 && errno == EAGAIN)) {
18978158db51029e7dbe160e60af0deb7594bec051dDan Egnor            break;  // no more events
19078158db51029e7dbe160e60af0deb7594bec051dDan Egnor        } else if (len < 0 && errno == EINTR) {
19178158db51029e7dbe160e60af0deb7594bec051dDan Egnor            continue;  // interrupted by signal, try again
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (len < 0) {
19378158db51029e7dbe160e60af0deb7594bec051dDan Egnor            jniThrowIOException(env, errno);  // Will throw on return
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if ((size_t) len < sizeof(logger_entry) + sizeof(int32_t)) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jniThrowException(env, "java/io/IOException", "Event too short");
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        logger_entry* entry = (logger_entry*) buf;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int32_t tag = * (int32_t*) (buf + sizeof(*entry));
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int found = 0;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; !found && i < tagLength; ++i) {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            found = (tag == tagValues[i]);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (found) {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jsize len = sizeof(*entry) + entry->len;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jbyteArray array = env->NewByteArray(len);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == NULL) break;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jbyte *bytes = env->GetByteArrayElements(array, NULL);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            memcpy(bytes, buf, len);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->ReleaseByteArrayElements(array, bytes, 0);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jobject event = env->NewObject(gEventClass, gEventInitID, array);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event == NULL) break;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->CallBooleanMethod(out, gCollectionAddID, event);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->DeleteLocalRef(event);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->DeleteLocalRef(array);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(fd);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseIntArrayElements(tags, tagValues, 0);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23095ff2401a9c6f0252aeedfa27ba0a9a5f0d7f55eJim Miller/*
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gRegisterMethods[] = {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* name, signature, funcPtr */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent",
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      "(ILjava/lang/String;)I",
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      (void*) android_util_EventLog_writeEvent_String
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    },
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent",
24262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor      "(I[Ljava/lang/Object;)I",
24362136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor      (void*) android_util_EventLog_writeEvent_Array
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    },
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "readEvents",
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      "([ILjava/util/Collection;)V",
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      (void*) android_util_EventLog_readEvents
24895ff2401a9c6f0252aeedfa27ba0a9a5f0d7f55eJim Miller    },
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { const char *name; jclass *clazz; } gClasses[] = {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "android/util/EventLog$Event", &gEventClass },
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/Integer", &gIntegerClass },
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/Long", &gLongClass },
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/String", &gStringClass },
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/util/Collection", &gCollectionClass },
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gIntegerClass, "value", "I", &gIntegerValueID },
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gLongClass, "value", "J", &gLongValueID },
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gEventClass, "<init>", "([B)V", &gEventInitID },
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_util_EventLog(JNIEnv* env) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gClasses); ++i) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jclass clazz = env->FindClass(gClasses[i].name);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (clazz == NULL) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find class: %s\n", gClasses[i].name);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gClasses[i].clazz = (jclass) env->NewGlobalRef(clazz);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gFields); ++i) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gFields[i].id = env->GetFieldID(
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *gFields[i].c, gFields[i].name, gFields[i].ft);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (*gFields[i].id == NULL) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find field: %s\n", gFields[i].name);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gMethods); ++i) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gMethods[i].id = env->GetMethodID(
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (*gMethods[i].id == NULL) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find method: %s\n", gMethods[i].name);
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return AndroidRuntime::registerNativeMethods(
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env,
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "android/util/EventLog",
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            gRegisterMethods, NELEM(gRegisterMethods));
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
304