• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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