summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-07-23 18:13:38 -0700
committerAdam Lesinski <adamlesinski@google.com>2015-07-24 12:56:37 -0700
commit515702c29e5eae0e3f02b5d65ed86218813e8945 (patch)
tree31db95ba405ecd448b59f5dd655a0655a29af995 /services
parenta0a71d8a221d4f3896c7b0d3b2b87eba4e7a77f7 (diff)
downloadframeworks_base-515702c29e5eae0e3f02b5d65ed86218813e8945.zip
frameworks_base-515702c29e5eae0e3f02b5d65ed86218813e8945.tar.gz
frameworks_base-515702c29e5eae0e3f02b5d65ed86218813e8945.tar.bz2
BatteryStats: Decode wakeup reasons in Java
Wakeup reasons come from drivers and sometimes are malformed UTF-8. Decode them in Java so we can easily replace malformed characters and still have user visible strings. Bug:22368519 Change-Id: Ifade1a7fcdf6545e7e344d74390200c329430e14
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java56
-rw-r--r--services/core/jni/com_android_server_am_BatteryStatsService.cpp18
2 files changed, 53 insertions, 21 deletions
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 4b0b924..4102f37 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -58,6 +58,11 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
import java.util.List;
/**
@@ -897,7 +902,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
final class WakeupReasonThread extends Thread {
- final String[] mReason = new String[1];
+ private static final int MAX_REASON_SIZE = 512;
+ private CharsetDecoder mDecoder;
+ private ByteBuffer mUtf8Buffer;
+ private CharBuffer mUtf16Buffer;
WakeupReasonThread() {
super("BatteryStats_wakeupReason");
@@ -906,25 +914,53 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ mDecoder = StandardCharsets.UTF_8
+ .newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .replaceWith("?");
+
+ mUtf8Buffer = ByteBuffer.allocateDirect(MAX_REASON_SIZE);
+ mUtf16Buffer = CharBuffer.allocate(MAX_REASON_SIZE);
+
try {
- int num;
- while ((num = nativeWaitWakeup(mReason)) >= 0) {
+ String reason;
+ while ((reason = waitWakeup()) != null) {
synchronized (mStats) {
- // num will be either 0 or 1.
- if (num > 0) {
- mStats.noteWakeupReasonLocked(mReason[0]);
- } else {
- mStats.noteWakeupReasonLocked("unknown");
- }
+ mStats.noteWakeupReasonLocked(reason);
}
}
} catch (RuntimeException e) {
Slog.e(TAG, "Failure reading wakeup reasons", e);
}
}
+
+ private String waitWakeup() {
+ mUtf8Buffer.clear();
+ mUtf16Buffer.clear();
+ mDecoder.reset();
+
+ int bytesWritten = nativeWaitWakeup(mUtf8Buffer);
+ if (bytesWritten < 0) {
+ return null;
+ } else if (bytesWritten == 0) {
+ return "unknown";
+ }
+
+ // Set the buffer's limit to the number of bytes written.
+ mUtf8Buffer.limit(bytesWritten);
+
+ // Decode the buffer from UTF-8 to UTF-16.
+ // Unmappable characters will be replaced.
+ mDecoder.decode(mUtf8Buffer, mUtf16Buffer, true);
+ mUtf16Buffer.flip();
+
+ // Create a String from the UTF-16 buffer.
+ return mUtf16Buffer.toString();
+ }
}
- private static native int nativeWaitWakeup(String[] outReason);
+ private static native int nativeWaitWakeup(ByteBuffer outBuffer);
private void dumpHelp(PrintWriter pw) {
pw.println("Battery stats (batterystats) dump options:");
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index e257e89..dfc5ef6 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -59,9 +59,9 @@ static void wakeup_callback(bool success)
}
}
-static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobjectArray outReasons)
+static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
{
- if (outReasons == NULL) {
+ if (outBuf == NULL) {
jniThrowException(env, "java/lang/NullPointerException", "null argument");
return -1;
}
@@ -99,11 +99,11 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobjectArray outReasons
return -1;
}
- ALOGV("Reading wakeup reasons");
+ char* mergedreason = (char*)env->GetDirectBufferAddress(outBuf);
+ int remainreasonlen = (int)env->GetDirectBufferCapacity(outBuf);
- char mergedreason[MAX_REASON_SIZE];
+ ALOGV("Reading wakeup reasons");
char* mergedreasonpos = mergedreason;
- int remainreasonlen = MAX_REASON_SIZE;
char reasonline[128];
int i = 0;
while (fgets(reasonline, sizeof(reasonline), fp) != NULL) {
@@ -161,21 +161,17 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobjectArray outReasons
ALOGV("Got %d reasons", i);
if (i > 0) {
*mergedreasonpos = 0;
- ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason));
- env->SetObjectArrayElement(outReasons, 0, reasonString.get());
- i = 1;
}
if (fclose(fp) != 0) {
ALOGE("Failed to close %s", LAST_RESUME_REASON);
return -1;
}
-
- return i;
+ return mergedreasonpos - mergedreason;
}
static JNINativeMethod method_table[] = {
- { "nativeWaitWakeup", "([Ljava/lang/String;)I", (void*)nativeWaitWakeup },
+ { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
};
int register_android_server_BatteryStatsService(JNIEnv *env)