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 "AdpfTypes.h"
27 #include "AppHintDesc.h"
28 #include "BackgroundWorker.h"
29 #include "GpuCapacityNode.h"
30 #include "SessionTaskMap.h"
31 
32 namespace aidl {
33 namespace google {
34 namespace hardware {
35 namespace power {
36 namespace impl {
37 namespace pixel {
38 
39 using ::android::Thread;
40 
41 constexpr char kPowerHalAdpfDisableTopAppBoost[] = "vendor.powerhal.adpf.disable.hint";
42 
43 template <class HintManagerT = ::android::perfmgr::HintManager>
44 class PowerSessionManager : public Immobile {
45   public:
46     ~PowerSessionManager() = default;
47 
48     // Update the current hint info
49     void updateHintMode(const std::string &mode, bool enabled);
50     // Add and remove power hint session
51     void addPowerSession(const std::string &idString,
52                          const std::shared_ptr<AppHintDesc> &sessionDescriptor,
53                          const std::shared_ptr<AppDescriptorTrace> &sessionTrace,
54                          const std::vector<int32_t> &threadIds, const ProcessTag procTag);
55     void removePowerSession(int64_t sessionId, const ProcessTag procTag);
56     // Replace current threads in session with threadIds
57     void setThreadsFromPowerSession(int64_t sessionId, const std::vector<int32_t> &threadIds,
58                                     const ProcessTag procTag);
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     void updateHboostStatistics(int64_t sessionId, SessionJankyLevel jankyLevel,
82                                 int32_t numOfFrames);
83 
84     void updateFrameBuckets(int64_t sessionId, const FrameBuckets &lastReportedFrames);
85 
86     // Singleton
getInstance()87     static PowerSessionManager *getInstance() {
88         static PowerSessionManager instance{};
89         return &instance;
90     }
91 
92     std::optional<Frequency> gpuFrequency() const;
93 
94     void registerSession(std::shared_ptr<void> session, int64_t sessionId);
95     void unregisterSession(int64_t sessionId);
96     // Only for testing
97     void clear();
98     std::shared_ptr<void> getSession(int64_t sessionId);
99     bool getGameModeEnableState();
100 
101   private:
102     std::optional<bool> isAnyAppSessionActive();
103     void disableSystemTopAppBoost();
104     void enableSystemTopAppBoost();
105     const std::string kDisableBoostHintName;
106 
107     // Rewrite specific
108     mutable std::mutex mSessionTaskMapMutex;
109     SessionTaskMap mSessionTaskMap;
110     std::shared_ptr<PriorityQueueWorkerPool> mPriorityQueueWorkerPool;
111 
112     // Session timeout
113     struct EventSessionTimeout {
114         std::chrono::steady_clock::time_point timeStamp;
115         int64_t sessionId{0};
116         int voteId{0};
117     };
118     void handleEvent(const EventSessionTimeout &e);
119     TemplatePriorityQueueWorker<EventSessionTimeout> mEventSessionTimeoutWorker;
120 
121     // Calculate uclamp range
122     void applyUclampLocked(int64_t sessionId, std::chrono::steady_clock::time_point timePoint)
123             REQUIRES(mSessionTaskMapMutex);
124 
125     void applyGpuVotesLocked(int64_t sessionId, std::chrono::steady_clock::time_point timePoint)
126             REQUIRES(mSessionTaskMapMutex);
127 
128     void applyCpuAndGpuVotes(int64_t sessionId, std::chrono::steady_clock::time_point timePoint);
129     // Force a session active or in-active, helper for other methods
130     void forceSessionActive(int64_t sessionId, bool isActive);
131 
132     // Singleton
PowerSessionManager()133     PowerSessionManager()
134         : kDisableBoostHintName(::android::base::GetProperty(kPowerHalAdpfDisableTopAppBoost,
135                                                              "ADPF_DISABLE_TA_BOOST")),
136           mPriorityQueueWorkerPool(new PriorityQueueWorkerPool(1, "adpf_handler")),
137           mEventSessionTimeoutWorker([&](auto e) { handleEvent(e); }, mPriorityQueueWorkerPool),
138           mGpuCapacityNode(createGpuCapacityNode()) {}
139     PowerSessionManager(PowerSessionManager const &) = delete;
140     PowerSessionManager &operator=(PowerSessionManager const &) = delete;
141 
142     std::optional<std::unique_ptr<GpuCapacityNode>> const mGpuCapacityNode;
143 
144     std::mutex mSessionMapMutex;
145     std::unordered_map<int, std::weak_ptr<void>> mSessionMap GUARDED_BY(mSessionMapMutex);
146 
147     std::atomic<bool> mGameModeEnabled{false};
148 };
149 
150 }  // namespace pixel
151 }  // namespace impl
152 }  // namespace power
153 }  // namespace hardware
154 }  // namespace google
155 }  // namespace aidl
156