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