diff options
10 files changed, 231 insertions, 503 deletions
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index 81dd96e..ce0b954 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -16,134 +16,43 @@ package android.util; -import com.google.android.collect.Lists; - +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** - * {@hide} - * Dynamically defined (in terms of event types), space efficient (i.e. "tight") event logging - * to help instrument code for large scale stability and performance monitoring. - * - * Note that this class contains all static methods. This is done for efficiency reasons. + * Access to the system diagnostic event record. System diagnostic events are + * used to record certain system-level events (such as garbage collection, + * activity manager state, system watchdogs, and other low level activity), + * which may be automatically collected and analyzed during system development. * - * Events for the event log are self-describing binary data structures. They start with a 20 byte - * header (generated automatically) which contains all of the following in order: + * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})! + * These diagnostic events are for system integrators, not application authors. * - * <ul> - * <li> Payload length: 2 bytes - length of the non-header portion </li> - * <li> Padding: 2 bytes - no meaning at this time </li> - * <li> Timestamp: - * <ul> - * <li> Seconds: 4 bytes - seconds since Epoch </li> - * <li> Nanoseconds: 4 bytes - plus extra nanoseconds </li> - * </ul></li> - * <li> Process ID: 4 bytes - matching {@link android.os.Process#myPid} </li> - * <li> Thread ID: 4 bytes - matching {@link android.os.Process#myTid} </li> - * </li> - * </ul> + * <p>Events use integer tag codes corresponding to /system/etc/event-log-tags. + * They carry a payload of one or more int, long, or String values. The + * event-log-tags file defines the payload contents for each type code. * - * The above is followed by a payload, comprised of the following: - * <ul> - * <li> Tag: 4 bytes - unique integer used to identify a particular event. This number is also - * used as a key to map to a string that can be displayed by log reading tools. - * </li> - * <li> Type: 1 byte - can be either {@link #INT}, {@link #LONG}, {@link #STRING}, - * or {@link #LIST}. </li> - * <li> Event log value: the size and format of which is one of: - * <ul> - * <li> INT: 4 bytes </li> - * <li> LONG: 8 bytes </li> - * <li> STRING: - * <ul> - * <li> Size of STRING: 4 bytes </li> - * <li> The string: n bytes as specified in the size fields above. </li> - * </ul></li> - * <li> {@link List LIST}: - * <ul> - * <li> Num items: 1 byte </li> - * <li> N value payloads, where N is the number of items specified above. </li> - * </ul></li> - * </ul> - * </li> - * <li> '\n': 1 byte - an automatically generated newline, used to help detect and recover from log - * corruption and enable standard unix tools like grep, tail and wc to operate - * on event logs. </li> - * </ul> - * - * Note that all output is done in the endian-ness of the device (as determined - * by {@link ByteOrder#nativeOrder()}). + * @pending */ - public class EventLog { + private static final String TAG = "EventLog"; - // Value types - public static final byte INT = 0; - public static final byte LONG = 1; - public static final byte STRING = 2; - public static final byte LIST = 3; + private static final String TAGS_FILE = "/system/etc/event-log-tags"; + private static final String COMMENT_PATTERN = "^\\s*(#.*)?$"; + private static final String TAG_PATTERN = "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$"; + private static HashMap<String, Integer> sTagCodes = null; + private static HashMap<Integer, String> sTagNames = null; - /** - * An immutable tuple used to log a heterogeneous set of loggable items. - * The items can be Integer, Long, String, or {@link List}. - * The maximum number of items is 127 - */ - public static final class List { - private Object[] mItems; - - /** - * Get a particular tuple item - * @param pos The position of the item in the tuple - */ - public final Object getItem(int pos) { - return mItems[pos]; - } - - /** - * Get the number of items in the tuple. - */ - public final byte getNumItems() { - return (byte) mItems.length; - } - - /** - * Create a new tuple. - * @param items The items to create the tuple with, as varargs. - * @throws IllegalArgumentException if the arguments are too few (0), - * too many, or aren't loggable types. - */ - public List(Object... items) throws IllegalArgumentException { - if (items.length > Byte.MAX_VALUE) { - throw new IllegalArgumentException( - "A List must have fewer than " - + Byte.MAX_VALUE + " items in it."); - } - for (int i = 0; i < items.length; i++) { - final Object item = items[i]; - if (item == null) { - // Would be nice to be able to write null strings... - items[i] = ""; - } else if (!(item instanceof List || - item instanceof String || - item instanceof Integer || - item instanceof Long)) { - throw new IllegalArgumentException( - "Attempt to create a List with illegal item type."); - } - } - this.mItems = items; - } - } - - /** - * A previously logged event read from the logs. - */ + /** A previously logged event read from the logs. */ public static final class Event { private final ByteBuffer mBuffer; @@ -158,77 +67,83 @@ public class EventLog { private static final int TAG_OFFSET = 20; private static final int DATA_START = 24; + // Value types + private static final byte INT_TYPE = 0; + private static final byte LONG_TYPE = 1; + private static final byte STRING_TYPE = 2; + private static final byte LIST_TYPE = 3; + /** @param data containing event, read from the system */ - public Event(byte[] data) { + /*package*/ Event(byte[] data) { mBuffer = ByteBuffer.wrap(data); mBuffer.order(ByteOrder.nativeOrder()); } + /** @return the process ID which wrote the log entry */ public int getProcessId() { return mBuffer.getInt(PROCESS_OFFSET); } + /** @return the thread ID which wrote the log entry */ public int getThreadId() { return mBuffer.getInt(THREAD_OFFSET); } + /** @return the wall clock time when the entry was written */ public long getTimeNanos() { return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l + mBuffer.getInt(NANOSECONDS_OFFSET); } + /** @return the type tag code of the entry */ public int getTag() { return mBuffer.getInt(TAG_OFFSET); } - /** @return one of Integer, Long, String, or List. */ + /** @return one of Integer, Long, String, null, or Object[] of same. */ public synchronized Object getData() { - mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET)); - mBuffer.position(DATA_START); // Just after the tag. - return decodeObject(); - } - - public byte[] getRawData() { - return mBuffer.array(); + try { + mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET)); + mBuffer.position(DATA_START); // Just after the tag. + return decodeObject(); + } catch (IllegalArgumentException e) { + Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e); + return null; + } catch (BufferUnderflowException e) { + Log.wtf(TAG, "Truncated entry payload: tag=" + getTag(), e); + return null; + } } /** @return the loggable item at the current position in mBuffer. */ private Object decodeObject() { - if (mBuffer.remaining() < 1) return null; - switch (mBuffer.get()) { - case INT: - if (mBuffer.remaining() < 4) return null; + byte type = mBuffer.get(); + switch (type) { + case INT_TYPE: return (Integer) mBuffer.getInt(); - case LONG: - if (mBuffer.remaining() < 8) return null; + case LONG_TYPE: return (Long) mBuffer.getLong(); - case STRING: + case STRING_TYPE: try { - if (mBuffer.remaining() < 4) return null; int length = mBuffer.getInt(); - if (length < 0 || mBuffer.remaining() < length) return null; int start = mBuffer.position(); mBuffer.position(start + length); return new String(mBuffer.array(), start, length, "UTF-8"); } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); // UTF-8 is guaranteed. + Log.wtf(TAG, "UTF-8 is not supported", e); + return null; } - case LIST: - if (mBuffer.remaining() < 1) return null; + case LIST_TYPE: int length = mBuffer.get(); - if (length < 0) return null; Object[] array = new Object[length]; - for (int i = 0; i < length; ++i) { - array[i] = decodeObject(); - if (array[i] == null) return null; - } - return new List(array); + for (int i = 0; i < length; ++i) array[i] = decodeObject(); + return array; default: - return null; + throw new IllegalArgumentException("Unknown entry type: " + type); } } } @@ -236,46 +151,36 @@ public class EventLog { // We assume that the native methods deal with any concurrency issues. /** - * Send an event log message. - * @param tag An event identifer + * Record an event log message. + * @param tag The event type tag code * @param value A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, int value); /** - * Send an event log message. - * @param tag An event identifer + * Record an event log message. + * @param tag The event type tag code * @param value A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, long value); /** - * Send an event log message. - * @param tag An event identifer + * Record an event log message. + * @param tag The event type tag code * @param str A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, String str); /** - * Send an event log message. - * @param tag An event identifer - * @param list A {@link List} to log - * @return The number of bytes written - */ - public static native int writeEvent(int tag, List list); - - /** - * Send an event log message. - * @param tag An event identifer + * Record an event log message. + * @param tag The event type tag code * @param list A list of values to log * @return The number of bytes written */ - public static int writeEvent(int tag, Object... list) { - return writeEvent(tag, new List(list)); - } + public static native int writeEvent(int tag, Object... list); /** * Read events from the log, filtered by type. @@ -287,11 +192,65 @@ public class EventLog { throws IOException; /** - * Read events from a file. - * @param path to read from - * @param output container to add events into - * @throws IOException if something goes wrong reading events + * Get the name associated with an event type tag code. + * @param tag code to look up + * @return the name of the tag, or null if no tag has that number */ - public static native void readEvents(String path, Collection<Event> output) - throws IOException; + public static String getTagName(int tag) { + readTagsFile(); + return sTagNames.get(tag); + } + + /** + * Get the event type tag code associated with an event name. + * @param name of event to look up + * @return the tag code, or -1 if no tag has that name + */ + public static int getTagCode(String name) { + readTagsFile(); + Integer code = sTagCodes.get(name); + return code != null ? code : -1; + } + + /** + * Read TAGS_FILE, populating sTagCodes and sTagNames, if not already done. + */ + private static synchronized void readTagsFile() { + if (sTagCodes != null && sTagNames != null) return; + + sTagCodes = new HashMap<String, Integer>(); + sTagNames = new HashMap<Integer, String>(); + + Pattern comment = Pattern.compile(COMMENT_PATTERN); + Pattern tag = Pattern.compile(TAG_PATTERN); + BufferedReader reader = null; + String line; + + try { + reader = new BufferedReader(new FileReader(TAGS_FILE), 256); + while ((line = reader.readLine()) != null) { + if (comment.matcher(line).matches()) continue; + + Matcher m = tag.matcher(line); + if (!m.matches()) { + Log.wtf(TAG, "Bad entry in " + TAGS_FILE + ": " + line); + continue; + } + + try { + int num = Integer.parseInt(m.group(1)); + String name = m.group(2); + sTagCodes.put(name, num); + sTagNames.put(num, name); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Error in " + TAGS_FILE + ": " + line, e); + } + } + } catch (IOException e) { + Log.wtf(TAG, "Error reading " + TAGS_FILE, e); + // Leave the maps existing but unpopulated + } finally { + try { if (reader != null) reader.close(); } catch (IOException e) {} + } + } } diff --git a/core/java/android/util/EventLogTags.java b/core/java/android/util/EventLogTags.java index be905e3..98868f7 100644 --- a/core/java/android/util/EventLogTags.java +++ b/core/java/android/util/EventLogTags.java @@ -25,16 +25,14 @@ import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** Parsed representation of /etc/event-log-tags. */ +/** + * to-bo-deprecated: This class is no longer functional. + * Use {@link android.util.EventLog} instead. + */ public class EventLogTags { - private final static String TAG = "EventLogTags"; - - private final static String TAGS_FILE = "/etc/event-log-tags"; - public static class Description { public final int mTag; public final String mName; - // TODO: Parse parameter descriptions when anyone has a use for them. Description(int tag, String name) { mTag = tag; @@ -42,49 +40,11 @@ public class EventLogTags { } } - private final static Pattern COMMENT_PATTERN = Pattern.compile( - "^\\s*(#.*)?$"); - - private final static Pattern TAG_PATTERN = Pattern.compile( - "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$"); + public EventLogTags() throws IOException {} - private final HashMap<String, Description> mNameMap = - new HashMap<String, Description>(); - - private final HashMap<Integer, Description> mTagMap = - new HashMap<Integer, Description>(); - - public EventLogTags() throws IOException { - this(new BufferedReader(new FileReader(TAGS_FILE), 256)); - } + public EventLogTags(BufferedReader input) throws IOException {} - public EventLogTags(BufferedReader input) throws IOException { - String line; - while ((line = input.readLine()) != null) { - Matcher m = COMMENT_PATTERN.matcher(line); - if (m.matches()) continue; + public Description get(String name) { return null; } - m = TAG_PATTERN.matcher(line); - if (m.matches()) { - try { - int tag = Integer.parseInt(m.group(1)); - Description d = new Description(tag, m.group(2)); - mNameMap.put(d.mName, d); - mTagMap.put(d.mTag, d); - } catch (NumberFormatException e) { - Log.e(TAG, "Error in event log tags entry: " + line, e); - } - } else { - Log.e(TAG, "Can't parse event log tags entry: " + line); - } - } - } - - public Description get(String name) { - return mNameMap.get(name); - } - - public Description get(int tag) { - return mTagMap.get(tag); - } + public Description get(int tag) { return null; } } diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp index 34b7c89..78356cf 100644 --- a/core/jni/android_util_EventLog.cpp +++ b/core/jni/android_util_EventLog.cpp @@ -21,13 +21,6 @@ #include "jni.h" #include "cutils/logger.h" -#define END_DELIMITER '\n' -#define INT_BUFFER_SIZE (sizeof(jbyte)+sizeof(jint)+sizeof(END_DELIMITER)) -#define LONG_BUFFER_SIZE (sizeof(jbyte)+sizeof(jlong)+sizeof(END_DELIMITER)) -#define INITAL_BUFFER_CAPACITY 256 - -#define MAX(a,b) ((a>b)?a:b) - namespace android { static jclass gCollectionClass; @@ -47,107 +40,6 @@ static jfieldID gLongValueID; static jclass gStringClass; -struct ByteBuf { - size_t len; - size_t capacity; - uint8_t* buf; - - ByteBuf(size_t initSize) { - buf = (uint8_t*)malloc(initSize); - len = 0; - capacity = initSize; - } - - ~ByteBuf() { - free(buf); - } - - bool ensureExtraCapacity(size_t extra) { - size_t spaceNeeded = len + extra; - if (spaceNeeded > capacity) { - size_t newCapacity = MAX(spaceNeeded, 2 * capacity); - void* newBuf = realloc(buf, newCapacity); - if (newBuf == NULL) { - return false; - } - capacity = newCapacity; - buf = (uint8_t*)newBuf; - return true; - } else { - return true; - } - } - - void putIntEvent(jint value) { - bool succeeded = ensureExtraCapacity(INT_BUFFER_SIZE); - buf[len++] = EVENT_TYPE_INT; - memcpy(buf+len, &value, sizeof(jint)); - len += sizeof(jint); - } - - void putByte(uint8_t value) { - bool succeeded = ensureExtraCapacity(sizeof(uint8_t)); - buf[len++] = value; - } - - void putLongEvent(jlong value) { - bool succeeded = ensureExtraCapacity(LONG_BUFFER_SIZE); - buf[len++] = EVENT_TYPE_LONG; - memcpy(buf+len, &value, sizeof(jlong)); - len += sizeof(jlong); - } - - - void putStringEvent(JNIEnv* env, jstring value) { - const char* strValue = env->GetStringUTFChars(value, NULL); - uint32_t strLen = strlen(strValue); //env->GetStringUTFLength(value); - bool succeeded = ensureExtraCapacity(1 + sizeof(uint32_t) + strLen); - buf[len++] = EVENT_TYPE_STRING; - memcpy(buf+len, &strLen, sizeof(uint32_t)); - len += sizeof(uint32_t); - memcpy(buf+len, strValue, strLen); - env->ReleaseStringUTFChars(value, strValue); - len += strLen; - } - - void putList(JNIEnv* env, jobject list) { - jobjectArray items = (jobjectArray) env->GetObjectField(list, gListItemsID); - if (items == NULL) { - jniThrowException(env, "java/lang/NullPointerException", NULL); - return; - } - - jsize numItems = env->GetArrayLength(items); - putByte(EVENT_TYPE_LIST); - putByte(numItems); - // We'd like to call GetPrimitveArrayCritical() but that might - // not be safe since we're going to be doing some I/O - for (int i = 0; i < numItems; i++) { - jobject item = env->GetObjectArrayElement(items, i); - if (env->IsInstanceOf(item, gIntegerClass)) { - jint intVal = env->GetIntField(item, gIntegerValueID); - putIntEvent(intVal); - } else if (env->IsInstanceOf(item, gLongClass)) { - jlong longVal = env->GetLongField(item, gLongValueID); - putLongEvent(longVal); - } else if (env->IsInstanceOf(item, gStringClass)) { - putStringEvent(env, (jstring)item); - } else if (env->IsInstanceOf(item, gListClass)) { - putList(env, item); - } else { - jniThrowException( - env, - "java/lang/IllegalArgumentException", - "Attempt to log an illegal item type."); - return; - } - env->DeleteLocalRef(item); - } - - env->DeleteLocalRef(items); - } -}; - /* * In class android.util.EventLog: * static native int writeEvent(int tag, int value) @@ -170,41 +62,80 @@ static jint android_util_EventLog_writeEvent_Long(JNIEnv* env, jobject clazz, /* * In class android.util.EventLog: - * static native int writeEvent(long tag, List value) + * static native int writeEvent(int tag, String value) */ -static jint android_util_EventLog_writeEvent_List(JNIEnv* env, jobject clazz, - jint tag, jobject value) { - if (value == NULL) { - jclass clazz = env->FindClass("java/lang/IllegalArgumentException"); - env->ThrowNew(clazz, "writeEvent needs a value."); - return -1; - } - ByteBuf byteBuf(INITAL_BUFFER_CAPACITY); - byteBuf.putList(env, value); - byteBuf.putByte((uint8_t)END_DELIMITER); - int numBytesPut = byteBuf.len; - int bytesWritten = android_bWriteLog(tag, byteBuf.buf, numBytesPut); - return bytesWritten; +static jint android_util_EventLog_writeEvent_String(JNIEnv* env, jobject clazz, + jint tag, jstring value) { + uint8_t buf[LOGGER_ENTRY_MAX_PAYLOAD]; + + // Don't throw NPE -- I feel like it's sort of mean for a logging function + // to be all crashy if you pass in NULL -- but make the NULL value explicit. + const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL"; + jint len = strlen(str); + const int max = sizeof(buf) - sizeof(len) - 2; // Type byte, final newline + if (len > max) len = max; + + buf[0] = EVENT_TYPE_STRING; + memcpy(&buf[1], &len, sizeof(len)); + memcpy(&buf[1 + sizeof(len)], str, len); + buf[1 + sizeof(len) + len] = '\n'; + + if (value != NULL) env->ReleaseStringUTFChars(value, str); + return android_bWriteLog(tag, buf, 2 + sizeof(len) + len); } /* * In class android.util.EventLog: - * static native int writeEvent(int tag, String value) + * static native int writeEvent(long tag, Object... value) */ -static jint android_util_EventLog_writeEvent_String(JNIEnv* env, jobject clazz, - jint tag, jstring value) { +static jint android_util_EventLog_writeEvent_Array(JNIEnv* env, jobject clazz, + jint tag, jobjectArray value) { if (value == NULL) { - jclass clazz = env->FindClass("java/lang/IllegalArgumentException"); - env->ThrowNew(clazz, "logEvent needs a value."); - return -1; + return android_util_EventLog_writeEvent_String(env, clazz, tag, NULL); + } + + uint8_t buf[LOGGER_ENTRY_MAX_PAYLOAD]; + const size_t max = sizeof(buf) - 1; // leave room for final newline + size_t pos = 2; // Save room for type tag & array count + + jsize copied = 0, num = env->GetArrayLength(value); + for (; copied < num && copied < 256; ++copied) { + jobject item = env->GetObjectArrayElement(value, copied); + if (item == NULL || env->IsInstanceOf(item, gStringClass)) { + if (pos + 1 + sizeof(jint) > max) break; + const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL"; + jint len = strlen(str); + if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len); + buf[pos++] = EVENT_TYPE_STRING; + memcpy(&buf[pos], &len, sizeof(len)); + memcpy(&buf[pos + sizeof(len)], str, len); + pos += sizeof(len) + len; + if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str); + } else if (env->IsInstanceOf(item, gIntegerClass)) { + jint intVal = env->GetIntField(item, gIntegerValueID); + if (pos + 1 + sizeof(intVal) > max) break; + buf[pos++] = EVENT_TYPE_INT; + memcpy(&buf[pos], &intVal, sizeof(intVal)); + pos += sizeof(intVal); + } else if (env->IsInstanceOf(item, gLongClass)) { + jlong longVal = env->GetLongField(item, gLongValueID); + if (pos + 1 + sizeof(longVal) > max) break; + buf[pos++] = EVENT_TYPE_LONG; + memcpy(&buf[pos], &longVal, sizeof(longVal)); + pos += sizeof(longVal); + } else { + jniThrowException(env, + "java/lang/IllegalArgumentException", + "Invalid payload item type"); + return -1; + } + env->DeleteLocalRef(item); } - ByteBuf byteBuf(INITAL_BUFFER_CAPACITY); - byteBuf.putStringEvent(env, value); - byteBuf.putByte((uint8_t)END_DELIMITER); - int numBytesPut = byteBuf.len; - int bytesWritten = android_bWriteLog(tag, byteBuf.buf, numBytesPut); - return bytesWritten; + buf[0] = EVENT_TYPE_LIST; + buf[1] = copied; + buf[pos++] = '\n'; + return android_bWriteLog(tag, buf, pos); } /* @@ -276,81 +207,6 @@ static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz, } /* - * In class android.util.EventLog: - * static native void readEvents(String path, Collection<Event> output) - * - * Reads events from a file (See Checkin.Aggregation). Events are stored in - * native raw format (logger_entry + payload). - */ -static void android_util_EventLog_readEventsFile(JNIEnv* env, jobject clazz, jstring path, - jobject out) { - if (path == NULL || out == NULL) { - jniThrowException(env, "java/lang/NullPointerException", NULL); - return; - } - - const char *pathString = env->GetStringUTFChars(path, 0); - int fd = open(pathString, O_RDONLY | O_NONBLOCK); - env->ReleaseStringUTFChars(path, pathString); - - if (fd < 0) { - jniThrowIOException(env, errno); - return; - } - - uint8_t buf[LOGGER_ENTRY_MAX_LEN]; - for (;;) { - // read log entry structure from file - int len = read(fd, buf, sizeof(logger_entry)); - if (len == 0) { - break; // end of file - } else if (len < 0) { - jniThrowIOException(env, errno); - } else if ((size_t) len < sizeof(logger_entry)) { - jniThrowException(env, "java/io/IOException", "Event header too short"); - break; - } - - // read event payload - logger_entry* entry = (logger_entry*) buf; - if (entry->len > LOGGER_ENTRY_MAX_PAYLOAD) { - jniThrowException(env, - "java/lang/IllegalArgumentException", - "Too much data for event payload. Corrupt file?"); - break; - } - - len = read(fd, buf + sizeof(logger_entry), entry->len); - if (len == 0) { - break; // end of file - } else if (len < 0) { - jniThrowIOException(env, errno); - } else if ((size_t) len < entry->len) { - jniThrowException(env, "java/io/IOException", "Event payload too short"); - break; - } - - // create EventLog$Event and add it to the collection - int buffer_size = sizeof(logger_entry) + entry->len; - jbyteArray array = env->NewByteArray(buffer_size); - if (array == NULL) break; - - jbyte *bytes = env->GetByteArrayElements(array, NULL); - memcpy(bytes, buf, buffer_size); - env->ReleaseByteArrayElements(array, bytes, 0); - - jobject event = env->NewObject(gEventClass, gEventInitID, array); - if (event == NULL) break; - - env->CallBooleanMethod(out, gCollectionAddID, event); - env->DeleteLocalRef(event); - env->DeleteLocalRef(array); - } - - close(fd); -} - -/* * JNI registration. */ static JNINativeMethod gRegisterMethods[] = { @@ -362,22 +218,17 @@ static JNINativeMethod gRegisterMethods[] = { (void*) android_util_EventLog_writeEvent_String }, { "writeEvent", - "(ILandroid/util/EventLog$List;)I", - (void*) android_util_EventLog_writeEvent_List + "(I[Ljava/lang/Object;)I", + (void*) android_util_EventLog_writeEvent_Array }, { "readEvents", "([ILjava/util/Collection;)V", (void*) android_util_EventLog_readEvents }, - { "readEvents", - "(Ljava/lang/String;Ljava/util/Collection;)V", - (void*) android_util_EventLog_readEventsFile - } }; static struct { const char *name; jclass *clazz; } gClasses[] = { { "android/util/EventLog$Event", &gEventClass }, - { "android/util/EventLog$List", &gListClass }, { "java/lang/Integer", &gIntegerClass }, { "java/lang/Long", &gLongClass }, { "java/lang/String", &gStringClass }, @@ -386,7 +237,6 @@ static struct { const char *name; jclass *clazz; } gClasses[] = { static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = { { &gIntegerClass, "value", "I", &gIntegerValueID }, - { &gListClass, "mItems", "[Ljava/lang/Object;", &gListItemsID }, { &gLongClass, "value", "J", &gLongValueID }, }; @@ -430,4 +280,3 @@ int register_android_util_EventLog(JNIEnv* env) { } }; // namespace android - diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index ecd3380..979b8ba 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -822,11 +822,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { mRetryMgr.resetRetryCount(); CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation()); - int bsid = (loc != null) ? loc.getBaseStationId() : -1; - - EventLog.List val = new EventLog.List(bsid, + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_SETUP_FAILED, + loc != null ? loc.getBaseStationId() : -1, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_SETUP_FAILED, val); } trySetupData(Phone.REASON_CDMA_DATA_DETACHED); } @@ -865,10 +863,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private void writeEventLogCdmaDataDrop() { CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation()); - int bsid = (loc != null) ? loc.getBaseStationId() : -1; - EventLog.List val = new EventLog.List(bsid, + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, + loc != null ? loc.getBaseStationId() : -1, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, val); } protected void onDataStateChanged(AsyncResult ar) { diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 8698b38..9289ad4 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -537,11 +537,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } else if (!mDesiredPowerState && cm.getRadioState().isOn()) { DataConnectionTracker dcTracker = phone.mDataConnection; if (! dcTracker.isDataConnectionAsDesired()) { - - EventLog.List val = new EventLog.List( + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, dcTracker.getStateInString(), - (dcTracker.getAnyDataEnabled() ? 1 : 0) ); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val); + dcTracker.getAnyDataEnabled() ? 1 : 0); } Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); msg.arg1 = 1; // tearDown is true diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java index 91c089e..f4b9931 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java @@ -868,13 +868,10 @@ public final class GsmCallTracker extends CallTracker { causeCode == CallFailCause.QOS_NOT_AVAIL || causeCode == CallFailCause.BEARER_NOT_AVAIL || causeCode == CallFailCause.ERROR_UNSPECIFIED) { - int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - - EventLog.List val = new EventLog.List(causeCode, cid, - TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP, val); + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP, + causeCode, loc != null ? loc.getCid() : -1, + TelephonyManager.getDefault().getNetworkType()); } for (int i = 0, s = droppedDuringPoll.size() diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 5c97925..13407a3 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -710,12 +710,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting"); // Add an event log when the network drops PDP - int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - EventLog.List val = new EventLog.List(cid, + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, + loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val); cleanUpConnection(true, null); return; @@ -733,12 +731,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { + " Reconnecting"); // Log the network drop on the event log. - int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - EventLog.List val = new EventLog.List(cid, + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, + loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val); cleanUpConnection(true, null); } @@ -1148,14 +1144,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if(DBG) log("PDP setup failed " + cause); // Log this failure to the Event Logs. if (cause.isEventLoggable()) { - int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - - EventLog.List val = new EventLog.List( - cause.ordinal(), cid, + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, + cause.ordinal(), loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val); } // No try for permanent failure diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index f82474c..3e5f53c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -482,12 +482,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { // Can't register data sevice while voice service is ok // i.e. CREG is ok while CGREG is not // possible a network or baseband side error - int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - - EventLog.List val = new EventLog.List(ss.getOperatorNumeric(), cid); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CGREG_FAIL, val); + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CGREG_FAIL, + ss.getOperatorNumeric(), loc != null ? loc.getCid() : -1); mReportedGprsNoReg = true; } mStartedGprsRegCheck = false; @@ -518,11 +515,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } else if (!mDesiredPowerState && cm.getRadioState().isOn()) { DataConnectionTracker dcTracker = phone.mDataConnection; if (! dcTracker.isDataConnectionAsDesired()) { - - EventLog.List val = new EventLog.List( - dcTracker.getStateInString(), - (dcTracker.getAnyDataEnabled() ? 1 : 0) ); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val); + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, + dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0); } Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); msg.arg1 = 1; // tearDown is true diff --git a/tests/framework-tests/src/android/util/EventLogFunctionalTest.java b/tests/framework-tests/src/android/util/EventLogFunctionalTest.java index 8263083..8afe35f 100644 --- a/tests/framework-tests/src/android/util/EventLogFunctionalTest.java +++ b/tests/framework-tests/src/android/util/EventLogFunctionalTest.java @@ -59,31 +59,21 @@ public class EventLogFunctionalTest extends TestCase { } public void testLogOfListWithOneInt() throws Exception { - final EventLog.List list = new EventLog.List(1234); - final int numBytes = EventLog.writeEvent(TEST_TAG, list); + final int numBytes = EventLog.writeEvent(TEST_TAG, new Object[] {1234}); Assert.assertEquals(STARTING_POS_OF_PAYLOAD + 1 + 1 + 4 + 1, numBytes); } public void testLogOfListWithMultipleInts() throws Exception { - final EventLog.List list = new EventLog.List(1234, 2345, 3456); - final int numBytes = EventLog.writeEvent(TEST_TAG, list); + final int numBytes = EventLog.writeEvent(TEST_TAG, new Object[] {1234, 2345, 3456}); Assert.assertEquals(STARTING_POS_OF_PAYLOAD + 1 + 1 + 4 + 1 + 4 + 1 + 4 + 1, numBytes); } - public void testLogOfListWithEmbeddedList() throws Exception { - final EventLog.List list = new EventLog.List( - new EventLog.List(1234, 2345, 3456)); - final int numBytes = EventLog.writeEvent(TEST_TAG, list); - Assert.assertEquals(STARTING_POS_OF_PAYLOAD + 2 + 1 + 1 + 4 + 1 + 4 + 1 + 4 + 1, numBytes); - } - public void testEventLargerThanInitialBufferCapacity() throws Exception { final Integer[] array = new Integer[127]; for (int i = 0; i < array.length; i++) { array[i] = i; } - final EventLog.List list = new EventLog.List((Object[]) array); - final int numBytes = EventLog.writeEvent(TEST_TAG, list); + final int numBytes = EventLog.writeEvent(TEST_TAG, (Object[]) array); Assert.assertEquals(STARTING_POS_OF_PAYLOAD + 1 + (5 * array.length) + 1, numBytes); } @@ -117,8 +107,7 @@ public class EventLogFunctionalTest extends TestCase { // This test is obsolete. See http://b/issue?id=1262082 public void disableTestReadCompoundEntry() throws Exception { long when = System.currentTimeMillis(); - EventLog.writeEvent(2719, - new EventLog.List(1l, new EventLog.List("2", "three", "4"), 5)); + EventLog.writeEvent(2719, 1l, "2", 3); Log.i(TAG, "Wrote compound event at T=" + when); ArrayList<EventLog.Event> list = new ArrayList<EventLog.Event>(); @@ -129,18 +118,11 @@ public class EventLogFunctionalTest extends TestCase { long eventTime = event.getTimeNanos() / 1000000; Log.i(TAG, " Found event T=" + eventTime); if (eventTime > when - 100 && eventTime < when + 1000) { - EventLog.List data = (EventLog.List) event.getData(); - assertEquals(data.getNumItems(), 3); - - EventLog.List nested = (EventLog.List) data.getItem(1); - assertEquals(nested.getNumItems(), 3); - - assertEquals(data.getItem(0), 1l); - assertEquals(nested.getItem(0), "2"); - assertEquals(nested.getItem(1), "three"); - assertEquals(nested.getItem(2), "4"); - assertEquals(data.getItem(2), 5); - + Object[] data = (Object[]) event.getData(); + assertEquals(data.length, 3); + assertEquals(data[0], 1l); + assertEquals(data[1], "2"); + assertEquals(data[2], 3); assertFalse(found); found = true; } diff --git a/tests/framework-tests/src/android/util/EventLogTest.java b/tests/framework-tests/src/android/util/EventLogTest.java index 4a5d888..2a9e9cd 100644 --- a/tests/framework-tests/src/android/util/EventLogTest.java +++ b/tests/framework-tests/src/android/util/EventLogTest.java @@ -33,13 +33,13 @@ public class EventLogTest extends TestCase { public void testIllegalListTypesThrowException() throws Exception { try { - EventLog.writeEvent(TEST_TAG, new EventLog.List(new Object())); + EventLog.writeEvent(TEST_TAG, new Object[]{new Object()}); fail("Can't create List with any old Object"); } catch (IllegalArgumentException e) { // expected } try { - EventLog.writeEvent(TEST_TAG, new EventLog.List((byte) 1)); + EventLog.writeEvent(TEST_TAG, new Object[]{(byte) 1}); fail("Can't create List with any old byte"); } catch (IllegalArgumentException e) { // expected |