summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/BatteryStats.java12
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java7
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java23
-rw-r--r--services/core/jni/Android.mk1
-rw-r--r--services/core/jni/com_android_server_am_BatteryStatsService.cpp99
5 files changed, 142 insertions, 0 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ecc4dec47af7..162dddb1f797 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1219,6 +1219,7 @@ public abstract class BatteryStats implements Parcelable {
// Platform-level low power state stats
public String statPlatformIdleState;
+ public String statSubsystemPowerState;
public HistoryStepDetails() {
clear();
@@ -1250,6 +1251,7 @@ public abstract class BatteryStats implements Parcelable {
out.writeInt(statSoftIrqTime);
out.writeInt(statIdlTime);
out.writeString(statPlatformIdleState);
+ out.writeString(statSubsystemPowerState);
}
public void readFromParcel(Parcel in) {
@@ -1271,6 +1273,7 @@ public abstract class BatteryStats implements Parcelable {
statSoftIrqTime = in.readInt();
statIdlTime = in.readInt();
statPlatformIdleState = in.readString();
+ statSubsystemPowerState = in.readString();
}
}
@@ -5543,6 +5546,10 @@ public abstract class BatteryStats implements Parcelable {
pw.print(", PlatformIdleStat ");
pw.print(rec.stepDetails.statPlatformIdleState);
pw.println();
+
+ pw.print(", SubsystemPowerState ");
+ pw.print(rec.stepDetails.statSubsystemPowerState);
+ pw.println();
} else {
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
@@ -5580,6 +5587,11 @@ public abstract class BatteryStats implements Parcelable {
pw.print(rec.stepDetails.statPlatformIdleState);
}
pw.println();
+
+ if (rec.stepDetails.statSubsystemPowerState != null) {
+ pw.print(rec.stepDetails.statSubsystemPowerState);
+ }
+ pw.println();
}
}
oldState = rec.states;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 46942bf429c5..cbe4c15cf790 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -171,6 +171,7 @@ public class BatteryStatsImpl extends BatteryStats {
public interface PlatformIdleStateCallback {
public String getPlatformLowPowerStats();
+ public String getSubsystemLowPowerStats();
}
private final PlatformIdleStateCallback mPlatformIdleStateCallback;
@@ -2878,6 +2879,12 @@ public class BatteryStatsImpl extends BatteryStats {
mPlatformIdleStateCallback.getPlatformLowPowerStats();
if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
mCurHistoryStepDetails.statPlatformIdleState);
+
+ mCurHistoryStepDetails.statSubsystemPowerState =
+ mPlatformIdleStateCallback.getSubsystemLowPowerStats();
+ if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
+ mCurHistoryStepDetails.statSubsystemPowerState);
+
}
computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
if (includeStepDetails != 0) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c20221bfe4aa..06ab75a8fb40 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -188,6 +188,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
+ private native int getSubsystemLowPowerStats(ByteBuffer outBuffer);
private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE)
@@ -219,6 +220,28 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ @Override
+ public String getSubsystemLowPowerStats() {
+ Slog.d(TAG, "begin getSubsystemLowPowerStats");
+ try {
+ mUtf8BufferStat.clear();
+ mUtf16BufferStat.clear();
+ mDecoderStat.reset();
+ int bytesWritten = getSubsystemLowPowerStats(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();
+ } finally {
+ Slog.d(TAG, "end getSubsystemLowPowerStats");
+ }
+ }
+
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!).
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 362dd9fbb17a..a3d28bbd3754 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -95,6 +95,7 @@ LOCAL_SHARED_LIBRARIES += \
android.hardware.ir@1.0 \
android.hardware.light@2.0 \
android.hardware.power@1.0 \
+ android.hardware.power@1.1 \
android.hardware.tetheroffload.config@1.0 \
android.hardware.thermal@1.0 \
android.hardware.tv.cec@1.0 \
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 57bb9fedc135..37ae78254ce2 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <android/hardware/power/1.0/IPower.h>
+#include <android/hardware/power/1.1/IPower.h>
#include <android_runtime/AndroidRuntime.h>
#include <jni.h>
@@ -46,6 +47,8 @@ using android::hardware::power::V1_0::IPower;
using android::hardware::power::V1_0::PowerStatePlatformSleepState;
using android::hardware::power::V1_0::PowerStateVoter;
using android::hardware::power::V1_0::Status;
+using android::hardware::power::V1_1::PowerStateSubsystem;
+using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
using android::hardware::hidl_vec;
namespace android
@@ -263,9 +266,105 @@ static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject o
return total_added;
}
+static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
+ char *output = (char*)env->GetDirectBufferAddress(outBuf);
+ char *offset = output;
+ int remaining = (int)env->GetDirectBufferCapacity(outBuf);
+ int total_added = -1;
+
+ //This is a IPower 1.1 API
+ sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 = nullptr;
+
+ if (outBuf == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", "null argument");
+ return -1;
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(gPowerHalMutex);
+ if (!getPowerHal()) {
+ ALOGE("Power Hal not loaded");
+ return -1;
+ }
+
+ //Trying to cast to 1.1, this will succeed only for devices supporting 1.1
+ gPowerHal_1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHal);
+ if (gPowerHal_1_1 == nullptr) {
+ //This device does not support IPower@1.1, exiting gracefully
+ return 0;
+ }
+
+ Return<void> ret = gPowerHal_1_1->getSubsystemLowPowerStats(
+ [&offset, &remaining, &total_added](hidl_vec<PowerStateSubsystem> subsystems,
+ Status status) {
+
+ if (status != Status::SUCCESS)
+ return;
+
+ for (size_t i = 0; i < subsystems.size(); i++) {
+ int added;
+ const PowerStateSubsystem &subsystem = subsystems[i];
+
+ added = snprintf(offset, remaining,
+ "subsystem_%zu name=%s ", i + 1, subsystem.name.c_str());
+ if (added < 0) {
+ break;
+ }
+
+ if (added > remaining) {
+ added = remaining;
+ }
+
+ offset += added;
+ remaining -= added;
+ total_added += added;
+
+ for (size_t j = 0; j < subsystem.states.size(); j++) {
+ const PowerStateSubsystemSleepState& state = subsystem.states[j];
+ added = snprintf(offset, remaining,
+ "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry TS(ms)=%" PRIu64 " ",
+ j + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
+ state.totalTransitions, state.lastEntryTimestampMs);
+ 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("PowerHal: buffer not enough");
+ break;
+ }
+ }
+ }
+ );
+
+ if (!ret.isOk()) {
+ ALOGE("getSubsystemLowPowerStats() failed: power HAL service not available");
+ gPowerHal = nullptr;
+ return -1;
+ }
+ }
+
+ *offset = 0;
+ total_added += 1;
+ return total_added;
+}
+
static const JNINativeMethod method_table[] = {
{ "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
{ "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats },
+ { "getSubsystemLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getSubsystemLowPowerStats },
};
int register_android_server_BatteryStatsService(JNIEnv *env)