BatteryStats: update to use new notifyWakeup with wakeup reasons

As SystemSuspend support notifyWakeup callback with wakeup reason
embedded, BatteryStats no longer required to pull such reasons from
kernel files by itself.

Test: adb shell dumpsys batterystats --history
Bug: 171021049
Change-Id: I69717387586994b744297f5ac0f5b66ef2bdce32
This commit is contained in:
Michael Sun
2020-10-16 23:58:14 +00:00
parent a09d15adb3
commit 060a1ca3ff

View File

@@ -17,7 +17,6 @@
#define LOG_TAG "BatteryStatsService"
//#define LOG_NDEBUG 0
#include <climits>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -28,6 +27,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <climits>
#include <unordered_map>
#include <utility>
@@ -46,15 +46,16 @@
#include <utils/misc.h>
#include <utils/Log.h>
using android::hardware::hidl_vec;
using android::hardware::Return;
using android::hardware::Void;
using android::system::suspend::BnSuspendCallback;
using android::hardware::power::stats::V1_0::IPowerStats;
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;
using android::system::suspend::BnSuspendCallback;
using android::system::suspend::ISuspendControlService;
using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower;
@@ -62,10 +63,9 @@ using IPowerV1_0 = android::hardware::power::V1_0::IPower;
namespace android
{
#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason"
#define MAX_REASON_SIZE 512
static bool wakeup_init = false;
static std::mutex mReasonsMutex;
static std::vector<std::string> mWakeupReasons;
static sem_t wakeup_sem;
extern sp<IPowerV1_0> getPowerHalHidlV1_0();
extern sp<IPowerV1_1> getPowerHalHidlV1_1();
@@ -84,7 +84,8 @@ std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>>
gPowerStatsHalStateNames = {};
std::vector<uint32_t> gPowerStatsHalPlatformIds = {};
std::vector<uint32_t> gPowerStatsHalSubsystemIds = {};
sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0 = nullptr;
sp<IPowerStats> gPowerStatsHalV1_0 = nullptr;
std::function<void(JNIEnv*, jobject)> gGetLowPowerStatsImpl = {};
std::function<jint(JNIEnv*, jobject)> gGetPlatformLowPowerStatsImpl = {};
std::function<jint(JNIEnv*, jobject)> gGetSubsystemLowPowerStatsImpl = {};
@@ -115,9 +116,25 @@ struct PowerHalDeathRecipient : virtual public hardware::hidl_death_recipient {
sp<PowerHalDeathRecipient> gDeathRecipient = new PowerHalDeathRecipient();
class WakeupCallback : public BnSuspendCallback {
public:
binder::Status notifyWakeup(bool success) override {
public:
binder::Status notifyWakeup(bool success,
const std::vector<std::string>& wakeupReasons) override {
ALOGI("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
bool reasonsCaptured = false;
{
std::unique_lock<std::mutex> reasonsLock(mReasonsMutex, std::defer_lock);
if (reasonsLock.try_lock() && mWakeupReasons.empty()) {
mWakeupReasons = std::move(wakeupReasons);
reasonsCaptured = true;
}
}
if (!reasonsCaptured) {
ALOGE("Failed to write wakeup reasons. Reasons dropped:");
for (auto wakeupReason : wakeupReasons) {
ALOGE("\t%s", wakeupReason.c_str());
}
}
int ret = sem_post(&wakeup_sem);
if (ret < 0) {
char buf[80];
@@ -157,8 +174,6 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
// Wait for wakeup.
ALOGV("Waiting for wakeup...");
// TODO(b/116747600): device can suspend and wakeup after sem_wait() finishes and before wakeup
// reason is recorded, i.e. BatteryStats might occasionally miss wakeup events.
int ret = sem_wait(&wakeup_sem);
if (ret < 0) {
char buf[80];
@@ -168,20 +183,27 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
return 0;
}
FILE *fp = fopen(LAST_RESUME_REASON, "r");
if (fp == NULL) {
ALOGE("Failed to open %s", LAST_RESUME_REASON);
return -1;
}
char* mergedreason = (char*)env->GetDirectBufferAddress(outBuf);
int remainreasonlen = (int)env->GetDirectBufferCapacity(outBuf);
ALOGV("Reading wakeup reasons");
std::vector<std::string> wakeupReasons;
{
std::unique_lock<std::mutex> reasonsLock(mReasonsMutex, std::defer_lock);
if (reasonsLock.try_lock() && !mWakeupReasons.empty()) {
wakeupReasons = std::move(mWakeupReasons);
mWakeupReasons.clear();
}
}
if (wakeupReasons.empty()) {
return 0;
}
char* mergedreasonpos = mergedreason;
char reasonline[128];
int i = 0;
while (fgets(reasonline, sizeof(reasonline), fp) != NULL) {
for (auto wakeupReason : wakeupReasons) {
auto reasonline = const_cast<char*>(wakeupReason.c_str());
char* pos = reasonline;
char* endPos;
int len;
@@ -238,10 +260,6 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
*mergedreasonpos = 0;
}
if (fclose(fp) != 0) {
ALOGE("Failed to close %s", LAST_RESUME_REASON);
return -1;
}
return mergedreasonpos - mergedreason;
}
@@ -340,7 +358,7 @@ static bool initializePowerStats() {
// The caller must be holding gPowerHalMutex.
static bool getPowerStatsHalLocked() {
if (gPowerStatsHalV1_0 == nullptr) {
gPowerStatsHalV1_0 = android::hardware::power::stats::V1_0::IPowerStats::getService();
gPowerStatsHalV1_0 = IPowerStats::getService();
if (gPowerStatsHalV1_0 == nullptr) {
ALOGE("Unable to get power.stats HAL service.");
return false;
@@ -833,7 +851,7 @@ static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) {
static void setUpPowerStatsLocked() {
// First see if power.stats HAL is available. Fall back to power HAL if
// power.stats HAL is unavailable.
if (android::hardware::power::stats::V1_0::IPowerStats::getService() != nullptr) {
if (IPowerStats::getService() != nullptr) {
ALOGI("Using power.stats HAL");
gGetLowPowerStatsImpl = getPowerStatsHalLowPowerData;
gGetPlatformLowPowerStatsImpl = getPowerStatsHalPlatformData;