summaryrefslogtreecommitdiff
path: root/powerstats/AocStateResidencyDataProvider.cpp
blob: c64496dd78a0df7760945f786b1e0973d0293913 (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
124
125
126
127
128
/*
 * Copyright (C) 2020 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.
 */

#include "AocStateResidencyDataProvider.h"

#include <android-base/logging.h>

namespace aidl {
namespace android {
namespace hardware {
namespace power {
namespace stats {

AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string,
        std::string>> ids, std::vector<std::pair<std::string, std::string>> states) {
    // AoC stats are reported in ticks of 244.140625ns. The transform
    // function converts ticks to milliseconds.
    // 1000000 / 244.140625 = 4096.
    static const uint64_t AOC_CLK = 4096;
    std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; };
    GenericStateResidencyDataProvider::StateResidencyConfig config = {
            .entryCountSupported = true,
            .entryCountPrefix = "Counter:",
            .totalTimeSupported = true,
            .totalTimePrefix = "Cumulative time:",
            .totalTimeTransform = aocTickToMs,
            .lastEntrySupported = true,
            .lastEntryPrefix = "Time last entered:",
            .lastEntryTransform = aocTickToMs,
    };
    for (const auto &id : ids) {
        for (const auto &state : states) {
            std::vector<std::pair<std::string, std::string>> aocStateHeaders = {
                std::make_pair(state.first, ""),
            };
            std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
            cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders),
                    id.first, "");
            std::unique_ptr<GenericStateResidencyDataProvider> sdp(
                    new GenericStateResidencyDataProvider(id.second + state.second, cfgs));
            mProviders[id.first].push_back(std::move(sdp));
        }
    }
}

bool AocStateResidencyDataProvider::getStateResidencies(
        std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
    // States from the same power entity are merged.
    bool ret = true;
    for (const auto &providerList : mProviders) {
        int32_t stateId = 0;
        std::string curEntity = providerList.first;
        std::vector<StateResidency> stateResidencies;

        // Iterate over each provider in the providerList, appending each of the states
        for (const auto &provider : providerList.second) {
            std::unordered_map<std::string, std::vector<StateResidency>> residency;
            ret &= provider->getStateResidencies(&residency);

            // Each provider should only return data for curEntity but checking anyway
            if (residency.find(curEntity) != residency.end()) {
                for (auto &r : residency.at(curEntity)) {
                    /*
                     * Modifying stateId here because we are stitching together infos from
                     * multiple GenericStateResidencyDataProviders. stateId must be modified
                     * to maintain uniqueness for a given entity
                     */
                    r.id = stateId++;
                    stateResidencies.push_back(r);
                }
            }
        }

        residencies->emplace(curEntity, stateResidencies);
    }
    return ret;
}

std::unordered_map<std::string, std::vector<State>> AocStateResidencyDataProvider::getInfo() {
    // States from the same power entity are merged
    std::unordered_map<std::string, std::vector<State>> infos;
    for (const auto &providerList : mProviders) {
        int32_t stateId = 0;
        std::string curEntity = providerList.first;
        std::vector<State> stateInfos;

        // Iterate over each provider in the providerList, appending each of the states
        for (const auto &provider : providerList.second) {
            std::unordered_map<std::string, std::vector<State>> info = provider->getInfo();

            // Each provider should only return data for curEntity but checking anyway
            if (info.find(curEntity) != info.end()) {
                for (auto &i : info.at(curEntity)) {
                    /*
                     * Modifying stateId because we are stitching together infos from
                     * multiple GenericStateResidencyDataProviders. stateId must be modified
                     * to maintain uniqueness for a given entity
                     */
                    i.id = stateId++;
                    stateInfos.push_back(i);
                }
            }
        }

        infos.emplace(curEntity, stateInfos);
    }

    return infos;
}

}  // namespace stats
}  // namespace power
}  // namespace hardware
}  // namespace android
}  // namespace aidl