1 /*
2 * Copyright (C) 2018 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 "[email protected]"
19
20 #include "Power.h"
21
22 #include <mutex>
23
24 #include <android-base/file.h>
25 #include <android-base/logging.h>
26 #include <android-base/properties.h>
27 #include <android-base/stringprintf.h>
28 #include <android-base/strings.h>
29
30 #include <utils/Log.h>
31 #include <utils/Trace.h>
32
33 #include "AudioStreaming.h"
34 #include "disp-power/DisplayLowPower.h"
35
36 namespace android {
37 namespace hardware {
38 namespace power {
39 namespace V1_3 {
40 namespace implementation {
41
42 using ::android::hardware::hidl_vec;
43 using ::android::hardware::Return;
44 using ::android::hardware::Void;
45 using ::android::hardware::power::V1_0::Feature;
46 using ::android::hardware::power::V1_0::Status;
47
48 constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
49 constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
50 constexpr char kPowerHalInitProp[] = "vendor.powerhal.init";
51 constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
52 constexpr char kPowerHalConfigPath[] = "/vendor/etc/powerhint.json";
53
54 static const std::map<enum CameraStreamingMode, std::string> kCamStreamingHint = {
55 {CAMERA_STREAMING_OFF, "CAMERA_STREAMING_OFF"},
56 {CAMERA_STREAMING, "CAMERA_STREAMING"},
57 {CAMERA_STREAMING_1080P, "CAMERA_STREAMING_1080P"},
58 {CAMERA_STREAMING_60FPS, "CAMERA_STREAMING_60FPS"},
59 {CAMERA_STREAMING_4K, "CAMERA_STREAMING_4K"},
60 {CAMERA_STREAMING_SECURE, "CAMERA_STREAMING_SECURE"}};
61
Power()62 Power::Power()
63 : mHintManager(nullptr),
64 mInteractionHandler(nullptr),
65 mDisplayLowPower(nullptr),
66 mVRModeOn(false),
67 mSustainedPerfModeOn(false),
68 mCameraStreamingMode(CAMERA_STREAMING_OFF),
69 mReady(false) {
70 mInitThread = std::thread([this]() {
71 android::base::WaitForProperty(kPowerHalInitProp, "1");
72 mHintManager = HintManager::GetFromJSON(kPowerHalConfigPath);
73 if (!mHintManager) {
74 LOG(FATAL) << "Invalid config: " << kPowerHalConfigPath;
75 }
76 mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager);
77 mInteractionHandler->Init();
78 mDisplayLowPower = std::make_unique<DisplayLowPower>();
79 mDisplayLowPower->Init();
80 std::string state = android::base::GetProperty(kPowerHalStateProp, "");
81 if (state == "CAMERA_STREAMING") {
82 ALOGI("Initialize with CAMERA_STREAMING on");
83 mHintManager->DoHint("CAMERA_STREAMING");
84 mCameraStreamingMode = CAMERA_STREAMING;
85 } else if (state == "CAMERA_STREAMING_1080P") {
86 ALOGI("Initialize CAMERA_STREAMING_1080P on");
87 mHintManager->DoHint("CAMERA_STREAMING_1080P");
88 mCameraStreamingMode = CAMERA_STREAMING_1080P;
89 } else if (state == "CAMERA_STREAMING_60FPS") {
90 ALOGI("Initialize CAMERA_STREAMING_60FPS on");
91 mHintManager->DoHint("CAMERA_STREAMING_60FPS");
92 mCameraStreamingMode = CAMERA_STREAMING_60FPS;
93 } else if (state == "CAMERA_STREAMING_4K") {
94 ALOGI("Initialize with CAMERA_STREAMING_4K on");
95 mHintManager->DoHint("CAMERA_STREAMING_4K");
96 mCameraStreamingMode = CAMERA_STREAMING_4K;
97 } else if (state == "CAMERA_STREAMING_SECURE") {
98 ALOGI("Initialize with CAMERA_STREAMING_SECURE on");
99 mHintManager->DoHint("CAMERA_STREAMING_SECURE");
100 mCameraStreamingMode = CAMERA_STREAMING_SECURE;
101 } else if (state == "SUSTAINED_PERFORMANCE") {
102 ALOGI("Initialize with SUSTAINED_PERFORMANCE on");
103 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
104 mSustainedPerfModeOn = true;
105 } else if (state == "VR_MODE") {
106 ALOGI("Initialize with VR_MODE on");
107 mHintManager->DoHint("VR_MODE");
108 mVRModeOn = true;
109 } else if (state == "VR_SUSTAINED_PERFORMANCE") {
110 ALOGI("Initialize with SUSTAINED_PERFORMANCE and VR_MODE on");
111 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
112 mSustainedPerfModeOn = true;
113 mVRModeOn = true;
114 } else {
115 ALOGI("Initialize PowerHAL");
116 }
117
118 state = android::base::GetProperty(kPowerHalAudioProp, "");
119 if (state == "AUDIO_LOW_LATENCY") {
120 ALOGI("Initialize with AUDIO_LOW_LATENCY on");
121 mHintManager->DoHint("AUDIO_LOW_LATENCY");
122 }
123
124 state = android::base::GetProperty(kPowerHalRenderingProp, "");
125 if (state == "EXPENSIVE_RENDERING") {
126 ALOGI("Initialize with EXPENSIVE_RENDERING on");
127 mHintManager->DoHint("EXPENSIVE_RENDERING");
128 }
129 // Now start to take powerhint
130 mReady.store(true);
131 ALOGI("PowerHAL ready to process hints");
132 });
133 mInitThread.detach();
134 }
135
136 // Methods from ::android::hardware::power::V1_0::IPower follow.
setInteractive(bool)137 Return<void> Power::setInteractive(bool /* interactive */) {
138 return Void();
139 }
140
powerHint(PowerHint_1_0 hint,int32_t data)141 Return<void> Power::powerHint(PowerHint_1_0 hint, int32_t data) {
142 if (!mReady) {
143 return Void();
144 }
145 ATRACE_INT(android::hardware::power::V1_0::toString(hint).c_str(), data);
146 ALOGD_IF(hint != PowerHint_1_0::INTERACTION, "%s: %d",
147 android::hardware::power::V1_0::toString(hint).c_str(), static_cast<int>(data));
148 switch (hint) {
149 case PowerHint_1_0::INTERACTION:
150 if (mVRModeOn || mSustainedPerfModeOn) {
151 ALOGV("%s: ignoring due to other active perf hints", __func__);
152 } else {
153 mInteractionHandler->Acquire(data);
154 }
155 break;
156 case PowerHint_1_0::SUSTAINED_PERFORMANCE:
157 if (data && !mSustainedPerfModeOn) {
158 if (!mVRModeOn) { // Sustained mode only.
159 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
160 } else { // Sustained + VR mode.
161 mHintManager->EndHint("VR_MODE");
162 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
163 }
164 mSustainedPerfModeOn = true;
165 } else if (!data && mSustainedPerfModeOn) {
166 mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
167 mHintManager->EndHint("SUSTAINED_PERFORMANCE");
168 if (mVRModeOn) { // Switch back to VR Mode.
169 mHintManager->DoHint("VR_MODE");
170 }
171 mSustainedPerfModeOn = false;
172 }
173 break;
174 case PowerHint_1_0::VR_MODE:
175 if (data && !mVRModeOn) {
176 if (!mSustainedPerfModeOn) { // VR mode only.
177 mHintManager->DoHint("VR_MODE");
178 } else { // Sustained + VR mode.
179 mHintManager->EndHint("SUSTAINED_PERFORMANCE");
180 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
181 }
182 mVRModeOn = true;
183 } else if (!data && mVRModeOn) {
184 mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
185 mHintManager->EndHint("VR_MODE");
186 if (mSustainedPerfModeOn) { // Switch back to sustained Mode.
187 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
188 }
189 mVRModeOn = false;
190 }
191 break;
192 case PowerHint_1_0::LAUNCH:
193 if (mVRModeOn || mSustainedPerfModeOn) {
194 ALOGV("%s: ignoring due to other active perf hints", __func__);
195 } else {
196 if (data) {
197 // Hint until canceled
198 mHintManager->DoHint("LAUNCH");
199 } else {
200 mHintManager->EndHint("LAUNCH");
201 }
202 }
203 break;
204 case PowerHint_1_0::LOW_POWER:
205 mDisplayLowPower->SetDisplayLowPower(static_cast<bool>(data));
206 break;
207 default:
208 break;
209 }
210 return Void();
211 }
212
setFeature(Feature,bool)213 Return<void> Power::setFeature(Feature /*feature*/, bool /*activate*/) {
214 // Nothing to do
215 return Void();
216 }
217
getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)218 Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
219 LOG(ERROR) << "getPlatformLowPowerStats not supported. Use IPowerStats HAL.";
220 _hidl_cb({}, Status::SUCCESS);
221 return Void();
222 }
223
224 // Methods from ::android::hardware::power::V1_1::IPower follow.
getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb)225 Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
226 LOG(ERROR) << "getSubsystemLowPowerStats not supported. Use IPowerStats HAL.";
227 _hidl_cb({}, Status::SUCCESS);
228 return Void();
229 }
230
powerHintAsync(PowerHint_1_0 hint,int32_t data)231 Return<void> Power::powerHintAsync(PowerHint_1_0 hint, int32_t data) {
232 // just call the normal power hint in this oneway function
233 return powerHint(hint, data);
234 }
235
236 // Methods from ::android::hardware::power::V1_2::IPower follow.
powerHintAsync_1_2(PowerHint_1_2 hint,int32_t data)237 Return<void> Power::powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) {
238 if (!mReady) {
239 return Void();
240 }
241
242 ATRACE_INT(android::hardware::power::V1_2::toString(hint).c_str(), data);
243 ALOGD_IF(hint >= PowerHint_1_2::AUDIO_STREAMING, "%s: %d",
244 android::hardware::power::V1_2::toString(hint).c_str(), static_cast<int>(data));
245
246 switch (hint) {
247 case PowerHint_1_2::AUDIO_LOW_LATENCY:
248 if (data) {
249 // Hint until canceled
250 mHintManager->DoHint("AUDIO_LOW_LATENCY");
251 } else {
252 mHintManager->EndHint("AUDIO_LOW_LATENCY");
253 }
254 break;
255 case PowerHint_1_2::AUDIO_STREAMING:
256 if (mVRModeOn || mSustainedPerfModeOn) {
257 ALOGV("%s: ignoring due to other active perf hints", __func__);
258 } else {
259 if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::AUDIO_STREAMING_ON)) {
260 mHintManager->DoHint("AUDIO_STREAMING");
261 } else if (data ==
262 static_cast<int32_t>(AUDIO_STREAMING_HINT::AUDIO_STREAMING_OFF)) {
263 mHintManager->EndHint("AUDIO_STREAMING");
264 } else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_SHORT)) {
265 mHintManager->DoHint("TPU_BOOST",
266 std::chrono::milliseconds(TPU_HINT_DURATION_MS::SHORT));
267 } else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_LONG)) {
268 mHintManager->DoHint("TPU_BOOST",
269 std::chrono::milliseconds(TPU_HINT_DURATION_MS::LONG));
270 } else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_OFF)) {
271 mHintManager->EndHint("TPU_BOOST");
272 } else {
273 ALOGE("AUDIO STREAMING INVALID DATA: %d", data);
274 }
275 }
276 break;
277 case PowerHint_1_2::CAMERA_LAUNCH:
278 if (data > 0) {
279 mHintManager->DoHint("CAMERA_LAUNCH");
280 } else if (data == 0) {
281 mHintManager->EndHint("CAMERA_LAUNCH");
282 } else {
283 ALOGE("CAMERA LAUNCH INVALID DATA: %d", data);
284 }
285 break;
286 case PowerHint_1_2::CAMERA_STREAMING: {
287 const enum CameraStreamingMode mode = static_cast<enum CameraStreamingMode>(data);
288 if (mode < CAMERA_STREAMING_OFF || mode >= CAMERA_STREAMING_MAX) {
289 ALOGE("CAMERA STREAMING INVALID Mode: %d", mode);
290 break;
291 }
292
293 if (mCameraStreamingMode == mode)
294 break;
295
296 // turn it off first if any previous hint.
297 if ((mCameraStreamingMode != CAMERA_STREAMING_OFF)) {
298 const auto modeValue = kCamStreamingHint.at(mCameraStreamingMode);
299 mHintManager->EndHint(modeValue);
300 if ((mCameraStreamingMode != CAMERA_STREAMING_SECURE)) {
301 // Boost 1s for tear down if not secure streaming use case
302 mHintManager->DoHint("CAMERA_LAUNCH", std::chrono::seconds(1));
303 }
304 }
305
306 if (mode != CAMERA_STREAMING_OFF) {
307 const auto hintValue = kCamStreamingHint.at(mode);
308 mHintManager->DoHint(hintValue);
309 }
310
311 mCameraStreamingMode = mode;
312 const auto prop = (mCameraStreamingMode == CAMERA_STREAMING_OFF)
313 ? ""
314 : kCamStreamingHint.at(mode).c_str();
315 if (!android::base::SetProperty(kPowerHalStateProp, prop)) {
316 ALOGE("%s: could set powerHAL state %s property", __func__, prop);
317 }
318 break;
319 }
320 case PowerHint_1_2::CAMERA_SHOT:
321 if (data > 0) {
322 mHintManager->DoHint("CAMERA_SHOT", std::chrono::milliseconds(data));
323 } else if (data == 0) {
324 mHintManager->EndHint("CAMERA_SHOT");
325 } else {
326 ALOGE("CAMERA SHOT INVALID DATA: %d", data);
327 }
328 break;
329 default:
330 return powerHint(static_cast<PowerHint_1_0>(hint), data);
331 }
332 return Void();
333 }
334
335 // Methods from ::android::hardware::power::V1_3::IPower follow.
powerHintAsync_1_3(PowerHint_1_3 hint,int32_t data)336 Return<void> Power::powerHintAsync_1_3(PowerHint_1_3 hint, int32_t data) {
337 if (!mReady) {
338 return Void();
339 }
340
341 if (hint == PowerHint_1_3::EXPENSIVE_RENDERING) {
342 ATRACE_INT(android::hardware::power::V1_3::toString(hint).c_str(), data);
343 if (mVRModeOn || mSustainedPerfModeOn) {
344 ALOGV("%s: ignoring due to other active perf hints", __func__);
345 } else {
346 if (data > 0) {
347 mHintManager->DoHint("EXPENSIVE_RENDERING");
348 } else {
349 mHintManager->EndHint("EXPENSIVE_RENDERING");
350 }
351 }
352 } else {
353 return powerHintAsync_1_2(static_cast<PowerHint_1_2>(hint), data);
354 }
355 return Void();
356 }
357
boolToString(bool b)358 constexpr const char *boolToString(bool b) {
359 return b ? "true" : "false";
360 }
361
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)362 Return<void> Power::debug(const hidl_handle &handle, const hidl_vec<hidl_string> &) {
363 if (handle != nullptr && handle->numFds >= 1 && mReady) {
364 int fd = handle->data[0];
365
366 std::string buf(android::base::StringPrintf(
367 "HintManager Running: %s\n"
368 "VRMode: %s\n"
369 "CameraStreamingMode: %s\n"
370 "SustainedPerformanceMode: %s\n",
371 boolToString(mHintManager->IsRunning()), boolToString(mVRModeOn),
372 kCamStreamingHint.at(mCameraStreamingMode).c_str(),
373 boolToString(mSustainedPerfModeOn)));
374 // Dump nodes through libperfmgr
375 mHintManager->DumpToFd(fd);
376 if (!android::base::WriteStringToFd(buf, fd)) {
377 PLOG(ERROR) << "Failed to dump state to fd";
378 }
379 fsync(fd);
380 }
381 return Void();
382 }
383
384 } // namespace implementation
385 } // namespace V1_3
386 } // namespace power
387 } // namespace hardware
388 } // namespace android
389