From 060a1ca3ffd1d1f36e0daca73f4bd510b8978a75 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Fri, 16 Oct 2020 23:58:14 +0000 Subject: [PATCH] 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 --- ..._android_server_am_BatteryStatsService.cpp | 68 ++++++++++++------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index b08868e2c7f8c..0e68f5b89a914 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "BatteryStatsService" //#define LOG_NDEBUG 0 -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #include #include @@ -46,15 +46,16 @@ #include #include +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 mWakeupReasons; static sem_t wakeup_sem; extern sp getPowerHalHidlV1_0(); extern sp getPowerHalHidlV1_1(); @@ -84,7 +84,8 @@ std::unordered_map> gPowerStatsHalStateNames = {}; std::vector gPowerStatsHalPlatformIds = {}; std::vector gPowerStatsHalSubsystemIds = {}; -sp gPowerStatsHalV1_0 = nullptr; +sp gPowerStatsHalV1_0 = nullptr; + std::function gGetLowPowerStatsImpl = {}; std::function gGetPlatformLowPowerStatsImpl = {}; std::function gGetSubsystemLowPowerStatsImpl = {}; @@ -115,9 +116,25 @@ struct PowerHalDeathRecipient : virtual public hardware::hidl_death_recipient { sp gDeathRecipient = new PowerHalDeathRecipient(); class WakeupCallback : public BnSuspendCallback { - public: - binder::Status notifyWakeup(bool success) override { +public: + binder::Status notifyWakeup(bool success, + const std::vector& wakeupReasons) override { ALOGI("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted"); + bool reasonsCaptured = false; + { + std::unique_lock 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 wakeupReasons; + { + std::unique_lock 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(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;