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