1 /* 2 * Copyright (C) 2017 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 specic language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_LIBPERFMGR_HINTMANAGER_H_ 18 #define ANDROID_LIBPERFMGR_HINTMANAGER_H_ 19 20 #include <android-base/thread_annotations.h> 21 22 #include <atomic> 23 #include <cstddef> 24 #include <cstdint> 25 #include <memory> 26 #include <mutex> 27 #include <set> 28 #include <string> 29 #include <unordered_map> 30 #include <utility> 31 #include <vector> 32 33 #include "perfmgr/AdpfConfig.h" 34 #include "perfmgr/NodeLooperThread.h" 35 36 namespace android { 37 namespace perfmgr { 38 39 struct HintStats { HintStatsHintStats40 HintStats() : count(0), duration_ms(0) {} 41 uint32_t count; 42 uint64_t duration_ms; 43 }; 44 45 struct HintStatus { 46 const std::chrono::milliseconds max_timeout; HintStatusHintStatus47 HintStatus() : max_timeout(std::chrono::milliseconds(0)) {} HintStatusHintStatus48 explicit HintStatus(std::chrono::milliseconds max_timeout) 49 : max_timeout(max_timeout), 50 start_time(std::chrono::steady_clock::time_point::min()), 51 end_time(std::chrono::steady_clock::time_point::min()) {} 52 std::chrono::steady_clock::time_point start_time; 53 std::chrono::steady_clock::time_point end_time; 54 struct HintStatsInternal { HintStatsInternalHintStatus::HintStatsInternal55 HintStatsInternal() : count(0), duration_ms(0) {} 56 std::atomic<uint32_t> count; 57 std::atomic<uint64_t> duration_ms; 58 } stats; 59 }; 60 61 enum class HintActionType { Node, DoHint, EndHint, MaskHint }; 62 63 struct HintAction { HintActionHintAction64 HintAction(HintActionType t, const std::string &v, const std::string &p) 65 : type(t), value(v), enable_property(p) {} 66 HintActionType type; 67 std::string value; 68 std::string enable_property; 69 }; 70 71 struct Hint { HintHint72 Hint() {} HintHint73 Hint(const Hint &obj) 74 : node_actions(obj.node_actions), 75 hint_actions(obj.hint_actions), 76 mask_requesters(obj.mask_requesters), 77 status(obj.status) {} 78 std::vector<NodeAction> node_actions; 79 std::vector<HintAction> hint_actions; 80 mutable std::mutex hint_lock; 81 std::set<std::string> mask_requesters GUARDED_BY(hint_lock); 82 std::shared_ptr<HintStatus> status GUARDED_BY(hint_lock); 83 }; 84 85 // HintManager is the external interface of the library to be used by PowerHAL 86 // to do power hints with sysfs nodes. HintManager maintains a representation of 87 // the actions that are parsed from the configuration file as a mapping from a 88 // PowerHint to the set of actions that are performed for that PowerHint. 89 class HintManager { 90 public: HintManager(sp<NodeLooperThread> nm,const std::unordered_map<std::string,Hint> & actions,const std::vector<std::shared_ptr<AdpfConfig>> & adpfs,const std::unordered_map<std::string,std::shared_ptr<AdpfConfig>> & tag_adpfs,std::optional<std::string> gpu_sysfs_config_path)91 HintManager(sp<NodeLooperThread> nm, const std::unordered_map<std::string, Hint> &actions, 92 const std::vector<std::shared_ptr<AdpfConfig>> &adpfs, 93 const std::unordered_map<std::string, std::shared_ptr<AdpfConfig>> &tag_adpfs, 94 std::optional<std::string> gpu_sysfs_config_path) 95 : nm_(std::move(nm)), 96 actions_(actions), 97 adpfs_(adpfs), 98 tag_profile_map_(tag_adpfs), 99 adpf_index_(0), 100 gpu_sysfs_config_path_(gpu_sysfs_config_path) {} ~HintManager()101 ~HintManager() { 102 if (nm_.get() != nullptr) nm_->Stop(); 103 } 104 105 // Return true if the sysfs manager thread is running. 106 bool IsRunning() const; 107 108 // Do hint based on hint_type which defined as PowerHint in the actions 109 // section of the JSON config. Return true with valid hint_type and also 110 // NodeLooperThread::Request succeeds; otherwise return false. 111 bool DoHint(const std::string &hint_type); 112 113 // Do hint with the override time for all actions defined for the given 114 // hint_type. Return true with valid hint_type and also 115 // NodeLooperThread::Request succeeds; otherwise return false. 116 bool DoHint(const std::string &hint_type, std::chrono::milliseconds timeout_ms_override); 117 118 // End hint early. Return true with valid hint_type and also 119 // NodeLooperThread::Cancel succeeds; otherwise return false. 120 bool EndHint(const std::string &hint_type); 121 122 // Query if given hint supported. 123 bool IsHintSupported(const std::string &hint_type) const; 124 125 // Query if given hint enabled. 126 bool IsHintEnabled(const std::string &hint_type) const; 127 128 // TODO(jimmyshiu@): Need to be removed once all powerhint.json up-to-date. 129 bool SetAdpfProfileFromDoHint(const std::string &profile_name); 130 std::shared_ptr<AdpfConfig> GetAdpfProfileFromDoHint() const; 131 132 bool SetAdpfProfile(const std::string &tag, const std::string &profile); 133 134 typedef std::function<void(std::shared_ptr<AdpfConfig>)> AdpfCallback; 135 void RegisterAdpfUpdateEvent(const std::string &tag, AdpfCallback *update_adpf_func); 136 void UnregisterAdpfUpdateEvent(const std::string &tag, AdpfCallback *update_adpf_func); 137 138 std::optional<std::string> gpu_sysfs_config_path() const; 139 140 // get current ADPF. 141 std::shared_ptr<AdpfConfig> GetAdpfProfile(const std::string &node_name = "OTHER") const; 142 143 // Check if ADPF is supported. 144 bool IsAdpfSupported() const; 145 146 // Query if given AdpfProfile supported. 147 bool IsAdpfProfileSupported(const std::string &name) const; 148 149 // Static method to construct the global HintManager from the JSON config file. 150 static HintManager *GetFromJSON(const std::string &config_path, bool start = true); 151 152 // Return available hints managed by HintManager 153 std::vector<std::string> GetHints() const; 154 155 // Return stats of hints managed by HintManager 156 HintStats GetHintStats(const std::string &hint_type) const; 157 158 // Dump internal status to fd 159 void DumpToFd(int fd); 160 161 // Start thread loop 162 bool Start(); 163 164 // Singleton 165 static HintManager *GetInstance(); 166 167 protected: 168 static std::vector<std::unique_ptr<Node>> ParseNodes(const std::string &json_doc); 169 static std::unordered_map<std::string, Hint> ParseActions( 170 const std::string &json_doc, const std::vector<std::unique_ptr<Node>> &nodes); 171 static std::vector<std::shared_ptr<AdpfConfig>> ParseAdpfConfigs(const std::string &json_doc); 172 static bool InitHintStatus(const std::unique_ptr<HintManager> &hm); 173 174 static void Reload(bool start); 175 HintManager(HintManager const&) = delete; 176 HintManager &operator=(HintManager const &) = delete; 177 178 bool ValidateHint(const std::string& hint_type) const; 179 // Helper function to update the HintStatus when DoHint 180 void DoHintStatus(const std::string &hint_type, std::chrono::milliseconds timeout_ms); 181 // Helper function to update the HintStatus when EndHint 182 void EndHintStatus(const std::string &hint_type); 183 // Helper function to take hint actions when DoHint 184 void DoHintAction(const std::string &hint_type); 185 // Helper function to take hint actions when EndHint 186 void EndHintAction(const std::string &hint_type); 187 sp<NodeLooperThread> nm_; 188 std::unordered_map<std::string, Hint> actions_; 189 std::vector<std::shared_ptr<AdpfConfig>> adpfs_; 190 // TODO(jimmyshiu@): Need to be removed once all powerhint.json up-to-date. 191 std::unordered_map<std::string, std::shared_ptr<AdpfConfig>> tag_profile_map_; 192 uint32_t adpf_index_; 193 std::optional<std::string> gpu_sysfs_config_path_; 194 195 static std::unique_ptr<HintManager> sInstance; 196 197 // Hint Update Callback 198 void OnNodeUpdate(const std::string &name, const std::string &path, const std::string &value); 199 // set ADPF config by hint name. 200 std::unordered_map<std::string, std::vector<AdpfCallback *>> tag_update_callback_list_; 201 }; 202 203 } // namespace perfmgr 204 } // namespace android 205 206 #endif // ANDROID_LIBPERFMGR_HINTMANAGER_H_ 207