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 "RailEnergyDataProvider.h"
19 #include <android-base/logging.h>
20 #include <android/hardware/power/stats/1.0/IPowerStats.h>
21
22 using android::sp;
23 using android::hardware::Return;
24 using android::hardware::power::stats::V1_0::IPowerStats;
25 using android::hardware::power::stats::V1_0::Status;
26
getImpl(PowerStatistic * stat) const27 int RailEnergyDataProvider::getImpl(PowerStatistic* stat) const {
28 sp<android::hardware::power::stats::V1_0::IPowerStats> powerStatsService =
29 android::hardware::power::stats::V1_0::IPowerStats::getService();
30 if (powerStatsService == nullptr) {
31 LOG(ERROR) << "unable to get power.stats HAL service";
32 return 1;
33 }
34
35 std::unordered_map<uint32_t, std::string> railNames;
36
37 Return<void> ret;
38 Status retStatus = Status::SUCCESS;
39 ret = powerStatsService->getRailInfo([&railNames, &retStatus](auto railInfos, auto status) {
40 retStatus = status;
41 if (status != Status::SUCCESS) {
42 return;
43 }
44
45 for (auto const& info : railInfos) {
46 railNames.emplace(info.index, info.railName);
47 }
48 });
49 if (retStatus == Status::NOT_SUPPORTED) {
50 LOG(WARNING) << __func__ << ": rail energy stats not supported";
51 return 0;
52 }
53 if (!ret.isOk() || retStatus != Status::SUCCESS) {
54 LOG(ERROR) << __func__ << ": no rail information available";
55 return 1;
56 }
57
58 auto railEntries = stat->mutable_rail_energy();
59 bool resultSuccess = true;
60 ret = powerStatsService->getEnergyData(
61 {}, [&railEntries, &railNames, &resultSuccess](auto energyData, auto status) {
62 if (status != Status::SUCCESS) {
63 LOG(ERROR) << __func__ << ": unable to get rail energy";
64 resultSuccess = false;
65 return;
66 }
67
68 for (auto const& energyDatum : energyData) {
69 auto entry = railEntries->add_entry();
70 entry->set_rail_name(railNames.at(energyDatum.index));
71 entry->set_energy_uws(energyDatum.energy);
72 }
73 });
74 if (!ret.isOk() || !resultSuccess) {
75 stat->clear_rail_energy();
76 LOG(ERROR) << __func__ << ": failed to get rail energy stats";
77 return 1;
78 }
79
80 // Sort entries by name. Sorting is needed to make interval processing efficient.
81 std::sort(railEntries->mutable_entry()->begin(), railEntries->mutable_entry()->end(),
82 [](const auto& a, const auto& b) { return a.rail_name() < b.rail_name(); });
83
84 return 0;
85 }
86
getImpl(const PowerStatistic & start,PowerStatistic * interval) const87 int RailEnergyDataProvider::getImpl(const PowerStatistic& start, PowerStatistic* interval) const {
88 auto startEnergy = start.rail_energy().entry();
89 auto intervalEnergy = interval->mutable_rail_energy()->mutable_entry();
90
91 // If start and interval are not the same size then they cannot have matching data
92 if (startEnergy.size() != intervalEnergy->size()) {
93 LOG(ERROR) << __func__ << ": mismatched data";
94 interval->clear_rail_energy();
95 return 1;
96 }
97
98 for (int i = 0; i < startEnergy.size(); ++i) {
99 // Check and make sure each entry matches. Data are in sorted order so if there is a
100 // mismatch then we will bail.
101 if (startEnergy.Get(i).rail_name() != intervalEnergy->Get(i).rail_name()) {
102 LOG(ERROR) << __func__ << ": mismatched data";
103 interval->clear_rail_energy();
104 return 1;
105 }
106
107 auto delta = intervalEnergy->Get(i).energy_uws() - startEnergy.Get(i).energy_uws();
108 intervalEnergy->Mutable(i)->set_energy_uws(delta);
109 }
110 return 0;
111 }
112
dumpImpl(const PowerStatistic & stat,std::ostream * output) const113 void RailEnergyDataProvider::dumpImpl(const PowerStatistic& stat, std::ostream* output) const {
114 *output << "Rail Energy:" << std::endl;
115 for (auto const& rail : stat.rail_energy().entry()) {
116 *output << rail.rail_name() << "=" << rail.energy_uws() << std::endl;
117 }
118 *output << std::endl;
119 }
120
typeOf() const121 PowerStatCase RailEnergyDataProvider::typeOf() const {
122 return PowerStatCase::kRailEnergy;
123 }
124