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