summaryrefslogtreecommitdiff
path: root/pwrstats_util/dataproviders/RailEnergyDataProvider.cpp
blob: 7a2213ef0ad4485f3a5e651fdc9517e9fa7dde97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "pwrstats_util"

#include "RailEnergyDataProvider.h"
#include <android-base/logging.h>
#include <android/hardware/power/stats/1.0/IPowerStats.h>

using android::sp;
using android::hardware::Return;
using android::hardware::power::stats::V1_0::IPowerStats;
using android::hardware::power::stats::V1_0::Status;

int RailEnergyDataProvider::getImpl(PowerStatistic* stat) const {
    sp<android::hardware::power::stats::V1_0::IPowerStats> powerStatsService =
            android::hardware::power::stats::V1_0::IPowerStats::getService();
    if (powerStatsService == nullptr) {
        LOG(ERROR) << "unable to get power.stats HAL service";
        return 1;
    }

    std::unordered_map<uint32_t, std::string> railNames;

    Return<void> ret;
    Status retStatus = Status::SUCCESS;
    ret = powerStatsService->getRailInfo([&railNames, &retStatus](auto railInfos, auto status) {
        retStatus = status;
        if (status != Status::SUCCESS) {
            return;
        }

        for (auto const& info : railInfos) {
            railNames.emplace(info.index, info.railName);
        }
    });
    if (retStatus == Status::NOT_SUPPORTED) {
        LOG(WARNING) << __func__ << ": rail energy stats not supported";
        return 0;
    }
    if (!ret.isOk() || retStatus != Status::SUCCESS) {
        LOG(ERROR) << __func__ << ": no rail information available";
        return 1;
    }

    auto railEntries = stat->mutable_rail_energy();
    bool resultSuccess = true;
    ret = powerStatsService->getEnergyData(
            {}, [&railEntries, &railNames, &resultSuccess](auto energyData, auto status) {
                if (status != Status::SUCCESS) {
                    LOG(ERROR) << __func__ << ": unable to get rail energy";
                    resultSuccess = false;
                    return;
                }

                for (auto const& energyDatum : energyData) {
                    auto entry = railEntries->add_entry();
                    entry->set_rail_name(railNames.at(energyDatum.index));
                    entry->set_energy_uws(energyDatum.energy);
                }
            });
    if (!ret.isOk() || !resultSuccess) {
        stat->clear_rail_energy();
        LOG(ERROR) << __func__ << ": failed to get rail energy stats";
        return 1;
    }

    // Sort entries by name. Sorting is needed to make interval processing efficient.
    std::sort(railEntries->mutable_entry()->begin(), railEntries->mutable_entry()->end(),
              [](const auto& a, const auto& b) { return a.rail_name() < b.rail_name(); });

    return 0;
}

int RailEnergyDataProvider::getImpl(const PowerStatistic& start, PowerStatistic* interval) const {
    auto startEnergy = start.rail_energy().entry();
    auto intervalEnergy = interval->mutable_rail_energy()->mutable_entry();

    // If start and interval are not the same size then they cannot have matching data
    if (startEnergy.size() != intervalEnergy->size()) {
        LOG(ERROR) << __func__ << ": mismatched data";
        interval->clear_rail_energy();
        return 1;
    }

    for (int i = 0; i < startEnergy.size(); ++i) {
        // Check and make sure each entry matches. Data are in sorted order so if there is a
        // mismatch then we will bail.
        if (startEnergy.Get(i).rail_name() != intervalEnergy->Get(i).rail_name()) {
            LOG(ERROR) << __func__ << ": mismatched data";
            interval->clear_rail_energy();
            return 1;
        }

        auto delta = intervalEnergy->Get(i).energy_uws() - startEnergy.Get(i).energy_uws();
        intervalEnergy->Mutable(i)->set_energy_uws(delta);
    }
    return 0;
}

void RailEnergyDataProvider::dumpImpl(const PowerStatistic& stat, std::ostream* output) const {
    *output << "Rail Energy:" << std::endl;
    for (auto const& rail : stat.rail_energy().entry()) {
        *output << rail.rail_name() << "=" << rail.energy_uws() << std::endl;
    }
    *output << std::endl;
}

PowerStatCase RailEnergyDataProvider::typeOf() const {
    return PowerStatCase::kRailEnergy;
}