From 68cdf1997f7b007e4c81089bc402a0356292f4c2 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Sun, 3 Apr 2016 21:57:15 -0700 Subject: [PATCH] Add low power stats to batteryhistory Exports SOC specific low power state info to batterystats service. BatteryStats service queries the powerHAL module whenever and updates the HistoryStepDetails whenever setBatteryState is called by the BatteryService. The stats get appended to the battery history whenever there is a change in the battery level. Bug: 26564574 Change-Id: I02b4db00aec0c69d1558492224f3a4dc1c386fa6 --- core/java/android/os/BatteryStats.java | 9 ++ .../android/internal/os/BatteryStatsImpl.java | 27 +++- .../server/am/BatteryStatsService.java | 34 ++++- ..._android_server_am_BatteryStatsService.cpp | 117 ++++++++++++++++++ ...droid_server_power_PowerManagerService.cpp | 2 +- 5 files changed, 182 insertions(+), 7 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b9a3cff1aabbe..2c63be255c0b0 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1070,6 +1070,9 @@ public abstract class BatteryStats implements Parcelable { public int statSoftIrqTime; public int statIdlTime; + // Platform-level low power state stats + public String statPlatformIdleState; + public HistoryStepDetails() { clear(); } @@ -1099,6 +1102,7 @@ public abstract class BatteryStats implements Parcelable { out.writeInt(statIrqTime); out.writeInt(statSoftIrqTime); out.writeInt(statIdlTime); + out.writeString(statPlatformIdleState); } public void readFromParcel(Parcel in) { @@ -1119,6 +1123,7 @@ public abstract class BatteryStats implements Parcelable { statIrqTime = in.readInt(); statSoftIrqTime = in.readInt(); statIdlTime = in.readInt(); + statPlatformIdleState = in.readString(); } } @@ -4788,6 +4793,8 @@ public abstract class BatteryStats implements Parcelable { pw.print(sb); pw.print(")"); } + pw.print(", PlatformIdleStat "); + pw.print(rec.stepDetails.statPlatformIdleState); pw.println(); } else { pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); @@ -4821,6 +4828,8 @@ public abstract class BatteryStats implements Parcelable { pw.print(rec.stepDetails.statSoftIrqTime); pw.print(','); pw.print(rec.stepDetails.statIdlTime); + pw.print(','); + pw.print(rec.stepDetails.statPlatformIdleState); pw.println(); } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index e69ed35ff90d4..5358d78e1b02a 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 142 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 143 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -150,6 +150,13 @@ public class BatteryStatsImpl extends BatteryStats { public void batterySendBroadcast(Intent intent); } + public interface PlatformIdleStateCallback { + public String getPlatformLowPowerStats(); + } + + private final PlatformIdleStateCallback mPlatformIdleStateCallback; + + final class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper, null, true); @@ -569,6 +576,7 @@ public class BatteryStatsImpl extends BatteryStats { mDailyFile = null; mHandler = null; mExternalSync = null; + mPlatformIdleStateCallback = null; clearHistoryLocked(); } @@ -2220,6 +2228,12 @@ public class BatteryStatsImpl extends BatteryStats { + cur.eventTag.string); } if (computeStepDetails) { + if (mPlatformIdleStateCallback != null) { + mCurHistoryStepDetails.statPlatformIdleState = + mPlatformIdleStateCallback.getPlatformLowPowerStats(); + if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" + + mCurHistoryStepDetails.statPlatformIdleState); + } computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails); if (includeStepDetails != 0) { mCurHistoryStepDetails.writeToParcel(dest); @@ -7372,11 +7386,16 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { - this(new SystemClocks(), systemDir, handler, externalSync); + this(new SystemClocks(), systemDir, handler, externalSync, null); + } + + public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync, + PlatformIdleStateCallback cb) { + this(new SystemClocks(), systemDir, handler, externalSync, cb); } public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, - ExternalStatsSync externalSync) { + ExternalStatsSync externalSync, PlatformIdleStateCallback cb) { init(clocks); if (systemDir != null) { @@ -7462,6 +7481,7 @@ public class BatteryStatsImpl extends BatteryStats { initDischarge(); clearHistoryLocked(); updateDailyDeadlineLocked(); + mPlatformIdleStateCallback = cb; } public BatteryStatsImpl(Parcel p) { @@ -7477,6 +7497,7 @@ public class BatteryStatsImpl extends BatteryStats { mExternalSync = null; clearHistoryLocked(); readFromParcel(p); + mPlatformIdleStateCallback = null; } public void setPowerProfile(PowerProfile profile) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 2516f5df4cbfd..c6786defd3f98 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -79,7 +79,8 @@ import java.util.concurrent.TimeoutException; * battery life. */ public final class BatteryStatsService extends IBatteryStats.Stub - implements PowerManagerInternal.LowPowerModeListener { + implements PowerManagerInternal.LowPowerModeListener, + BatteryStatsImpl.PlatformIdleStateCallback { static final String TAG = "BatteryStatsService"; /** @@ -173,6 +174,33 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } + private native int getPlatformLowPowerStats(ByteBuffer outBuffer); + private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE) + .replaceWith("?"); + private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE); + private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); + private static final int MAX_LOW_POWER_STATS_SIZE = 512; + + @Override + public String getPlatformLowPowerStats() { + mUtf8BufferStat.clear(); + mUtf16BufferStat.clear(); + mDecoderStat.reset(); + int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat); + if (bytesWritten < 0) { + return null; + } else if (bytesWritten == 0) { + return "Empty"; + } + mUtf8BufferStat.limit(bytesWritten); + mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true); + mUtf16BufferStat.flip(); + return mUtf16BufferStat.toString(); + } + BatteryStatsService(File systemDir, Handler handler) { // Our handler here will be accessing the disk, use a different thread than // what the ActivityManagerService gave us (no I/O on that one!). @@ -182,9 +210,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub mHandler = new BatteryStatsHandler(thread.getLooper()); // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through. - mStats = new BatteryStatsImpl(systemDir, handler, mHandler); + mStats = new BatteryStatsImpl(systemDir, handler, mHandler, this); } - + public void publish(Context context) { mContext = context; mStats.setRadioScanningTimeout(mContext.getResources().getInteger( diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 5c43659796440..183a370bac0d7 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -27,8 +27,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -47,6 +49,7 @@ namespace android static bool wakeup_init = false; static sem_t wakeup_sem; +extern struct power_module* gPowerModule; static void wakeup_callback(bool success) { @@ -170,8 +173,122 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf) return mergedreasonpos - mergedreason; } +static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) { + int num_modes = -1; + char *output = (char*)env->GetDirectBufferAddress(outBuf), *offset = output; + int remaining = (int)env->GetDirectBufferCapacity(outBuf); + power_state_platform_sleep_state_t *list; + size_t *voter_list; + int total_added = -1; + + if (outBuf == NULL) { + jniThrowException(env, "java/lang/NullPointerException", "null argument"); + goto error; + } + + if (!gPowerModule) { + ALOGE("%s: gPowerModule not loaded", POWER_HARDWARE_MODULE_ID); + goto error; + } + + if (! (gPowerModule->get_platform_low_power_stats && gPowerModule->get_number_of_platform_modes + && gPowerModule->get_voter_list)) { + ALOGE("%s: Missing API", POWER_HARDWARE_MODULE_ID); + goto error; + } + + if (gPowerModule->get_number_of_platform_modes) { + num_modes = gPowerModule->get_number_of_platform_modes(gPowerModule); + } + + if (num_modes < 1) { + ALOGE("%s: Platform does not even have one low power mode", POWER_HARDWARE_MODULE_ID); + goto error; + } + + list = (power_state_platform_sleep_state_t *)calloc(num_modes, + sizeof(power_state_platform_sleep_state_t)); + if (!list) { + ALOGE("%s: power_state_platform_sleep_state_t allocation failed", POWER_HARDWARE_MODULE_ID); + goto error; + } + + voter_list = (size_t *)calloc(num_modes, sizeof(*voter_list)); + if (!voter_list) { + ALOGE("%s: voter_list allocation failed", POWER_HARDWARE_MODULE_ID); + goto err_free; + } + + gPowerModule->get_voter_list(gPowerModule, voter_list); + + for (int i = 0; i < num_modes; i++) { + list[i].voters = (power_state_voter_t *)calloc(voter_list[i], + sizeof(power_state_voter_t)); + if (!list[i].voters) { + ALOGE("%s: voter_t allocation failed", POWER_HARDWARE_MODULE_ID); + goto err_free; + } + } + + if (!gPowerModule->get_platform_low_power_stats(gPowerModule, list)) { + for (int i = 0; i < num_modes; i++) { + int added; + + added = snprintf(offset, remaining, "%s_time=%" PRIu64 " %s_count=%" PRIu64 " ", + list[i].name, list[i].residency_in_msec_since_boot, list[i].name, + list[i].total_transitions); + if (added < 0) { + break; + } + if (added > remaining) { + added = remaining; + } + offset += added; + remaining -= added; + total_added += added; + + for (unsigned int j = 0; j < list[i].number_of_voters; j++) { + added = snprintf(offset, remaining, "%s_time=%" PRIu64 " %s_count=%" PRIu64 " ", + list[i].voters[j].name, + list[i].voters[j].total_time_in_msec_voted_for_since_boot, + list[i].voters[j].name, + list[i].voters[j].total_number_of_times_voted_since_boot); + if (added < 0) { + break; + } + if (added > remaining) { + added = remaining; + } + offset += added; + remaining -= added; + total_added += added; + } + + if (remaining <= 0) { + /* rewrite NULL character*/ + offset--; + total_added--; + ALOGE("%s module: buffer not enough", POWER_HARDWARE_MODULE_ID); + break; + } + } + } + *offset = 0; + total_added += 1; + +err_free: + for (int i = 0; i < num_modes; i++) { + free(list[i].voters); + } + free(list); + free(voter_list); +error: + return total_added; +} + static const JNINativeMethod method_table[] = { { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup }, + { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats }, }; int register_android_server_BatteryStatsService(JNIEnv *env) diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp index 2fdb8e2469cd6..cbbfda6aa1598 100644 --- a/services/core/jni/com_android_server_power_PowerManagerService.cpp +++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp @@ -48,7 +48,7 @@ static struct { // ---------------------------------------------------------------------------- static jobject gPowerManagerServiceObj; -static struct power_module* gPowerModule; +struct power_module* gPowerModule; static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];