1 /*
2  * Copyright (C) 2020 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 
19 #include "Power.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android-base/strings.h>
25 #include <fmq/AidlMessageQueue.h>
26 #include <fmq/EventFlag.h>
27 #include <perfmgr/HintManager.h>
28 #include <utils/Log.h>
29 
30 #include <cstdint>
31 #include <memory>
32 #include <optional>
33 
34 #include "AdpfTypes.h"
35 #include "ChannelManager.h"
36 #include "PowerHintSession.h"
37 #include "PowerSessionManager.h"
38 #include "SupportManager.h"
39 #include "disp-power/DisplayLowPower.h"
40 
41 namespace aidl {
42 namespace google {
43 namespace hardware {
44 namespace power {
45 namespace impl {
46 namespace pixel {
47 using ::android::perfmgr::HintManager;
48 
49 constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
50 constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
51 constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
52 
Power(std::shared_ptr<DisplayLowPower> dlpw)53 Power::Power(std::shared_ptr<DisplayLowPower> dlpw)
54     : mDisplayLowPower(dlpw),
55       mInteractionHandler(nullptr),
56       mVRModeOn(false),
57       mSustainedPerfModeOn(false) {
58     mInteractionHandler = std::make_unique<InteractionHandler>();
59     mInteractionHandler->Init();
60 
61     std::string state = ::android::base::GetProperty(kPowerHalStateProp, "");
62     if (state == "SUSTAINED_PERFORMANCE") {
63         LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE on";
64         HintManager::GetInstance()->DoHint("SUSTAINED_PERFORMANCE");
65         mSustainedPerfModeOn = true;
66     } else if (state == "VR") {
67         LOG(INFO) << "Initialize with VR on";
68         HintManager::GetInstance()->DoHint(state);
69         mVRModeOn = true;
70     } else if (state == "VR_SUSTAINED_PERFORMANCE") {
71         LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE and VR on";
72         HintManager::GetInstance()->DoHint("VR_SUSTAINED_PERFORMANCE");
73         mSustainedPerfModeOn = true;
74         mVRModeOn = true;
75     } else {
76         LOG(INFO) << "Initialize PowerHAL";
77     }
78 
79     state = ::android::base::GetProperty(kPowerHalAudioProp, "");
80     if (state == "AUDIO_STREAMING_LOW_LATENCY") {
81         LOG(INFO) << "Initialize with AUDIO_LOW_LATENCY on";
82         HintManager::GetInstance()->DoHint(state);
83     }
84 
85     state = ::android::base::GetProperty(kPowerHalRenderingProp, "");
86     if (state == "EXPENSIVE_RENDERING") {
87         LOG(INFO) << "Initialize with EXPENSIVE_RENDERING on";
88         HintManager::GetInstance()->DoHint("EXPENSIVE_RENDERING");
89     }
90 
91     auto status = this->getInterfaceVersion(&mServiceVersion);
92     LOG(INFO) << "PowerHAL InterfaceVersion:" << mServiceVersion << " isOK: " << status.isOk();
93 
94     mSupportInfo = SupportManager::makeSupportInfo();
95 }
96 
setMode(Mode type,bool enabled)97 ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
98     LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled;
99     if (HintManager::GetInstance()->IsAdpfSupported()) {
100         PowerSessionManager<>::getInstance()->updateHintMode(toString(type), enabled);
101     }
102     switch (type) {
103         case Mode::LOW_POWER:
104             mDisplayLowPower->SetDisplayLowPower(enabled);
105             if (enabled) {
106                 HintManager::GetInstance()->DoHint(toString(type));
107             } else {
108                 HintManager::GetInstance()->EndHint(toString(type));
109             }
110             break;
111         case Mode::SUSTAINED_PERFORMANCE:
112             if (enabled && !mSustainedPerfModeOn) {
113                 if (!mVRModeOn) {  // Sustained mode only.
114                     HintManager::GetInstance()->DoHint("SUSTAINED_PERFORMANCE");
115                 } else {  // Sustained + VR mode.
116                     HintManager::GetInstance()->EndHint("VR");
117                     HintManager::GetInstance()->DoHint("VR_SUSTAINED_PERFORMANCE");
118                 }
119                 mSustainedPerfModeOn = true;
120             } else if (!enabled && mSustainedPerfModeOn) {
121                 HintManager::GetInstance()->EndHint("VR_SUSTAINED_PERFORMANCE");
122                 HintManager::GetInstance()->EndHint("SUSTAINED_PERFORMANCE");
123                 if (mVRModeOn) {  // Switch back to VR Mode.
124                     HintManager::GetInstance()->DoHint("VR");
125                 }
126                 mSustainedPerfModeOn = false;
127             }
128             break;
129         case Mode::VR:
130             if (enabled && !mVRModeOn) {
131                 if (!mSustainedPerfModeOn) {  // VR mode only.
132                     HintManager::GetInstance()->DoHint("VR");
133                 } else {  // Sustained + VR mode.
134                     HintManager::GetInstance()->EndHint("SUSTAINED_PERFORMANCE");
135                     HintManager::GetInstance()->DoHint("VR_SUSTAINED_PERFORMANCE");
136                 }
137                 mVRModeOn = true;
138             } else if (!enabled && mVRModeOn) {
139                 HintManager::GetInstance()->EndHint("VR_SUSTAINED_PERFORMANCE");
140                 HintManager::GetInstance()->EndHint("VR");
141                 if (mSustainedPerfModeOn) {  // Switch back to sustained Mode.
142                     HintManager::GetInstance()->DoHint("SUSTAINED_PERFORMANCE");
143                 }
144                 mVRModeOn = false;
145             }
146             break;
147         case Mode::LAUNCH:
148             if (mVRModeOn || mSustainedPerfModeOn) {
149                 break;
150             }
151             [[fallthrough]];
152         case Mode::DOUBLE_TAP_TO_WAKE:
153             [[fallthrough]];
154         case Mode::FIXED_PERFORMANCE:
155             [[fallthrough]];
156         case Mode::EXPENSIVE_RENDERING:
157             [[fallthrough]];
158         case Mode::INTERACTIVE:
159             [[fallthrough]];
160         case Mode::DEVICE_IDLE:
161             [[fallthrough]];
162         case Mode::DISPLAY_INACTIVE:
163             [[fallthrough]];
164         case Mode::AUDIO_STREAMING_LOW_LATENCY:
165             [[fallthrough]];
166         case Mode::CAMERA_STREAMING_SECURE:
167             [[fallthrough]];
168         case Mode::CAMERA_STREAMING_LOW:
169             [[fallthrough]];
170         case Mode::CAMERA_STREAMING_MID:
171             [[fallthrough]];
172         case Mode::CAMERA_STREAMING_HIGH:
173             [[fallthrough]];
174         case Mode::GAME_LOADING:
175             [[fallthrough]];
176         default:
177             if (enabled) {
178                 HintManager::GetInstance()->DoHint(toString(type));
179             } else {
180                 HintManager::GetInstance()->EndHint(toString(type));
181             }
182             break;
183     }
184 
185     return ndk::ScopedAStatus::ok();
186 }
187 
isModeSupported(Mode type,bool * _aidl_return)188 ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) {
189     bool supported = supportFromBitset(mSupportInfo.modes, type);
190     LOG(INFO) << "Power Mode " << toString(type) << " isModeSupported: " << supported;
191     *_aidl_return = supported;
192     return ndk::ScopedAStatus::ok();
193 }
194 
setBoost(Boost type,int32_t durationMs)195 ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
196     LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs;
197     switch (type) {
198         case Boost::INTERACTION:
199             if (mVRModeOn || mSustainedPerfModeOn) {
200                 break;
201             }
202             mInteractionHandler->Acquire(durationMs);
203             break;
204         case Boost::DISPLAY_UPDATE_IMMINENT:
205             [[fallthrough]];
206         case Boost::ML_ACC:
207             [[fallthrough]];
208         case Boost::AUDIO_LAUNCH:
209             [[fallthrough]];
210         case Boost::CAMERA_LAUNCH:
211             [[fallthrough]];
212         case Boost::CAMERA_SHOT:
213             [[fallthrough]];
214         default:
215             if (mVRModeOn || mSustainedPerfModeOn) {
216                 break;
217             }
218             if (durationMs > 0) {
219                 HintManager::GetInstance()->DoHint(toString(type),
220                                                    std::chrono::milliseconds(durationMs));
221             } else if (durationMs == 0) {
222                 HintManager::GetInstance()->DoHint(toString(type));
223             } else {
224                 HintManager::GetInstance()->EndHint(toString(type));
225             }
226             break;
227     }
228 
229     return ndk::ScopedAStatus::ok();
230 }
231 
isBoostSupported(Boost type,bool * _aidl_return)232 ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) {
233     bool supported = supportFromBitset(mSupportInfo.boosts, type);
234     LOG(INFO) << "Power oost " << toString(type) << " isBoostSupported: " << supported;
235     *_aidl_return = supported;
236     return ndk::ScopedAStatus::ok();
237 }
238 
boolToString(bool b)239 constexpr const char *boolToString(bool b) {
240     return b ? "true" : "false";
241 }
242 
dump(int fd,const char **,uint32_t)243 binder_status_t Power::dump(int fd, const char **, uint32_t) {
244     std::string buf(::android::base::StringPrintf(
245             "HintManager Running: %s\n"
246             "VRMode: %s\n"
247             "SustainedPerformanceMode: %s\n",
248             boolToString(HintManager::GetInstance()->IsRunning()), boolToString(mVRModeOn),
249             boolToString(mSustainedPerfModeOn)));
250     // Dump nodes through libperfmgr
251     HintManager::GetInstance()->DumpToFd(fd);
252     PowerSessionManager<>::getInstance()->dumpToFd(fd);
253     if (!::android::base::WriteStringToFd(buf, fd)) {
254         PLOG(ERROR) << "Failed to dump state to fd";
255     }
256     fsync(fd);
257     return STATUS_OK;
258 }
259 
getCpuHeadroom(const CpuHeadroomParams & _,CpuHeadroomResult *)260 ndk::ScopedAStatus Power::getCpuHeadroom(const CpuHeadroomParams &_, CpuHeadroomResult *) {
261     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
262 }
263 
getGpuHeadroom(const GpuHeadroomParams & _,GpuHeadroomResult *)264 ndk::ScopedAStatus Power::getGpuHeadroom(const GpuHeadroomParams &_, GpuHeadroomResult *) {
265     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
266 }
267 
createHintSession(int32_t tgid,int32_t uid,const std::vector<int32_t> & threadIds,int64_t durationNanos,std::shared_ptr<IPowerHintSession> * _aidl_return)268 ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid,
269                                             const std::vector<int32_t> &threadIds,
270                                             int64_t durationNanos,
271                                             std::shared_ptr<IPowerHintSession> *_aidl_return) {
272     SessionConfig config;
273     return createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, SessionTag::OTHER,
274                                        &config, _aidl_return);
275 }
276 
getHintSessionPreferredRate(int64_t * outNanoseconds)277 ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t *outNanoseconds) {
278     *outNanoseconds = HintManager::GetInstance()->IsAdpfSupported()
279                               ? HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs
280                               : 0;
281     if (*outNanoseconds <= 0) {
282         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
283     }
284 
285     return ndk::ScopedAStatus::ok();
286 }
287 
createHintSessionWithConfig(int32_t tgid,int32_t uid,const std::vector<int32_t> & threadIds,int64_t durationNanos,SessionTag tag,SessionConfig * config,std::shared_ptr<IPowerHintSession> * _aidl_return)288 ndk::ScopedAStatus Power::createHintSessionWithConfig(
289         int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds, int64_t durationNanos,
290         SessionTag tag, SessionConfig *config, std::shared_ptr<IPowerHintSession> *_aidl_return) {
291     if (!HintManager::GetInstance()->IsAdpfSupported()) {
292         *_aidl_return = nullptr;
293         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
294     }
295     if (threadIds.size() == 0) {
296         LOG(ERROR) << "Error: threadIds.size() shouldn't be " << threadIds.size();
297         *_aidl_return = nullptr;
298         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
299     }
300     std::shared_ptr<PowerHintSession<>> session =
301             ndk::SharedRefBase::make<PowerHintSession<>>(tgid, uid, threadIds, durationNanos, tag);
302 
303     *_aidl_return = session;
304     session->getSessionConfig(config);
305     PowerSessionManager<>::getInstance()->registerSession(session, config->id);
306 
307     return ndk::ScopedAStatus::ok();
308 }
309 
getSessionChannel(int32_t tgid,int32_t uid,ChannelConfig * _aidl_return)310 ndk::ScopedAStatus Power::getSessionChannel(int32_t tgid, int32_t uid,
311                                             ChannelConfig *_aidl_return) {
312     if (ChannelManager<>::getInstance()->getChannelConfig(tgid, uid, _aidl_return)) {
313         return ndk::ScopedAStatus::ok();
314     }
315     return ndk::ScopedAStatus::fromStatus(EX_ILLEGAL_STATE);
316 }
317 
closeSessionChannel(int32_t tgid,int32_t uid)318 ndk::ScopedAStatus Power::closeSessionChannel(int32_t tgid, int32_t uid) {
319     ChannelManager<>::getInstance()->closeChannel(tgid, uid);
320     return ndk::ScopedAStatus::ok();
321 }
322 
getSupportInfo(SupportInfo * _aidl_return)323 ndk::ScopedAStatus Power::getSupportInfo(SupportInfo *_aidl_return) {
324     // Copy the support object into the binder
325     *_aidl_return = mSupportInfo;
326     return ndk::ScopedAStatus::ok();
327 }
328 
sendCompositionData(const std::vector<CompositionData> &)329 ndk::ScopedAStatus Power::sendCompositionData(const std::vector<CompositionData> &) {
330     LOG(INFO) << "Composition data received!";
331     return ndk::ScopedAStatus::ok();
332 }
333 
sendCompositionUpdate(const CompositionUpdate &)334 ndk::ScopedAStatus Power::sendCompositionUpdate(const CompositionUpdate &) {
335     LOG(INFO) << "Composition update received!";
336     return ndk::ScopedAStatus::ok();
337 }
338 
339 }  // namespace pixel
340 }  // namespace impl
341 }  // namespace power
342 }  // namespace hardware
343 }  // namespace google
344 }  // namespace aidl
345