1 /*
2 * Copyright (C) 2024 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
17 #include "PowerStatsProfileTokenGenerator.h"
18
19 #include <string>
20 #include <unordered_map>
21
22 namespace android::hardware::graphics::composer {
23
PowerStatsProfileTokenGenerator()24 PowerStatsProfileTokenGenerator::PowerStatsProfileTokenGenerator() {
25 parseDisplayStateResidencyPattern();
26 }
27
generateRefreshSourceToken(PowerStatsProfile * profile) const28 std::string PowerStatsProfileTokenGenerator::generateRefreshSourceToken(
29 PowerStatsProfile* profile) const {
30 if (profile->isOff()) {
31 return "";
32 }
33
34 if (isPresentRefresh(profile->mRefreshSource)) {
35 return "p";
36 } else {
37 return "np";
38 }
39 }
40
generateModeToken(PowerStatsProfile * profile) const41 std::string PowerStatsProfileTokenGenerator::generateModeToken(PowerStatsProfile* profile) const {
42 if (profile->isOff()) {
43 return "OFF";
44 } else {
45 if (profile->mPowerMode == HWC_POWER_MODE_DOZE) {
46 return "LPM";
47 }
48 return (profile->mBrightnessMode == BrightnessMode::kHighBrightnessMode) ? "HBM" : "NBM";
49 }
50 }
51
generateWidthToken(PowerStatsProfile * profile) const52 std::string PowerStatsProfileTokenGenerator::generateWidthToken(PowerStatsProfile* profile) const {
53 if (profile->isOff()) {
54 return "";
55 }
56 return std::to_string(profile->mWidth);
57 }
58
generateHeightToken(PowerStatsProfile * profile) const59 std::string PowerStatsProfileTokenGenerator::generateHeightToken(PowerStatsProfile* profile) const {
60 if (profile->isOff()) {
61 return "";
62 }
63 return std::to_string(profile->mHeight);
64 }
65
generateFpsToken(PowerStatsProfile * profile) const66 std::string PowerStatsProfileTokenGenerator::generateFpsToken(PowerStatsProfile* profile) const {
67 if (profile->isOff()) {
68 return "";
69 }
70 if (profile->mFps == 0) {
71 return "oth";
72 }
73 return std::to_string(profile->mFps);
74 }
75
generateToken(const std::string & tokenLabel,PowerStatsProfile * profile)76 std::optional<std::string> PowerStatsProfileTokenGenerator::generateToken(
77 const std::string& tokenLabel, PowerStatsProfile* profile) {
78 static std::unordered_map<std::string, std::function<std::string(PowerStatsProfile*)>>
79 functors = {{"refreshSource",
80 std::bind(&PowerStatsProfileTokenGenerator::generateRefreshSourceToken,
81 this, std::placeholders::_1)},
82 {"mode",
83 std::bind(&PowerStatsProfileTokenGenerator::generateModeToken, this,
84 std::placeholders::_1)},
85 {"width",
86 std::bind(&PowerStatsProfileTokenGenerator::generateWidthToken, this,
87 std::placeholders::_1)},
88 {"height",
89 std::bind(&PowerStatsProfileTokenGenerator::generateHeightToken, this,
90 std::placeholders::_1)},
91 {"fps",
92 std::bind(&PowerStatsProfileTokenGenerator::generateFpsToken, this,
93 std::placeholders::_1)}};
94
95 if (functors.find(tokenLabel) != functors.end()) {
96 return (functors[tokenLabel])(profile);
97 } else {
98 ALOGE("%s syntax error: unable to find token label = %s", __func__, tokenLabel.c_str());
99 return std::nullopt;
100 }
101 }
102
generateStateName(PowerStatsProfile * profile,bool enableMapping)103 std::string PowerStatsProfileTokenGenerator::generateStateName(PowerStatsProfile* profile,
104 bool enableMapping) {
105 std::string stateName;
106 const std::vector<std::pair<std::string, std::string>>& residencyPattern =
107 !isPresentRefresh(profile->mRefreshSource) ? mNonPresentDisplayStateResidencyPatternList
108 : mPresentDisplayStateResidencyPatternList;
109
110 for (const auto& pattern : residencyPattern) {
111 const auto token = generateToken(pattern.first, profile);
112 if (token.has_value()) {
113 stateName += token.value();
114 if (pattern.first == "mode" && token.value() == "OFF") {
115 break;
116 }
117 } else {
118 ALOGE("DisplayStateResidencyProvider %s(): cannot find token with label %s", __func__,
119 pattern.first.c_str());
120 continue;
121 }
122 stateName += pattern.second;
123 }
124 if (!enableMapping && !isPresentRefresh(profile->mRefreshSource)) {
125 stateName += generateFpsToken(profile);
126 }
127 return stateName;
128 }
129
parseResidencyPattern(std::vector<std::pair<std::string,std::string>> & residencyPatternMap,const std::string_view residencyPattern)130 bool PowerStatsProfileTokenGenerator::parseResidencyPattern(
131 std::vector<std::pair<std::string, std::string>>& residencyPatternMap,
132 const std::string_view residencyPattern) {
133 size_t start, end;
134 start = 0;
135 end = -1;
136 while (true) {
137 start = residencyPattern.find_first_of(kTokenLabelStart, end + 1);
138 if (start == std::string::npos) {
139 break;
140 }
141 ++start;
142 end = residencyPattern.find_first_of(kTokenLabelEnd, start);
143 if (end == std::string::npos) {
144 break;
145 }
146 std::string tokenLabel(residencyPattern.substr(start, end - start));
147
148 start = residencyPattern.find_first_of(kDelimiterStart, end + 1);
149 if (start == std::string::npos) {
150 break;
151 }
152 ++start;
153 end = residencyPattern.find_first_of(kDelimiterEnd, start);
154 if (end == std::string::npos) {
155 break;
156 }
157 std::string delimiter(residencyPattern.substr(start, end - start));
158 residencyPatternMap.emplace_back(std::make_pair(tokenLabel, delimiter));
159 }
160 return (end == residencyPattern.length() - 1);
161 }
162
parseDisplayStateResidencyPattern()163 bool PowerStatsProfileTokenGenerator::parseDisplayStateResidencyPattern() {
164 return parseResidencyPattern(mPresentDisplayStateResidencyPatternList,
165 kPresentDisplayStateResidencyPattern) &&
166 parseResidencyPattern(mNonPresentDisplayStateResidencyPatternList,
167 kNonPresentDisplayStateResidencyPattern);
168 }
169
170 } // namespace android::hardware::graphics::composer
171