Merge "BatteryStats: update to use new notifyWakeup with wakeup reasons"

This commit is contained in:
Michael Sun
2020-10-27 20:40:45 +00:00
committed by Gerrit Code Review

View File

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