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 <atomic>
21 #include <cstddef>
22 #include <cstdint>
23 #include <memory>
24 #include <mutex>
25 #include <string>
26 #include <unordered_map>
27 #include <utility>
28 #include <vector>
29 
30 #include "perfmgr/NodeLooperThread.h"
31 
32 namespace android {
33 namespace perfmgr {
34 
35 struct HintStats {
HintStatsHintStats36     HintStats() : count(0), duration_ms(0) {}
37     uint32_t count;
38     uint64_t duration_ms;
39 };
40 
41 struct HintStatus {
42     const std::chrono::milliseconds max_timeout;
HintStatusHintStatus43     HintStatus() : max_timeout(std::chrono::milliseconds(0)) {}
HintStatusHintStatus44     explicit HintStatus(std::chrono::milliseconds max_timeout)
45         : max_timeout(max_timeout),
46           start_time(std::chrono::steady_clock::time_point::min()),
47           end_time(std::chrono::steady_clock::time_point::min()) {}
48     std::chrono::steady_clock::time_point start_time;
49     std::chrono::steady_clock::time_point end_time;
50     std::mutex mutex;
51     struct HintStatsInternal {
HintStatsInternalHintStatus::HintStatsInternal52         HintStatsInternal() : count(0), duration_ms(0) {}
53         std::atomic<uint32_t> count;
54         std::atomic<uint64_t> duration_ms;
55     } stats;
56 };
57 
58 enum class HintActionType { Node, DoHint, EndHint, MaskHint };
59 
60 struct HintAction {
HintActionHintAction61     HintAction(HintActionType t, const std::string &v) : type(t), value(v) {}
62     HintActionType type;
63     std::string value;
64 };
65 
66 struct Hint {
HintHint67     Hint() : enabled(true) {}
68     std::vector<NodeAction> node_actions;
69     std::vector<HintAction> hint_actions;
70     // No locking for `enabled' flag
71     // There should not be multiple writers
72     bool enabled;
73     std::shared_ptr<HintStatus> status;
74 };
75 
76 // HintManager is the external interface of the library to be used by PowerHAL
77 // to do power hints with sysfs nodes. HintManager maintains a representation of
78 // the actions that are parsed from the configuration file as a mapping from a
79 // PowerHint to the set of actions that are performed for that PowerHint.
80 class HintManager {
81   public:
HintManager(sp<NodeLooperThread> nm,const std::unordered_map<std::string,Hint> & actions)82     HintManager(sp<NodeLooperThread> nm, const std::unordered_map<std::string, Hint> &actions)
83         : nm_(std::move(nm)), actions_(actions) {}
~HintManager()84     ~HintManager() {
85         if (nm_.get() != nullptr) nm_->Stop();
86     }
87 
88     // Return true if the sysfs manager thread is running.
89     bool IsRunning() const;
90 
91     // Do hint based on hint_type which defined as PowerHint in the actions
92     // section of the JSON config. Return true with valid hint_type and also
93     // NodeLooperThread::Request succeeds; otherwise return false.
94     bool DoHint(const std::string& hint_type);
95 
96     // Do hint with the override time for all actions defined for the given
97     // hint_type.  Return true with valid hint_type and also
98     // NodeLooperThread::Request succeeds; otherwise return false.
99     bool DoHint(const std::string& hint_type,
100                 std::chrono::milliseconds timeout_ms_override);
101 
102     // End hint early. Return true with valid hint_type and also
103     // NodeLooperThread::Cancel succeeds; otherwise return false.
104     bool EndHint(const std::string& hint_type);
105 
106     // Query if given hint supported.
107     bool IsHintSupported(const std::string& hint_type) const;
108 
109     // Query if given hint enabled.
110     bool IsHintEnabled(const std::string &hint_type) const;
111 
112     // Static method to construct HintManager from the JSON config file.
113     static std::unique_ptr<HintManager> GetFromJSON(
114         const std::string& config_path, bool start = true);
115 
116     // Return available hints managed by HintManager
117     std::vector<std::string> GetHints() const;
118 
119     // Return stats of hints managed by HintManager
120     HintStats GetHintStats(const std::string &hint_type) const;
121 
122     // Dump internal status to fd
123     void DumpToFd(int fd);
124 
125     // Start thread loop
126     bool Start();
127 
128   protected:
129     static std::vector<std::unique_ptr<Node>> ParseNodes(
130         const std::string& json_doc);
131     static std::unordered_map<std::string, Hint> ParseActions(
132             const std::string &json_doc, const std::vector<std::unique_ptr<Node>> &nodes);
133     static bool InitHintStatus(const std::unique_ptr<HintManager> &hm);
134 
135   private:
136     HintManager(HintManager const&) = delete;
137     void operator=(HintManager const&) = delete;
138     bool ValidateHint(const std::string& hint_type) const;
139     // Helper function to update the HintStatus when DoHint
140     void DoHintStatus(const std::string &hint_type, std::chrono::milliseconds timeout_ms);
141     // Helper function to update the HintStatus when EndHint
142     void EndHintStatus(const std::string &hint_type);
143     // Helper function to take hint actions when DoHint
144     void DoHintAction(const std::string &hint_type);
145     // Helper function to take hint actions when EndHint
146     void EndHintAction(const std::string &hint_type);
147     sp<NodeLooperThread> nm_;
148     std::unordered_map<std::string, Hint> actions_;
149 };
150 
151 }  // namespace perfmgr
152 }  // namespace android
153 
154 #endif  // ANDROID_LIBPERFMGR_HINTMANAGER_H_
155