blob: 94df933c2f0598ef8c249d8e6c02458019823c35 [file] [log] [blame]
Andy Hung125ff522024-06-28 09:51:30 -07001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "PowerStatsProvider.h"
18#include <android-base/logging.h>
19#include <android/binder_manager.h>
20#include <unordered_map>
21#include <aidl/android/hardware/power/stats/IPowerStats.h>
22
23using ::aidl::android::hardware::power::stats::IPowerStats;
24
25namespace android::media::psh_utils {
26
27static auto getPowerStatsService() {
28 [[clang::no_destroy]] static constinit std::mutex m;
29 [[clang::no_destroy]] static constinit
30 std::shared_ptr<IPowerStats> powerStats;
31
32 std::lock_guard l(m);
33 if (powerStats) {
34 return powerStats;
35 }
36 const auto serviceName =
37 std::string(IPowerStats::descriptor)
38 .append("/default");
39 powerStats = IPowerStats::fromBinder(
40 ::ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str())));
41 return powerStats;
42}
43
Andy Hung1ada5f92024-08-05 15:07:48 -070044status_t RailEnergyDataProvider::fill(PowerStats *stat) const {
45 if (stat == nullptr) return BAD_VALUE;
Andy Hung125ff522024-06-28 09:51:30 -070046 auto powerStatsService = getPowerStatsService();
47 if (powerStatsService == nullptr) {
48 LOG(ERROR) << "unable to get power.stats AIDL service";
Andy Hung1ada5f92024-08-05 15:07:48 -070049 return NO_INIT;
Andy Hung125ff522024-06-28 09:51:30 -070050 }
51
52 std::unordered_map<int32_t, ::aidl::android::hardware::power::stats::Channel> channelMap;
53 {
54 std::vector<::aidl::android::hardware::power::stats::Channel> channels;
55 if (!powerStatsService->getEnergyMeterInfo(&channels).isOk()) {
56 LOG(ERROR) << "unable to get energy meter info";
Andy Hung1ada5f92024-08-05 15:07:48 -070057 return INVALID_OPERATION;
Andy Hung125ff522024-06-28 09:51:30 -070058 }
59 for (auto& channel : channels) {
60 channelMap.emplace(channel.id, std::move(channel));
61 }
62 }
63
64 std::vector<::aidl::android::hardware::power::stats::EnergyMeasurement> measurements;
65 if (!powerStatsService->readEnergyMeter({}, &measurements).isOk()) {
66 LOG(ERROR) << "unable to get energy measurements";
Andy Hung1ada5f92024-08-05 15:07:48 -070067 return INVALID_OPERATION;
Andy Hung125ff522024-06-28 09:51:30 -070068 }
69
70 for (const auto& measurement : measurements) {
71 stat->rail_energy.emplace_back(
72 channelMap.at(measurement.id).subsystem,
73 channelMap.at(measurement.id).name,
74 measurement.energyUWs);
75 }
76
77 // Sort entries first by subsystem_name, then by rail_name.
78 // Sorting is needed to make interval processing efficient.
79 std::sort(stat->rail_energy.begin(), stat->rail_energy.end(),
80 [](const auto& a, const auto& b) {
81 if (a.subsystem_name != b.subsystem_name) {
82 return a.subsystem_name < b.subsystem_name;
83 }
84 return a.rail_name < b.rail_name;
85 });
86
Andy Hung1ada5f92024-08-05 15:07:48 -070087 return NO_ERROR;
Andy Hung125ff522024-06-28 09:51:30 -070088}
89
Andy Hung1ada5f92024-08-05 15:07:48 -070090status_t PowerEntityResidencyDataProvider::fill(PowerStats* stat) const {
91 if (stat == nullptr) return BAD_VALUE;
Andy Hung125ff522024-06-28 09:51:30 -070092 auto powerStatsService = getPowerStatsService();
93 if (powerStatsService == nullptr) {
94 LOG(ERROR) << "unable to get power.stats AIDL service";
Andy Hung1ada5f92024-08-05 15:07:48 -070095 return NO_INIT;
Andy Hung125ff522024-06-28 09:51:30 -070096 }
97
98 // these are based on entityId
99 std::unordered_map<int32_t, std::string> entityNames;
100 std::unordered_map<int32_t, std::unordered_map<int32_t, std::string>> stateNames;
101 std::vector<int32_t> powerEntityIds; // ids to use
102
103 {
104 std::vector<::aidl::android::hardware::power::stats::PowerEntity> entities;
105 if (!powerStatsService->getPowerEntityInfo(&entities).isOk()) {
106 LOG(ERROR) << __func__ << ": unable to get entity info";
Andy Hung1ada5f92024-08-05 15:07:48 -0700107 return INVALID_OPERATION;
Andy Hung125ff522024-06-28 09:51:30 -0700108 }
109
110 std::vector<std::string> powerEntityNames;
111 for (const auto& entity : entities) {
112 std::unordered_map<int32_t, std::string> states;
113 for (const auto& state : entity.states) {
114 states.emplace(state.id, state.name);
115 }
116
117 if (std::find(powerEntityNames.begin(), powerEntityNames.end(), entity.name) !=
118 powerEntityNames.end()) {
119 powerEntityIds.emplace_back(entity.id);
120 }
121 entityNames.emplace(entity.id, std::move(entity.name));
122 stateNames.emplace(entity.id, std::move(states));
123 }
124 }
125
126 std::vector<::aidl::android::hardware::power::stats::StateResidencyResult> results;
127 if (!powerStatsService->getStateResidency(powerEntityIds, &results).isOk()) {
128 LOG(ERROR) << __func__ << ": Unable to get state residency";
Andy Hung1ada5f92024-08-05 15:07:48 -0700129 return INVALID_OPERATION;
Andy Hung125ff522024-06-28 09:51:30 -0700130 }
131
132 for (const auto& result : results) {
133 for (const auto& curStateResidency : result.stateResidencyData) {
134 stat->power_entity_state_residency.emplace_back(
135 entityNames.at(result.id),
136 stateNames.at(result.id).at(curStateResidency.id),
137 static_cast<uint64_t>(curStateResidency.totalTimeInStateMs),
138 static_cast<uint64_t>(curStateResidency.totalStateEntryCount));
139 }
140 }
141
142 // Sort entries first by entity_name, then by state_name.
143 // Sorting is needed to make interval processing efficient.
144 std::sort(stat->power_entity_state_residency.begin(),
145 stat->power_entity_state_residency.end(),
146 [](const auto& a, const auto& b) {
147 if (a.entity_name != b.entity_name) {
148 return a.entity_name < b.entity_name;
149 }
150 return a.state_name < b.state_name;
151 });
Andy Hung1ada5f92024-08-05 15:07:48 -0700152 return NO_ERROR;
Andy Hung125ff522024-06-28 09:51:30 -0700153}
154
155} // namespace android::media::psh_utils