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 #define LOG_TAG "powerhal-libperfmgr"
18 #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
19 
20 #include <log/log.h>
21 #include <processgroup/processgroup.h>
22 #include <utils/Trace.h>
23 
24 #include "PowerSessionManager.h"
25 
26 namespace aidl {
27 namespace google {
28 namespace hardware {
29 namespace power {
30 namespace impl {
31 namespace pixel {
32 
setHintManager(std::shared_ptr<HintManager> const & hint_manager)33 void PowerSessionManager::setHintManager(std::shared_ptr<HintManager> const &hint_manager) {
34     // Only initialize hintmanager instance if hint is supported.
35     if (hint_manager->IsHintSupported(kDisableBoostHintName)) {
36         mHintManager = hint_manager;
37     }
38 }
39 
updateHintMode(const std::string & mode,bool enabled)40 void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) {
41     ALOGV("PowerSessionManager::updateHintMode: mode: %s, enabled: %d", mode.c_str(), enabled);
42     if (enabled && mode.compare(0, 8, "REFRESH_") == 0) {
43         if (mode.compare("REFRESH_120FPS") == 0) {
44             mDisplayRefreshRate = 120;
45         } else if (mode.compare("REFRESH_90FPS") == 0) {
46             mDisplayRefreshRate = 90;
47         } else if (mode.compare("REFRESH_60FPS") == 0) {
48             mDisplayRefreshRate = 60;
49         }
50     }
51 }
52 
getDisplayRefreshRate()53 int PowerSessionManager::getDisplayRefreshRate() {
54     return mDisplayRefreshRate;
55 }
56 
addPowerSession(PowerHintSession * session)57 void PowerSessionManager::addPowerSession(PowerHintSession *session) {
58     std::lock_guard<std::mutex> guard(mLock);
59     for (auto t : session->getTidList()) {
60         if (mTidRefCountMap.find(t) == mTidRefCountMap.end()) {
61             if (!SetTaskProfiles(t, {"ResetUclampGrp"})) {
62                 ALOGW("Failed to set ResetUclampGrp task profile for tid:%d", t);
63             } else {
64                 mTidRefCountMap[t] = 1;
65             }
66             continue;
67         }
68         if (mTidRefCountMap[t] <= 0) {
69             ALOGE("Error! Unexpected zero/negative RefCount:%d for tid:%d", mTidRefCountMap[t], t);
70             continue;
71         }
72         mTidRefCountMap[t]++;
73     }
74     mSessions.insert(session);
75 }
76 
removePowerSession(PowerHintSession * session)77 void PowerSessionManager::removePowerSession(PowerHintSession *session) {
78     std::lock_guard<std::mutex> guard(mLock);
79     for (auto t : session->getTidList()) {
80         if (mTidRefCountMap.find(t) == mTidRefCountMap.end()) {
81             ALOGE("Unexpected Error! Failed to look up tid:%d in TidRefCountMap", t);
82             continue;
83         }
84         mTidRefCountMap[t]--;
85         if (mTidRefCountMap[t] <= 0) {
86             if (!SetTaskProfiles(t, {"NoResetUclampGrp"})) {
87                 ALOGW("Failed to set NoResetUclampGrp task profile for tid:%d", t);
88             }
89             mTidRefCountMap.erase(t);
90         }
91     }
92     mSessions.erase(session);
93 }
94 
isAnySessionActive()95 std::optional<bool> PowerSessionManager::isAnySessionActive() {
96     std::lock_guard<std::mutex> guard(mLock);
97     bool active = false;
98     for (PowerHintSession *s : mSessions) {
99         // session active and not stale is actually active.
100         if (s->isActive() && !s->isStale()) {
101             active = true;
102             break;
103         }
104     }
105     if (active == mActive) {
106         return std::nullopt;
107     } else {
108         mActive = active;
109     }
110 
111     return active;
112 }
113 
handleMessage(const Message &)114 void PowerSessionManager::handleMessage(const Message &) {
115     auto active = isAnySessionActive();
116     if (!active.has_value()) {
117         return;
118     }
119     if (active.value()) {
120         disableSystemTopAppBoost();
121     } else {
122         enableSystemTopAppBoost();
123     }
124 }
125 
enableSystemTopAppBoost()126 void PowerSessionManager::enableSystemTopAppBoost() {
127     if (mHintManager) {
128         ALOGV("PowerSessionManager::enableSystemTopAppBoost!!");
129         mHintManager->EndHint(kDisableBoostHintName);
130     }
131 }
132 
disableSystemTopAppBoost()133 void PowerSessionManager::disableSystemTopAppBoost() {
134     if (mHintManager) {
135         ALOGV("PowerSessionManager::disableSystemTopAppBoost!!");
136         mHintManager->DoHint(kDisableBoostHintName);
137     }
138 }
139 
140 // =========== PowerHintMonitor implementation start from here ===========
start()141 void PowerHintMonitor::start() {
142     if (!isRunning()) {
143         run("PowerHintMonitor", ::android::PRIORITY_HIGHEST);
144     }
145 }
146 
threadLoop()147 bool PowerHintMonitor::threadLoop() {
148     while (true) {
149         mLooper->pollOnce(-1);
150     }
151     return true;
152 }
153 
getLooper()154 sp<Looper> PowerHintMonitor::getLooper() {
155     return mLooper;
156 }
157 
158 }  // namespace pixel
159 }  // namespace impl
160 }  // namespace power
161 }  // namespace hardware
162 }  // namespace google
163 }  // namespace aidl
164