Loading power/stats/1.0/default/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and cc_library_shared { cc_binary { name: "android.hardware.power.stats@1.0-service", relative_install_path: "hw", init_rc: ["android.hardware.power.stats@1.0-service.rc"], Loading power/stats/1.0/default/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line krossmo@google.com bsschwar@google.com tstrudel@google.com power/stats/1.0/default/PowerStats.cpp +201 −8 Original line number Diff line number Diff line Loading @@ -287,25 +287,218 @@ Return<void> PowerStats::streamEnergyData(uint32_t timeMs, uint32_t samplingRate return Void(); } uint32_t PowerStats::addPowerEntity(const std::string& name, PowerEntityType type) { uint32_t id = mPowerEntityInfos.size(); mPowerEntityInfos.push_back({id, name, type}); return id; } void PowerStats::addStateResidencyDataProvider(std::shared_ptr<IStateResidencyDataProvider> p) { std::vector<PowerEntityStateSpace> stateSpaces = p->getStateSpaces(); for (auto stateSpace : stateSpaces) { mPowerEntityStateSpaces.emplace(stateSpace.powerEntityId, stateSpace); mStateResidencyDataProviders.emplace(stateSpace.powerEntityId, p); } } Return<void> PowerStats::getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) { hidl_vec<PowerEntityInfo> eInfo; _hidl_cb(eInfo, Status::NOT_SUPPORTED); // If not configured, return NOT_SUPPORTED if (mPowerEntityInfos.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } _hidl_cb(mPowerEntityInfos, Status::SUCCESS); return Void(); } Return<void> PowerStats::getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateInfo_cb _hidl_cb) { (void)powerEntityIds; hidl_vec<PowerEntityStateSpace> powerEntityStateSpaces; _hidl_cb(powerEntityStateSpaces, Status::NOT_SUPPORTED); // If not configured, return NOT_SUPPORTED if (mPowerEntityStateSpaces.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } std::vector<PowerEntityStateSpace> stateSpaces; // If powerEntityIds is empty then return state space info for all entities if (powerEntityIds.size() == 0) { stateSpaces.reserve(mPowerEntityStateSpaces.size()); for (auto i : mPowerEntityStateSpaces) { stateSpaces.emplace_back(i.second); } _hidl_cb(stateSpaces, Status::SUCCESS); return Void(); } // Return state space information only for valid ids auto ret = Status::SUCCESS; stateSpaces.reserve(powerEntityIds.size()); for (const uint32_t id : powerEntityIds) { auto stateSpace = mPowerEntityStateSpaces.find(id); if (stateSpace != mPowerEntityStateSpaces.end()) { stateSpaces.emplace_back(stateSpace->second); } else { ret = Status::INVALID_INPUT; } } _hidl_cb(stateSpaces, ret); return Void(); } Return<void> PowerStats::getPowerEntityStateResidencyData( const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) { (void)powerEntityIds; // If not configured, return NOT_SUPPORTED if (mStateResidencyDataProviders.empty() || mPowerEntityStateSpaces.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } // If powerEntityIds is empty then return data for all supported entities if (powerEntityIds.size() == 0) { std::vector<uint32_t> ids; for (auto stateSpace : mPowerEntityStateSpaces) { ids.emplace_back(stateSpace.first); } return getPowerEntityStateResidencyData(ids, _hidl_cb); } std::unordered_map<uint32_t, PowerEntityStateResidencyResult> stateResidencies; std::vector<PowerEntityStateResidencyResult> results; results.reserve(powerEntityIds.size()); // return results for only the given powerEntityIds bool invalidInput = false; bool filesystemError = false; for (auto id : powerEntityIds) { auto dataProvider = mStateResidencyDataProviders.find(id); // skip if the given powerEntityId does not have an associated StateResidencyDataProvider if (dataProvider == mStateResidencyDataProviders.end()) { invalidInput = true; continue; } // get the results if we have not already done so. if (stateResidencies.find(id) == stateResidencies.end()) { if (!dataProvider->second->getResults(stateResidencies)) { filesystemError = true; } } // append results auto stateResidency = stateResidencies.find(id); if (stateResidency != stateResidencies.end()) { results.emplace_back(stateResidency->second); } } auto ret = Status::SUCCESS; if (filesystemError) { ret = Status::FILESYSTEM_ERROR; } else if (invalidInput) { ret = Status::INVALID_INPUT; } _hidl_cb(results, ret); return Void(); } bool DumpResidencyDataToFd(const hidl_vec<PowerEntityInfo>& infos, const hidl_vec<PowerEntityStateSpace>& stateSpaces, const hidl_vec<PowerEntityStateResidencyResult>& results, int fd) { // construct lookup table of powerEntityId to name std::unordered_map<uint32_t, std::string> entityNames; for (auto info : infos) { entityNames.emplace(info.powerEntityId, info.powerEntityName); } // construct lookup table of powerEntityId, powerEntityStateId to state name std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> stateNames; for (auto stateSpace : stateSpaces) { stateNames.emplace(stateSpace.powerEntityId, std::unordered_map<uint32_t, std::string>()); for (auto state : stateSpace.states) { stateNames.at(stateSpace.powerEntityId) .emplace(state.powerEntityStateId, state.powerEntityStateName); } } std::ostringstream dumpStats; dumpStats << "\n========== PowerStats HAL 1.0 state residencies ==========\n"; const char* headerFormat = " %14s %14s %16s %15s %16s\n"; const char* dataFormat = " %14s %14s %13" PRIu64 " ms %15" PRIu64 " %13" PRIu64 " ms\n"; dumpStats << android::base::StringPrintf(headerFormat, "Entity", "State", "Total time", "Total entries", "Last entry timestamp"); for (auto result : results) { for (auto stateResidency : result.stateResidencyData) { dumpStats << android::base::StringPrintf( dataFormat, entityNames.at(result.powerEntityId).c_str(), stateNames.at(result.powerEntityId) .at(stateResidency.powerEntityStateId) .c_str(), stateResidency.totalTimeInStateMs, stateResidency.totalStateEntryCount, stateResidency.lastEntryTimestampMs); } } dumpStats << "========== End of PowerStats HAL 1.0 state residencies ==========\n"; return android::base::WriteStringToFd(dumpStats.str(), fd); } Return<void> PowerStats::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) { if (handle == nullptr || handle->numFds < 1) { return Void(); } int fd = handle->data[0]; Status status; hidl_vec<PowerEntityInfo> infos; // Get power entity information getPowerEntityInfo([&status, &infos](auto rInfos, auto rStatus) { status = rStatus; infos = rInfos; }); if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting power entity info"; return Void(); } // Get power entity state information hidl_vec<PowerEntityStateSpace> stateSpaces; getPowerEntityStateInfo({}, [&status, &stateSpaces](auto rStateSpaces, auto rStatus) { status = rStatus; stateSpaces = rStateSpaces; }); if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting state info"; return Void(); } // Get power entity state residency data hidl_vec<PowerEntityStateResidencyResult> results; _hidl_cb(results, Status::NOT_SUPPORTED); getPowerEntityStateResidencyData({}, [&status, &results](auto rResults, auto rStatus) { status = rStatus; results = rResults; }); // This implementation of getPowerEntityStateResidencyData supports the // return of partial results if status == FILESYSTEM_ERROR. if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting residency data -- Some results missing"; } if (!DumpResidencyDataToFd(infos, stateSpaces, results, fd)) { PLOG(ERROR) << "Failed to dump residency data to fd"; } fsync(fd); return Void(); } Loading power/stats/1.0/default/PowerStats.h +19 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <fmq/MessageQueue.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h> #include <unordered_map> namespace android { namespace hardware { Loading Loading @@ -60,8 +61,19 @@ struct OnDeviceMmt { std::unique_ptr<MessageQueueSync> fmqSynchronized; }; class IStateResidencyDataProvider { public: virtual ~IStateResidencyDataProvider() = default; virtual bool getResults( std::unordered_map<uint32_t, PowerEntityStateResidencyResult>& results) = 0; virtual std::vector<PowerEntityStateSpace> getStateSpaces() = 0; }; struct PowerStats : public IPowerStats { public: PowerStats(); uint32_t addPowerEntity(const std::string& name, PowerEntityType type); void addStateResidencyDataProvider(std::shared_ptr<IStateResidencyDataProvider> p); // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow. Return<void> getRailInfo(getRailInfo_cb _hidl_cb) override; Return<void> getEnergyData(const hidl_vec<uint32_t>& railIndices, Loading @@ -75,12 +87,19 @@ struct PowerStats : public IPowerStats { const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) override; // Methods from ::android::hidl::base::V1_0::IBase follow. Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override; private: OnDeviceMmt mPm; void findIioPowerMonitorNodes(); size_t parsePowerRails(); int parseIioEnergyNode(std::string devName); Status parseIioEnergyNodes(); std::vector<PowerEntityInfo> mPowerEntityInfos; std::unordered_map<uint32_t, PowerEntityStateSpace> mPowerEntityStateSpaces; std::unordered_map<uint32_t, std::shared_ptr<IStateResidencyDataProvider>> mStateResidencyDataProviders; }; } // namespace implementation Loading power/stats/1.0/default/service.cpp +53 −1 Original line number Diff line number Diff line Loading @@ -31,17 +31,69 @@ using android::hardware::joinRpcThreadpool; // Generated HIDL files using android::hardware::power::stats::V1_0::IPowerStats; using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult; using android::hardware::power::stats::V1_0::PowerEntityStateSpace; using android::hardware::power::stats::V1_0::PowerEntityType; using android::hardware::power::stats::V1_0::implementation::IStateResidencyDataProvider; using android::hardware::power::stats::V1_0::implementation::PowerStats; class DefaultStateResidencyDataProvider : public IStateResidencyDataProvider { public: DefaultStateResidencyDataProvider(uint32_t id) : mPowerEntityId(id), mActiveStateId(0), mSleepStateId(1) {} ~DefaultStateResidencyDataProvider() = default; bool getResults(std::unordered_map<uint32_t, PowerEntityStateResidencyResult>& results) { PowerEntityStateResidencyResult result = { .powerEntityId = mPowerEntityId }; result.stateResidencyData.resize(2); // Using fake numbers here for display only. A real implementation would // use actual tracked stats. result.stateResidencyData[0] = { .powerEntityStateId = mActiveStateId, .totalTimeInStateMs = 1, .totalStateEntryCount = 2, .lastEntryTimestampMs = 3 }; result.stateResidencyData[1] = { .powerEntityStateId = mSleepStateId, .totalTimeInStateMs = 4, .totalStateEntryCount = 5, .lastEntryTimestampMs = 6, }; results.emplace(mPowerEntityId, result); return true; } std::vector<PowerEntityStateSpace> getStateSpaces() { return {{ .powerEntityId = mPowerEntityId, .states = { {.powerEntityStateId = mActiveStateId, .powerEntityStateName = "Active"}, {.powerEntityStateId = mSleepStateId, .powerEntityStateName = "Sleep"} } }}; } private: const uint32_t mPowerEntityId; const uint32_t mActiveStateId; const uint32_t mSleepStateId; }; int main(int /* argc */, char** /* argv */) { ALOGI("power.stats service 1.0 is starting."); android::sp<IPowerStats> service = new PowerStats(); PowerStats* service = new PowerStats(); if (service == nullptr) { ALOGE("Can not create an instance of power.stats HAL Iface, exiting."); return 1; } uint32_t defaultId = service->addPowerEntity("DefaultEntity", PowerEntityType::SUBSYSTEM); auto defaultSdp = std::make_shared<DefaultStateResidencyDataProvider>(defaultId); service->addStateResidencyDataProvider(std::move(defaultSdp)); configureRpcThreadpool(1, true /*callerWillJoin*/); status_t status = service->registerAsService(); Loading Loading
power/stats/1.0/default/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and cc_library_shared { cc_binary { name: "android.hardware.power.stats@1.0-service", relative_install_path: "hw", init_rc: ["android.hardware.power.stats@1.0-service.rc"], Loading
power/stats/1.0/default/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line krossmo@google.com bsschwar@google.com tstrudel@google.com
power/stats/1.0/default/PowerStats.cpp +201 −8 Original line number Diff line number Diff line Loading @@ -287,25 +287,218 @@ Return<void> PowerStats::streamEnergyData(uint32_t timeMs, uint32_t samplingRate return Void(); } uint32_t PowerStats::addPowerEntity(const std::string& name, PowerEntityType type) { uint32_t id = mPowerEntityInfos.size(); mPowerEntityInfos.push_back({id, name, type}); return id; } void PowerStats::addStateResidencyDataProvider(std::shared_ptr<IStateResidencyDataProvider> p) { std::vector<PowerEntityStateSpace> stateSpaces = p->getStateSpaces(); for (auto stateSpace : stateSpaces) { mPowerEntityStateSpaces.emplace(stateSpace.powerEntityId, stateSpace); mStateResidencyDataProviders.emplace(stateSpace.powerEntityId, p); } } Return<void> PowerStats::getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) { hidl_vec<PowerEntityInfo> eInfo; _hidl_cb(eInfo, Status::NOT_SUPPORTED); // If not configured, return NOT_SUPPORTED if (mPowerEntityInfos.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } _hidl_cb(mPowerEntityInfos, Status::SUCCESS); return Void(); } Return<void> PowerStats::getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateInfo_cb _hidl_cb) { (void)powerEntityIds; hidl_vec<PowerEntityStateSpace> powerEntityStateSpaces; _hidl_cb(powerEntityStateSpaces, Status::NOT_SUPPORTED); // If not configured, return NOT_SUPPORTED if (mPowerEntityStateSpaces.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } std::vector<PowerEntityStateSpace> stateSpaces; // If powerEntityIds is empty then return state space info for all entities if (powerEntityIds.size() == 0) { stateSpaces.reserve(mPowerEntityStateSpaces.size()); for (auto i : mPowerEntityStateSpaces) { stateSpaces.emplace_back(i.second); } _hidl_cb(stateSpaces, Status::SUCCESS); return Void(); } // Return state space information only for valid ids auto ret = Status::SUCCESS; stateSpaces.reserve(powerEntityIds.size()); for (const uint32_t id : powerEntityIds) { auto stateSpace = mPowerEntityStateSpaces.find(id); if (stateSpace != mPowerEntityStateSpaces.end()) { stateSpaces.emplace_back(stateSpace->second); } else { ret = Status::INVALID_INPUT; } } _hidl_cb(stateSpaces, ret); return Void(); } Return<void> PowerStats::getPowerEntityStateResidencyData( const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) { (void)powerEntityIds; // If not configured, return NOT_SUPPORTED if (mStateResidencyDataProviders.empty() || mPowerEntityStateSpaces.empty()) { _hidl_cb({}, Status::NOT_SUPPORTED); return Void(); } // If powerEntityIds is empty then return data for all supported entities if (powerEntityIds.size() == 0) { std::vector<uint32_t> ids; for (auto stateSpace : mPowerEntityStateSpaces) { ids.emplace_back(stateSpace.first); } return getPowerEntityStateResidencyData(ids, _hidl_cb); } std::unordered_map<uint32_t, PowerEntityStateResidencyResult> stateResidencies; std::vector<PowerEntityStateResidencyResult> results; results.reserve(powerEntityIds.size()); // return results for only the given powerEntityIds bool invalidInput = false; bool filesystemError = false; for (auto id : powerEntityIds) { auto dataProvider = mStateResidencyDataProviders.find(id); // skip if the given powerEntityId does not have an associated StateResidencyDataProvider if (dataProvider == mStateResidencyDataProviders.end()) { invalidInput = true; continue; } // get the results if we have not already done so. if (stateResidencies.find(id) == stateResidencies.end()) { if (!dataProvider->second->getResults(stateResidencies)) { filesystemError = true; } } // append results auto stateResidency = stateResidencies.find(id); if (stateResidency != stateResidencies.end()) { results.emplace_back(stateResidency->second); } } auto ret = Status::SUCCESS; if (filesystemError) { ret = Status::FILESYSTEM_ERROR; } else if (invalidInput) { ret = Status::INVALID_INPUT; } _hidl_cb(results, ret); return Void(); } bool DumpResidencyDataToFd(const hidl_vec<PowerEntityInfo>& infos, const hidl_vec<PowerEntityStateSpace>& stateSpaces, const hidl_vec<PowerEntityStateResidencyResult>& results, int fd) { // construct lookup table of powerEntityId to name std::unordered_map<uint32_t, std::string> entityNames; for (auto info : infos) { entityNames.emplace(info.powerEntityId, info.powerEntityName); } // construct lookup table of powerEntityId, powerEntityStateId to state name std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> stateNames; for (auto stateSpace : stateSpaces) { stateNames.emplace(stateSpace.powerEntityId, std::unordered_map<uint32_t, std::string>()); for (auto state : stateSpace.states) { stateNames.at(stateSpace.powerEntityId) .emplace(state.powerEntityStateId, state.powerEntityStateName); } } std::ostringstream dumpStats; dumpStats << "\n========== PowerStats HAL 1.0 state residencies ==========\n"; const char* headerFormat = " %14s %14s %16s %15s %16s\n"; const char* dataFormat = " %14s %14s %13" PRIu64 " ms %15" PRIu64 " %13" PRIu64 " ms\n"; dumpStats << android::base::StringPrintf(headerFormat, "Entity", "State", "Total time", "Total entries", "Last entry timestamp"); for (auto result : results) { for (auto stateResidency : result.stateResidencyData) { dumpStats << android::base::StringPrintf( dataFormat, entityNames.at(result.powerEntityId).c_str(), stateNames.at(result.powerEntityId) .at(stateResidency.powerEntityStateId) .c_str(), stateResidency.totalTimeInStateMs, stateResidency.totalStateEntryCount, stateResidency.lastEntryTimestampMs); } } dumpStats << "========== End of PowerStats HAL 1.0 state residencies ==========\n"; return android::base::WriteStringToFd(dumpStats.str(), fd); } Return<void> PowerStats::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) { if (handle == nullptr || handle->numFds < 1) { return Void(); } int fd = handle->data[0]; Status status; hidl_vec<PowerEntityInfo> infos; // Get power entity information getPowerEntityInfo([&status, &infos](auto rInfos, auto rStatus) { status = rStatus; infos = rInfos; }); if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting power entity info"; return Void(); } // Get power entity state information hidl_vec<PowerEntityStateSpace> stateSpaces; getPowerEntityStateInfo({}, [&status, &stateSpaces](auto rStateSpaces, auto rStatus) { status = rStatus; stateSpaces = rStateSpaces; }); if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting state info"; return Void(); } // Get power entity state residency data hidl_vec<PowerEntityStateResidencyResult> results; _hidl_cb(results, Status::NOT_SUPPORTED); getPowerEntityStateResidencyData({}, [&status, &results](auto rResults, auto rStatus) { status = rStatus; results = rResults; }); // This implementation of getPowerEntityStateResidencyData supports the // return of partial results if status == FILESYSTEM_ERROR. if (status != Status::SUCCESS) { LOG(ERROR) << "Error getting residency data -- Some results missing"; } if (!DumpResidencyDataToFd(infos, stateSpaces, results, fd)) { PLOG(ERROR) << "Failed to dump residency data to fd"; } fsync(fd); return Void(); } Loading
power/stats/1.0/default/PowerStats.h +19 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <fmq/MessageQueue.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h> #include <unordered_map> namespace android { namespace hardware { Loading Loading @@ -60,8 +61,19 @@ struct OnDeviceMmt { std::unique_ptr<MessageQueueSync> fmqSynchronized; }; class IStateResidencyDataProvider { public: virtual ~IStateResidencyDataProvider() = default; virtual bool getResults( std::unordered_map<uint32_t, PowerEntityStateResidencyResult>& results) = 0; virtual std::vector<PowerEntityStateSpace> getStateSpaces() = 0; }; struct PowerStats : public IPowerStats { public: PowerStats(); uint32_t addPowerEntity(const std::string& name, PowerEntityType type); void addStateResidencyDataProvider(std::shared_ptr<IStateResidencyDataProvider> p); // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow. Return<void> getRailInfo(getRailInfo_cb _hidl_cb) override; Return<void> getEnergyData(const hidl_vec<uint32_t>& railIndices, Loading @@ -75,12 +87,19 @@ struct PowerStats : public IPowerStats { const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) override; // Methods from ::android::hidl::base::V1_0::IBase follow. Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override; private: OnDeviceMmt mPm; void findIioPowerMonitorNodes(); size_t parsePowerRails(); int parseIioEnergyNode(std::string devName); Status parseIioEnergyNodes(); std::vector<PowerEntityInfo> mPowerEntityInfos; std::unordered_map<uint32_t, PowerEntityStateSpace> mPowerEntityStateSpaces; std::unordered_map<uint32_t, std::shared_ptr<IStateResidencyDataProvider>> mStateResidencyDataProviders; }; } // namespace implementation Loading
power/stats/1.0/default/service.cpp +53 −1 Original line number Diff line number Diff line Loading @@ -31,17 +31,69 @@ using android::hardware::joinRpcThreadpool; // Generated HIDL files using android::hardware::power::stats::V1_0::IPowerStats; using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult; using android::hardware::power::stats::V1_0::PowerEntityStateSpace; using android::hardware::power::stats::V1_0::PowerEntityType; using android::hardware::power::stats::V1_0::implementation::IStateResidencyDataProvider; using android::hardware::power::stats::V1_0::implementation::PowerStats; class DefaultStateResidencyDataProvider : public IStateResidencyDataProvider { public: DefaultStateResidencyDataProvider(uint32_t id) : mPowerEntityId(id), mActiveStateId(0), mSleepStateId(1) {} ~DefaultStateResidencyDataProvider() = default; bool getResults(std::unordered_map<uint32_t, PowerEntityStateResidencyResult>& results) { PowerEntityStateResidencyResult result = { .powerEntityId = mPowerEntityId }; result.stateResidencyData.resize(2); // Using fake numbers here for display only. A real implementation would // use actual tracked stats. result.stateResidencyData[0] = { .powerEntityStateId = mActiveStateId, .totalTimeInStateMs = 1, .totalStateEntryCount = 2, .lastEntryTimestampMs = 3 }; result.stateResidencyData[1] = { .powerEntityStateId = mSleepStateId, .totalTimeInStateMs = 4, .totalStateEntryCount = 5, .lastEntryTimestampMs = 6, }; results.emplace(mPowerEntityId, result); return true; } std::vector<PowerEntityStateSpace> getStateSpaces() { return {{ .powerEntityId = mPowerEntityId, .states = { {.powerEntityStateId = mActiveStateId, .powerEntityStateName = "Active"}, {.powerEntityStateId = mSleepStateId, .powerEntityStateName = "Sleep"} } }}; } private: const uint32_t mPowerEntityId; const uint32_t mActiveStateId; const uint32_t mSleepStateId; }; int main(int /* argc */, char** /* argv */) { ALOGI("power.stats service 1.0 is starting."); android::sp<IPowerStats> service = new PowerStats(); PowerStats* service = new PowerStats(); if (service == nullptr) { ALOGE("Can not create an instance of power.stats HAL Iface, exiting."); return 1; } uint32_t defaultId = service->addPowerEntity("DefaultEntity", PowerEntityType::SUBSYSTEM); auto defaultSdp = std::make_shared<DefaultStateResidencyDataProvider>(defaultId); service->addStateResidencyDataProvider(std::move(defaultSdp)); configureRpcThreadpool(1, true /*callerWillJoin*/); status_t status = service->registerAsService(); Loading