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