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 #pragma once 18 19 #include <optional> 20 #include <string> 21 22 #include "../display/common/CommonDisplayContextProvider.h" 23 #include "PowerStatsProfile.h" 24 25 namespace android::hardware::graphics::composer { 26 27 struct StateNameComparator { operatorStateNameComparator28 bool operator()(const std::string& a, const std::string& b) const { 29 // 1. Find the last '@' in both strings 30 size_t posA = a.rfind('@'); 31 size_t posB = b.rfind('@'); 32 33 // 2. Extract the parts before and after the '@' 34 std::string prefixA = (posA != std::string::npos) ? a.substr(0, posA) : a; 35 std::string suffixA = (posA != std::string::npos) ? a.substr(posA + 1) : ""; 36 std::string prefixB = (posB != std::string::npos) ? b.substr(0, posB) : b; 37 std::string suffixB = (posB != std::string::npos) ? b.substr(posB + 1) : ""; 38 39 // 3. Compare prefixes first 40 if (prefixA != prefixB) { 41 return prefixA < prefixB; 42 } 43 44 // 4. If prefixes are the same, check for "np" and extract numeric parts 45 bool hasNpA = suffixA.find("np") == 0; 46 bool hasNpB = suffixB.find("np") == 0; 47 std::string numPartA = hasNpA ? suffixA.substr(2) : suffixA; 48 std::string numPartB = hasNpB ? suffixB.substr(2) : suffixB; 49 50 // 5. Compare based on "np" presence 51 if (hasNpA != hasNpB) { 52 return !hasNpA; // "np" prefixes come after non-"np" prefixes 53 } 54 55 // 6. If both have "np" or neither has it, compare numeric parts 56 bool isNumA = std::all_of(numPartA.begin(), numPartA.end(), ::isdigit); 57 bool isNumB = std::all_of(numPartB.begin(), numPartB.end(), ::isdigit); 58 59 if (isNumA && isNumB) { 60 char* endPtrA; 61 char* endPtrB; 62 63 long numA = strtol(numPartA.c_str(), &endPtrA, 10); 64 long numB = strtol(numPartB.c_str(), &endPtrB, 10); 65 66 if (*endPtrA != '\0' || *endPtrB != '\0' || numA < std::numeric_limits<int>::min() || 67 numA > std::numeric_limits<int>::max() || numB < std::numeric_limits<int>::min() || 68 numB > std::numeric_limits<int>::max()) { 69 ALOGE("Error parsing numeric parts in KeyComparator"); 70 71 return false; 72 } 73 74 return numA < numB; 75 } else { 76 return suffixA < suffixB; 77 } 78 } 79 }; 80 81 class PowerStatsProfileTokenGenerator { 82 public: 83 PowerStatsProfileTokenGenerator(); 84 85 std::optional<std::string> generateToken(const std::string& tokenLabel, 86 PowerStatsProfile* profile); 87 88 std::string generateStateName(PowerStatsProfile* profile, bool enableMapping = true); 89 90 private: 91 // The format of pattern is: ([token label]'delimiter'?)* 92 static constexpr std::string_view kPresentDisplayStateResidencyPattern = 93 "[mode](:)[width](x)[height](@)[fps]()"; 94 95 // The format of pattern is: ([token label]'delimiter'?)* 96 static constexpr std::string_view kNonPresentDisplayStateResidencyPattern = 97 "[mode](:)[width](x)[height](@)[refreshSource]()"; 98 99 static constexpr char kTokenLabelStart = '['; 100 static constexpr char kTokenLabelEnd = ']'; 101 static constexpr char kDelimiterStart = '('; 102 static constexpr char kDelimiterEnd = ')'; 103 104 bool parseDisplayStateResidencyPattern(); 105 106 bool parseResidencyPattern( 107 std::vector<std::pair<std::string, std::string>>& residencyPatternMap, 108 const std::string_view residencyPattern); 109 110 std::string generateRefreshSourceToken(PowerStatsProfile* profile) const; 111 112 std::string generateModeToken(PowerStatsProfile* profile) const; 113 114 std::string generateWidthToken(PowerStatsProfile* profile) const; 115 116 std::string generateHeightToken(PowerStatsProfile* profile) const; 117 118 std::string generateFpsToken(PowerStatsProfile* profile) const; 119 120 std::vector<std::pair<std::string, std::string>> mNonPresentDisplayStateResidencyPatternList; 121 std::vector<std::pair<std::string, std::string>> mPresentDisplayStateResidencyPatternList; 122 }; 123 124 } // namespace android::hardware::graphics::composer 125