summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/util/StatsLog.java76
-rw-r--r--core/jni/Android.bp1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_util_StatsLog.cpp201
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