diff options
| -rw-r--r-- | core/java/android/util/StatsLog.java | 76 | ||||
| -rw-r--r-- | core/jni/Android.bp | 1 | ||||
| -rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
| -rw-r--r-- | core/jni/android_util_StatsLog.cpp | 201 |
4 files changed, 280 insertions, 0 deletions
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java new file mode 100644 index 000000000000..0be1a8cfabae --- /dev/null +++ b/core/java/android/util/StatsLog.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +/** + * Logging access for platform metrics. + * + * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})! + * These diagnostic stats are for system integrators, not application authors. + * + * <p>Stats use integer tag codes. + * They carry a payload of one or more int, long, or String values. + * @hide + */ +public class StatsLog { + /** @hide */ public StatsLog() {} + + private static final String TAG = "StatsLog"; + + // We assume that the native methods deal with any concurrency issues. + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeInt(int tag, int value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeLong(int tag, long value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeFloat(int tag, float value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param str A value to log + * @return The number of bytes written + */ + public static native int writeString(int tag, String str); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param list A list of values to log. All values should + * be of type int, long, float or String. + * @return The number of bytes written + */ + public static native int writeArray(int tag, Object... list); +} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index c62934100540..d63e22c189f8 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -103,6 +103,7 @@ cc_library_shared { "android_nio_utils.cpp", "android_util_AssetManager.cpp", "android_util_Binder.cpp", + "android_util_StatsLog.cpp", "android_util_EventLog.cpp", "android_util_MemoryIntArray.cpp", "android_util_Log.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 5afd06750601..02c9848ea149 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -111,6 +111,7 @@ namespace android { extern int register_android_app_admin_SecurityLog(JNIEnv* env); extern int register_android_content_AssetManager(JNIEnv* env); extern int register_android_util_EventLog(JNIEnv* env); +extern int register_android_util_StatsLog(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); extern int register_android_util_MemoryIntArray(JNIEnv* env); extern int register_android_util_PathParser(JNIEnv* env); @@ -1311,6 +1312,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), + REG_JNI(register_android_util_StatsLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_MemoryIntArray), REG_JNI(register_android_util_PathParser), diff --git a/core/jni/android_util_StatsLog.cpp b/core/jni/android_util_StatsLog.cpp new file mode 100644 index 000000000000..c992365094f7 --- /dev/null +++ b/core/jni/android_util_StatsLog.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007-2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <log/log_event_list.h> + +#include <log/log.h> + +#include <nativehelper/JNIHelp.h> +#include "core_jni_helpers.h" +#include "jni.h" + +#define UNUSED __attribute__((__unused__)) + +namespace android { + +static jclass gCollectionClass; +static jmethodID gCollectionAddID; + +static jclass gIntegerClass; +static jfieldID gIntegerValueID; + +static jclass gLongClass; +static jfieldID gLongValueID; + +static jclass gFloatClass; +static jfieldID gFloatValueID; + +static jclass gStringClass; + +/* + * In class android.util.StatsLog: + * static native int writeInt(int tag, int value) + */ +static jint android_util_StatsLog_write_Integer(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jint value) +{ + android_log_event_list ctx(tag); + ctx << (int32_t)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeLong(long tag, long value) + */ +static jint android_util_StatsLog_write_Long(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jlong value) +{ + android_log_event_list ctx(tag); + ctx << (int64_t)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeFloat(long tag, float value) + */ +static jint android_util_StatsLog_write_Float(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jfloat value) +{ + android_log_event_list ctx(tag); + ctx << (float)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeString(int tag, String value) + */ +static jint android_util_StatsLog_write_String(JNIEnv* env, + jobject clazz UNUSED, + jint tag, jstring value) { + android_log_event_list ctx(tag); + // 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. + if (value != NULL) { + const char *str = env->GetStringUTFChars(value, NULL); + ctx << str; + env->ReleaseStringUTFChars(value, str); + } else { + ctx << "NULL"; + } + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeArray(long tag, Object... value) + */ +static jint android_util_StatsLog_write_Array(JNIEnv* env, jobject clazz, + jint tag, jobjectArray value) { + android_log_event_list ctx(tag); + + if (value == NULL) { + ctx << "[NULL]"; + return ctx.write(LOG_ID_STATS); + } + + jsize copied = 0, num = env->GetArrayLength(value); + for (; copied < num && copied < 255; ++copied) { + if (ctx.status()) break; + jobject item = env->GetObjectArrayElement(value, copied); + if (item == NULL) { + ctx << "NULL"; + } else if (env->IsInstanceOf(item, gStringClass)) { + const char *str = env->GetStringUTFChars((jstring) item, NULL); + ctx << str; + env->ReleaseStringUTFChars((jstring) item, str); + } else if (env->IsInstanceOf(item, gIntegerClass)) { + ctx << (int32_t)env->GetIntField(item, gIntegerValueID); + } else if (env->IsInstanceOf(item, gLongClass)) { + ctx << (int64_t)env->GetLongField(item, gLongValueID); + } else if (env->IsInstanceOf(item, gFloatClass)) { + ctx << (float)env->GetFloatField(item, gFloatValueID); + } else { + jniThrowException(env, + "java/lang/IllegalArgumentException", + "Invalid payload item type"); + return -1; + } + env->DeleteLocalRef(item); + } + return ctx.write(LOG_ID_STATS); +} + +/* + * JNI registration. + */ +static const JNINativeMethod gRegisterMethods[] = { + /* name, signature, funcPtr */ + { "writeInt", "(II)I", (void*) android_util_StatsLog_write_Integer }, + { "writeLong", "(IJ)I", (void*) android_util_StatsLog_write_Long }, + { "writeFloat", "(IF)I", (void*) android_util_StatsLog_write_Float }, + { "writeString", + "(ILjava/lang/String;)I", + (void*) android_util_StatsLog_write_String + }, + { "writeArray", + "(I[Ljava/lang/Object;)I", + (void*) android_util_StatsLog_write_Array + }, +}; + +static struct { const char *name; jclass *clazz; } gClasses[] = { + { "java/lang/Integer", &gIntegerClass }, + { "java/lang/Long", &gLongClass }, + { "java/lang/Float", &gFloatClass }, + { "java/lang/String", &gStringClass }, + { "java/util/Collection", &gCollectionClass }, +}; + +static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = { + { &gIntegerClass, "value", "I", &gIntegerValueID }, + { &gLongClass, "value", "J", &gLongValueID }, + { &gFloatClass, "value", "F", &gFloatValueID }, +}; + +static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = { + { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID }, +}; + +int register_android_util_StatsLog(JNIEnv* env) { + for (int i = 0; i < NELEM(gClasses); ++i) { + jclass clazz = FindClassOrDie(env, gClasses[i].name); + *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz); + } + + for (int i = 0; i < NELEM(gFields); ++i) { + *gFields[i].id = GetFieldIDOrDie(env, + *gFields[i].c, gFields[i].name, gFields[i].ft); + } + + for (int i = 0; i < NELEM(gMethods); ++i) { + *gMethods[i].id = GetMethodIDOrDie(env, + *gMethods[i].c, gMethods[i].name, gMethods[i].mt); + } + + return RegisterMethodsOrDie( + env, + "android/util/StatsLog", + gRegisterMethods, NELEM(gRegisterMethods)); +} + +}; // namespace android |