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