/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define DEBUG false // STOPSHIP if true #include "Log.h" #include <android/hardware/power/1.0/IPower.h> #include <android/hardware/power/1.1/IPower.h> #include <fcntl.h> #include <hardware/power.h> #include <hardware_legacy/power.h> #include <inttypes.h> #include <semaphore.h> #include <stddef.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "external/SubsystemSleepStatePuller.h" #include "external/StatsPuller.h" #include "SubsystemSleepStatePuller.h" #include "logd/LogEvent.h" #include "statslog.h" #include "stats_log_util.h" using android::hardware::hidl_vec; 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::Return; using android::hardware::Void; using std::make_shared; using std::shared_ptr; namespace android { namespace os { namespace statsd { sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0 = nullptr; sp<android::hardware::power::V1_1::IPower> gPowerHalV1_1 = nullptr; std::mutex gPowerHalMutex; bool gPowerHalExists = true; bool getPowerHal() { if (gPowerHalExists && gPowerHalV1_0 == nullptr) { gPowerHalV1_0 = android::hardware::power::V1_0::IPower::getService(); if (gPowerHalV1_0 != nullptr) { gPowerHalV1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0); ALOGI("Loaded power HAL service"); } else { ALOGW("Couldn't load power HAL service"); gPowerHalExists = false; } } return gPowerHalV1_0 != nullptr; } SubsystemSleepStatePuller::SubsystemSleepStatePuller() : StatsPuller(android::util::SUBSYSTEM_SLEEP_STATE) { } bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { std::lock_guard<std::mutex> lock(gPowerHalMutex); if (!getPowerHal()) { ALOGE("Power Hal not loaded"); return false; } int64_t wallClockTimestampNs = getWallClockNs(); int64_t elapsedTimestampNs = getElapsedRealtimeNs(); data->clear(); Return<void> ret; ret = gPowerHalV1_0->getPlatformLowPowerStats( [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStatePlatformSleepState> states, Status status) { if (status != Status::SUCCESS) return; for (size_t i = 0; i < states.size(); i++) { const PowerStatePlatformSleepState& state = states[i]; auto statePtr = make_shared<LogEvent>( android::util::SUBSYSTEM_SLEEP_STATE, wallClockTimestampNs, elapsedTimestampNs); statePtr->write(state.name); statePtr->write(""); statePtr->write(state.totalTransitions); statePtr->write(state.residencyInMsecSinceBoot); statePtr->init(); data->push_back(statePtr); VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(), (long long)state.residencyInMsecSinceBoot, (long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0); for (auto voter : state.voters) { auto voterPtr = make_shared<LogEvent>( android::util::SUBSYSTEM_SLEEP_STATE, wallClockTimestampNs, elapsedTimestampNs); voterPtr->write(state.name); voterPtr->write(voter.name); voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot); voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot); voterPtr->init(); data->push_back(voterPtr); VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(), voter.name.c_str(), (long long)voter.totalTimeInMsecVotedForSinceBoot, (long long)voter.totalNumberOfTimesVotedSinceBoot); } } }); if (!ret.isOk()) { ALOGE("getLowPowerStats() failed: power HAL service not available"); gPowerHalV1_0 = nullptr; return false; } // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1 sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0); if (gPowerHal_1_1 != nullptr) { ret = gPowerHal_1_1->getSubsystemLowPowerStats( [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStateSubsystem> subsystems, Status status) { if (status != Status::SUCCESS) return; if (subsystems.size() > 0) { for (size_t i = 0; i < subsystems.size(); i++) { const PowerStateSubsystem& subsystem = subsystems[i]; for (size_t j = 0; j < subsystem.states.size(); j++) { const PowerStateSubsystemSleepState& state = subsystem.states[j]; auto subsystemStatePtr = make_shared<LogEvent>( android::util::SUBSYSTEM_SLEEP_STATE, wallClockTimestampNs, elapsedTimestampNs); subsystemStatePtr->write(subsystem.name); subsystemStatePtr->write(state.name); subsystemStatePtr->write(state.totalTransitions); subsystemStatePtr->write(state.residencyInMsecSinceBoot); subsystemStatePtr->init(); data->push_back(subsystemStatePtr); VLOG("subsystemstate: %s, %s, %lld, %lld, %lld", subsystem.name.c_str(), state.name.c_str(), (long long)state.residencyInMsecSinceBoot, (long long)state.totalTransitions, (long long)state.lastEntryTimestampMs); } } } }); } return true; } } // namespace statsd } // namespace os } // namespace android