1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "pwrstats_util"
17
18 #include "PowerEntityResidencyDataProvider.h"
19 #include "DataProviderHelper.h"
20
21 #include <android-base/logging.h>
22 #include <android/hardware/power/stats/1.0/IPowerStats.h>
23
24 using android::sp;
25 using android::hardware::Return;
26
27 /**
28 * Power Entity State Residency data provider:
29 * Provides data monitored by Power Stats HAL 1.0
30 **/
31
getImpl(PowerStatistic * stat) const32 int PowerEntityResidencyDataProvider::getImpl(PowerStatistic* stat) const {
33 sp<android::hardware::power::stats::V1_0::IPowerStats> powerStatsService =
34 android::hardware::power::stats::V1_0::IPowerStats::getService();
35 if (powerStatsService == nullptr) {
36 LOG(ERROR) << "unable to get power.stats HAL service";
37 return 1;
38 }
39
40 std::unordered_map<uint32_t, std::string> entityNames;
41 std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> stateNames;
42
43 // Create map of entity names based on entity id
44 Return<void> ret;
45 ret = powerStatsService->getPowerEntityInfo([&entityNames](auto infos, auto /* status */) {
46 for (auto const& info : infos) {
47 entityNames.emplace(info.powerEntityId, info.powerEntityName);
48 }
49 });
50 if (!ret.isOk()) {
51 LOG(ERROR) << __func__ << ": unable to get entity info";
52 return 1;
53 }
54
55 // Create map of each entity's states based on entity and state id
56 ret = powerStatsService->getPowerEntityStateInfo({}, [&stateNames](auto stateSpaces,
57 auto /* status */) {
58 for (auto const& stateSpace : stateSpaces) {
59 stateNames.emplace(stateSpace.powerEntityId,
60 std::unordered_map<uint32_t, std::string>());
61 auto& entityStateNames = stateNames.at(stateSpace.powerEntityId);
62 for (auto const& state : stateSpace.states) {
63 entityStateNames.emplace(state.powerEntityStateId, state.powerEntityStateName);
64 }
65 }
66 });
67 if (!ret.isOk()) {
68 LOG(ERROR) << __func__ << ": unable to get state info";
69 return 1;
70 }
71
72 // Retrieve residency data and create the PowerStatistic::PowerEntityStateResidency
73 ret = powerStatsService->getPowerEntityStateResidencyData({}, [&entityNames, &stateNames,
74 &stat](auto results,
75 auto /* status */) {
76 auto residencies = stat->mutable_power_entity_state_residency();
77 for (auto const& result : results) {
78 for (auto const& curStateResidency : result.stateResidencyData) {
79 auto residency = residencies->add_residency();
80 residency->set_entity_name(entityNames.at(result.powerEntityId));
81 residency->set_state_name(stateNames.at(result.powerEntityId)
82 .at(curStateResidency.powerEntityStateId));
83 residency->set_time_ms(static_cast<uint64_t>(curStateResidency.totalTimeInStateMs));
84 }
85 }
86
87 // Sort entries first by entity_name, then by state_name.
88 // Sorting is needed to make interval processing efficient.
89 std::sort(residencies->mutable_residency()->begin(),
90 residencies->mutable_residency()->end(), [](const auto& a, const auto& b) {
91 if (a.entity_name() != b.entity_name()) {
92 return a.entity_name() < b.entity_name();
93 }
94
95 return a.state_name() < b.state_name();
96 });
97 });
98 if (!ret.isOk()) {
99 LOG(ERROR) << __func__ << ": Unable to get residency info";
100 return 1;
101 }
102
103 return 0;
104 }
105
getImpl(const PowerStatistic & start,PowerStatistic * interval) const106 int PowerEntityResidencyDataProvider::getImpl(const PowerStatistic& start,
107 PowerStatistic* interval) const {
108 auto startResidency = start.power_entity_state_residency().residency();
109 auto intervalResidency = interval->mutable_power_entity_state_residency()->mutable_residency();
110
111 if (0 != StateResidencyInterval(startResidency, intervalResidency)) {
112 interval->clear_power_entity_state_residency();
113 return 1;
114 }
115
116 return 0;
117 }
118
dumpImpl(const PowerStatistic & stat,std::ostream * output) const119 void PowerEntityResidencyDataProvider::dumpImpl(const PowerStatistic& stat,
120 std::ostream* output) const {
121 *output << "Power Entity State Residencies:" << std::endl;
122 StateResidencyDump(stat.power_entity_state_residency().residency(), output);
123 }
124
typeOf() const125 PowerStatCase PowerEntityResidencyDataProvider::typeOf() const {
126 return PowerStatCase::kPowerEntityStateResidency;
127 }
128