1 /*
2  * Copyright 2021 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 <android-base/properties.h>
20 #include <perfmgr/HintManager.h>
21 #include <utils/Mutex.h>
22 
23 #include <mutex>
24 #include <optional>
25 
26 #include "AppHintDesc.h"
27 #include "BackgroundWorker.h"
28 #include "GpuCapacityNode.h"
29 #include "SessionTaskMap.h"
30 
31 namespace aidl {
32 namespace google {
33 namespace hardware {
34 namespace power {
35 namespace impl {
36 namespace pixel {
37 
38 using ::android::Thread;
39 
40 constexpr char kPowerHalAdpfDisableTopAppBoost[] = "vendor.powerhal.adpf.disable.hint";
41 
42 template <class HintManagerT = ::android::perfmgr::HintManager>
43 class PowerSessionManager : public Immobile {
44   public:
45     ~PowerSessionManager() = default;
46 
47     // Update the current hint info
48     void updateHintMode(const std::string &mode, bool enabled);
49     void updateHintBoost(const std::string &boost, int32_t durationMs);
50     int getDisplayRefreshRate();
51     // Add and remove power hint session
52     void addPowerSession(const std::string &idString,
53                          const std::shared_ptr<AppHintDesc> &sessionDescriptor,
54                          const std::shared_ptr<AppDescriptorTrace> &sessionTrace,
55                          const std::vector<int32_t> &threadIds);
56     void removePowerSession(int64_t sessionId);
57     // Replace current threads in session with threadIds
58     void setThreadsFromPowerSession(int64_t sessionId, const std::vector<int32_t> &threadIds);
59     // Pause and resume power hint session
60     void pause(int64_t sessionId);
61     void resume(int64_t sessionId);
62 
63     void updateUniversalBoostMode();
64     void dumpToFd(int fd);
65 
66     void updateTargetWorkDuration(int64_t sessionId, AdpfVoteType voteId,
67                                   std::chrono::nanoseconds durationNs);
68 
69     // Set vote for power hint session
70     void voteSet(int64_t sessionId, AdpfVoteType voteId, int uclampMin, int uclampMax,
71                  std::chrono::steady_clock::time_point startTime,
72                  std::chrono::nanoseconds durationNs);
73     void voteSet(int64_t sessionId, AdpfVoteType voteId, Cycles capacity,
74                  std::chrono::steady_clock::time_point startTime,
75                  std::chrono::nanoseconds durationNs);
76 
77     void disableBoosts(int64_t sessionId);
78 
79     void setPreferPowerEfficiency(int64_t sessionId, bool enabled);
80 
81     // Singleton
getInstance()82     static PowerSessionManager *getInstance() {
83         static PowerSessionManager instance{};
84         return &instance;
85     }
86 
87     std::optional<Frequency> gpuFrequency() const;
88 
89     void registerSession(std::shared_ptr<void> session, int64_t sessionId);
90     void unregisterSession(int64_t sessionId);
91     // Only for testing
92     void clear();
93     std::shared_ptr<void> getSession(int64_t sessionId);
94 
95   private:
96     std::optional<bool> isAnyAppSessionActive();
97     void disableSystemTopAppBoost();
98     void enableSystemTopAppBoost();
99     const std::string kDisableBoostHintName;
100 
101     int mDisplayRefreshRate;
102 
103     // Rewrite specific
104     mutable std::mutex mSessionTaskMapMutex;
105     SessionTaskMap mSessionTaskMap;
106     std::shared_ptr<PriorityQueueWorkerPool> mPriorityQueueWorkerPool;
107 
108     // Session timeout
109     struct EventSessionTimeout {
110         std::chrono::steady_clock::time_point timeStamp;
111         int64_t sessionId{0};
112         int voteId{0};
113     };
114     void handleEvent(const EventSessionTimeout &e);
115     TemplatePriorityQueueWorker<EventSessionTimeout> mEventSessionTimeoutWorker;
116 
117     // Calculate uclamp range
118     void applyUclampLocked(int64_t sessionId, std::chrono::steady_clock::time_point timePoint)
119             REQUIRES(mSessionTaskMapMutex);
120 
121     void applyGpuVotesLocked(int64_t sessionId, std::chrono::steady_clock::time_point timePoint)
122             REQUIRES(mSessionTaskMapMutex);
123 
124     void applyCpuAndGpuVotes(int64_t sessionId, std::chrono::steady_clock::time_point timePoint);
125     // Force a session active or in-active, helper for other methods
126     void forceSessionActive(int64_t sessionId, bool isActive);
127 
128     // Singleton
PowerSessionManager()129     PowerSessionManager()
130         : kDisableBoostHintName(::android::base::GetProperty(kPowerHalAdpfDisableTopAppBoost,
131                                                              "ADPF_DISABLE_TA_BOOST")),
132           mDisplayRefreshRate(60),
133           mPriorityQueueWorkerPool(new PriorityQueueWorkerPool(1, "adpf_handler")),
134           mEventSessionTimeoutWorker([&](auto e) { handleEvent(e); }, mPriorityQueueWorkerPool),
135           mGpuCapacityNode(createGpuCapacityNode()) {}
136     PowerSessionManager(PowerSessionManager const &) = delete;
137     PowerSessionManager &operator=(PowerSessionManager const &) = delete;
138 
139     std::optional<std::unique_ptr<GpuCapacityNode>> const mGpuCapacityNode;
140 
141     std::mutex mSessionMapMutex;
142     std::map<int, std::weak_ptr<void>> mSessionMap GUARDED_BY(mSessionMapMutex);
143 };
144 
145 }  // namespace pixel
146 }  // namespace impl
147 }  // namespace power
148 }  // namespace hardware
149 }  // namespace google
150 }  // namespace aidl
151