diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-07-23 18:13:38 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-07-24 12:56:37 -0700 |
commit | 515702c29e5eae0e3f02b5d65ed86218813e8945 (patch) | |
tree | 31db95ba405ecd448b59f5dd655a0655a29af995 /services | |
parent | a0a71d8a221d4f3896c7b0d3b2b87eba4e7a77f7 (diff) | |
download | frameworks_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.java | 56 | ||||
-rw-r--r-- | services/core/jni/com_android_server_am_BatteryStatsService.cpp | 18 |
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) |