android_util_EventLog.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define END_DELIMITER '\n'
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define INT_BUFFER_SIZE (sizeof(jbyte)+sizeof(jint)+sizeof(END_DELIMITER))
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LONG_BUFFER_SIZE (sizeof(jbyte)+sizeof(jlong)+sizeof(END_DELIMITER))
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define INITAL_BUFFER_CAPACITY 256
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAX(a,b) ((a>b)?a:b)
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gCollectionClass;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gCollectionAddID;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gEventClass;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gEventInitID;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gIntegerClass;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gIntegerValueID;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gListClass;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gListItemsID;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gLongClass;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gLongValueID;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gStringClass;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct ByteBuf {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t capacity;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t* buf;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ByteBuf(size_t initSize) {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf = (uint8_t*)malloc(initSize);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len = 0;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        capacity = initSize;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~ByteBuf() {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        free(buf);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool ensureExtraCapacity(size_t extra) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t spaceNeeded = len + extra;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (spaceNeeded > capacity) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t newCapacity = MAX(spaceNeeded, 2 * capacity);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            void* newBuf = realloc(buf, newCapacity);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (newBuf == NULL) {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            capacity = newCapacity;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buf = (uint8_t*)newBuf;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void putIntEvent(jint value) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool succeeded = ensureExtraCapacity(INT_BUFFER_SIZE);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf[len++] = EVENT_TYPE_INT;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf+len, &value, sizeof(jint));
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len += sizeof(jint);
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void putByte(uint8_t value) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool succeeded = ensureExtraCapacity(sizeof(uint8_t));
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf[len++] = value;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void putLongEvent(jlong value) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool succeeded = ensureExtraCapacity(LONG_BUFFER_SIZE);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf[len++] = EVENT_TYPE_LONG;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf+len, &value, sizeof(jlong));
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len += sizeof(jlong);
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void putStringEvent(JNIEnv* env, jstring value) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* strValue = env->GetStringUTFChars(value, NULL);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t strLen = strlen(strValue); //env->GetStringUTFLength(value);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool succeeded = ensureExtraCapacity(1 + sizeof(uint32_t) + strLen);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf[len++] = EVENT_TYPE_STRING;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf+len, &strLen, sizeof(uint32_t));
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len += sizeof(uint32_t);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf+len, strValue, strLen);
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->ReleaseStringUTFChars(value, strValue);
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len += strLen;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void putList(JNIEnv* env, jobject list) {
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jobjectArray items = (jobjectArray) env->GetObjectField(list, gListItemsID);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (items == NULL) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jniThrowException(env, "java/lang/NullPointerException", NULL);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jsize numItems = env->GetArrayLength(items);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        putByte(EVENT_TYPE_LIST);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        putByte(numItems);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We'd like to call GetPrimitveArrayCritical() but that might
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // not be safe since we're going to be doing some I/O
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < numItems; i++) {
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jobject item = env->GetObjectArrayElement(items, i);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (env->IsInstanceOf(item, gIntegerClass)) {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                jint intVal = env->GetIntField(item, gIntegerValueID);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                putIntEvent(intVal);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (env->IsInstanceOf(item, gLongClass)) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                jlong longVal = env->GetLongField(item, gLongValueID);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                putLongEvent(longVal);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (env->IsInstanceOf(item, gStringClass)) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                putStringEvent(env, (jstring)item);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (env->IsInstanceOf(item, gListClass)) {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                putList(env, item);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                jniThrowException(
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        env,
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "java/lang/IllegalArgumentException",
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Attempt to log an illegal item type.");
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->DeleteLocalRef(item);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->DeleteLocalRef(items);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(int tag, int value)
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_util_EventLog_writeEvent_Integer(JNIEnv* env, jobject clazz,
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                     jint tag, jint value)
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android_btWriteLog(tag, EVENT_TYPE_INT, &value, sizeof(value));
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(long tag, long value)
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_util_EventLog_writeEvent_Long(JNIEnv* env, jobject clazz,
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                  jint tag, jlong value)
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android_btWriteLog(tag, EVENT_TYPE_LONG, &value, sizeof(value));
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(long tag, List value)
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_util_EventLog_writeEvent_List(JNIEnv* env, jobject clazz,
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                  jint tag, jobject value) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (value == NULL) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jclass clazz = env->FindClass("java/lang/IllegalArgumentException");
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->ThrowNew(clazz, "writeEvent needs a value.");
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ByteBuf byteBuf(INITAL_BUFFER_CAPACITY);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byteBuf.putList(env, value);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byteBuf.putByte((uint8_t)END_DELIMITER);
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int numBytesPut = byteBuf.len;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int bytesWritten = android_bWriteLog(tag, byteBuf.buf, numBytesPut);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return bytesWritten;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native int writeEvent(int tag, String value)
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_util_EventLog_writeEvent_String(JNIEnv* env, jobject clazz,
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    jint tag, jstring value) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (value == NULL) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jclass clazz = env->FindClass("java/lang/IllegalArgumentException");
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->ThrowNew(clazz, "logEvent needs a value.");
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ByteBuf byteBuf(INITAL_BUFFER_CAPACITY);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byteBuf.putStringEvent(env, value);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byteBuf.putByte((uint8_t)END_DELIMITER);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int numBytesPut = byteBuf.len;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int bytesWritten = android_bWriteLog(tag, byteBuf.buf, numBytesPut);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return bytesWritten;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In class android.util.EventLog:
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  static native void readEvents(int[] tags, Collection<Event> output)
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz,
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                             jintArray tags,
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                             jobject out) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tags == NULL || out == NULL) {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/NullPointerException", NULL);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd = open("/dev/" LOGGER_LOG_EVENTS, O_RDONLY | O_NONBLOCK);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowIOException(env, errno);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jsize tagLength = env->GetArrayLength(tags);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jint *tagValues = env->GetIntArrayElements(tags, NULL);
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t buf[LOGGER_ENTRY_MAX_LEN];
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int len = read(fd, buf, sizeof(buf));
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len == 0 || (len < 0 && errno == EAGAIN)) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (len < 0) {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This calls env->ThrowNew(), which doesn't throw an exception
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // now, but sets a flag to trigger an exception after we return.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jniThrowIOException(env, errno);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if ((size_t) len < sizeof(logger_entry) + sizeof(int32_t)) {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jniThrowException(env, "java/io/IOException", "Event too short");
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        logger_entry* entry = (logger_entry*) buf;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int32_t tag = * (int32_t*) (buf + sizeof(*entry));
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int found = 0;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; !found && i < tagLength; ++i) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            found = (tag == tagValues[i]);
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (found) {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jsize len = sizeof(*entry) + entry->len;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jbyteArray array = env->NewByteArray(len);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array == NULL) break;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jbyte *bytes = env->GetByteArrayElements(array, NULL);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            memcpy(bytes, buf, len);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->ReleaseByteArrayElements(array, bytes, 0);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            jobject event = env->NewObject(gEventClass, gEventInitID, array);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event == NULL) break;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->CallBooleanMethod(out, gCollectionAddID, event);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->DeleteLocalRef(event);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->DeleteLocalRef(array);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(fd);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseIntArrayElements(tags, tagValues, 0);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gRegisterMethods[] = {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* name, signature, funcPtr */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent",
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      "(ILjava/lang/String;)I",
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      (void*) android_util_EventLog_writeEvent_String
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    },
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "writeEvent",
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      "(ILandroid/util/EventLog$List;)I",
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      (void*) android_util_EventLog_writeEvent_List
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    },
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "readEvents",
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      "([ILjava/util/Collection;)V",
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      (void*) android_util_EventLog_readEvents
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { const char *name; jclass *clazz; } gClasses[] = {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "android/util/EventLog$Event", &gEventClass },
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "android/util/EventLog$List", &gListClass },
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/Integer", &gIntegerClass },
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/Long", &gLongClass },
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/lang/String", &gStringClass },
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "java/util/Collection", &gCollectionClass },
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gIntegerClass, "value", "I", &gIntegerValueID },
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gListClass, "mItems", "[Ljava/lang/Object;", &gListItemsID },
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gLongClass, "value", "J", &gLongValueID },
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gEventClass, "<init>", "([B)V", &gEventInitID },
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_util_EventLog(JNIEnv* env) {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gClasses); ++i) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jclass clazz = env->FindClass(gClasses[i].name);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (clazz == NULL) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find class: %s\n", gClasses[i].name);
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gClasses[i].clazz = (jclass) env->NewGlobalRef(clazz);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gFields); ++i) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gFields[i].id = env->GetFieldID(
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *gFields[i].c, gFields[i].name, gFields[i].ft);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (*gFields[i].id == NULL) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find field: %s\n", gFields[i].name);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < NELEM(gMethods); ++i) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *gMethods[i].id = env->GetMethodID(
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (*gMethods[i].id == NULL) {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Can't find method: %s\n", gMethods[i].name);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return AndroidRuntime::registerNativeMethods(
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env,
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "android/util/EventLog",
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            gRegisterMethods, NELEM(gRegisterMethods));
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
354