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 "HalWrapper"
18 #include <android/hardware/power/Boost.h>
19 #include <android/hardware/power/IPowerHintSession.h>
20 #include <android/hardware/power/Mode.h>
21 #include <powermanager/PowerHalWrapper.h>
22 #include <utils/Log.h>
23
24 #include <cinttypes>
25
26 using namespace android::hardware::power;
27 namespace Aidl = android::hardware::power;
28
29 namespace android {
30
31 namespace power {
32
33 // -------------------------------------------------------------------------------------------------
34
toHalResult(const binder::Status & result)35 inline HalResult<void> toHalResult(const binder::Status& result) {
36 if (result.isOk()) {
37 return HalResult<void>::ok();
38 }
39 ALOGE("Power HAL request failed: %s", result.toString8().c_str());
40 return HalResult<void>::fromStatus(result);
41 }
42
43 template <typename T>
44 template <typename R>
fromReturn(hardware::Return<R> & ret,T data)45 HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) {
46 return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description());
47 }
48
49 template <typename T>
50 template <typename R>
fromReturn(hardware::Return<R> & ret,V1_0::Status status,T data)51 HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) {
52 return ret.isOk() ? HalResult<T>::fromStatus(status, data)
53 : HalResult<T>::failed(ret.description());
54 }
55
56 // -------------------------------------------------------------------------------------------------
57
fromStatus(status_t status)58 HalResult<void> HalResult<void>::fromStatus(status_t status) {
59 if (status == android::OK) {
60 return HalResult<void>::ok();
61 }
62 return HalResult<void>::failed(statusToString(status));
63 }
64
fromStatus(binder::Status status)65 HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
66 if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
67 return HalResult<void>::unsupported();
68 }
69 if (status.isOk()) {
70 return HalResult<void>::ok();
71 }
72 return HalResult<void>::failed(std::string(status.toString8().c_str()));
73 }
74
75 template <typename R>
fromReturn(hardware::Return<R> & ret)76 HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {
77 return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description());
78 }
79 // -------------------------------------------------------------------------------------------------
80
setBoost(Boost boost,int32_t durationMs)81 HalResult<void> EmptyHalWrapper::setBoost(Boost boost, int32_t durationMs) {
82 ALOGV("Skipped setBoost %s with duration %dms because Power HAL not available",
83 toString(boost).c_str(), durationMs);
84 return HalResult<void>::unsupported();
85 }
86
setMode(Mode mode,bool enabled)87 HalResult<void> EmptyHalWrapper::setMode(Mode mode, bool enabled) {
88 ALOGV("Skipped setMode %s to %s because Power HAL not available", toString(mode).c_str(),
89 enabled ? "true" : "false");
90 return HalResult<void>::unsupported();
91 }
92
createHintSession(int32_t,int32_t,const std::vector<int32_t> & threadIds,int64_t)93 HalResult<sp<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSession(
94 int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) {
95 ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available",
96 threadIds.size());
97 return HalResult<sp<Aidl::IPowerHintSession>>::unsupported();
98 }
99
getHintSessionPreferredRate()100 HalResult<int64_t> EmptyHalWrapper::getHintSessionPreferredRate() {
101 ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available");
102 return HalResult<int64_t>::unsupported();
103 }
104
105 // -------------------------------------------------------------------------------------------------
106
setBoost(Boost boost,int32_t durationMs)107 HalResult<void> HidlHalWrapperV1_0::setBoost(Boost boost, int32_t durationMs) {
108 if (boost == Boost::INTERACTION) {
109 return sendPowerHint(V1_3::PowerHint::INTERACTION, durationMs);
110 } else {
111 ALOGV("Skipped setBoost %s because Power HAL AIDL not available", toString(boost).c_str());
112 return HalResult<void>::unsupported();
113 }
114 }
115
setMode(Mode mode,bool enabled)116 HalResult<void> HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) {
117 uint32_t data = enabled ? 1 : 0;
118 switch (mode) {
119 case Mode::LAUNCH:
120 return sendPowerHint(V1_3::PowerHint::LAUNCH, data);
121 case Mode::LOW_POWER:
122 return sendPowerHint(V1_3::PowerHint::LOW_POWER, data);
123 case Mode::SUSTAINED_PERFORMANCE:
124 return sendPowerHint(V1_3::PowerHint::SUSTAINED_PERFORMANCE, data);
125 case Mode::VR:
126 return sendPowerHint(V1_3::PowerHint::VR_MODE, data);
127 case Mode::INTERACTIVE:
128 return setInteractive(enabled);
129 case Mode::DOUBLE_TAP_TO_WAKE:
130 return setFeature(V1_0::Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, enabled);
131 default:
132 ALOGV("Skipped setMode %s because Power HAL AIDL not available",
133 toString(mode).c_str());
134 return HalResult<void>::unsupported();
135 }
136 }
137
sendPowerHint(V1_3::PowerHint hintId,uint32_t data)138 HalResult<void> HidlHalWrapperV1_0::sendPowerHint(V1_3::PowerHint hintId, uint32_t data) {
139 auto ret = mHandleV1_0->powerHint(static_cast<V1_0::PowerHint>(hintId), data);
140 return HalResult<void>::fromReturn(ret);
141 }
142
setInteractive(bool enabled)143 HalResult<void> HidlHalWrapperV1_0::setInteractive(bool enabled) {
144 auto ret = mHandleV1_0->setInteractive(enabled);
145 return HalResult<void>::fromReturn(ret);
146 }
147
setFeature(V1_0::Feature feature,bool enabled)148 HalResult<void> HidlHalWrapperV1_0::setFeature(V1_0::Feature feature, bool enabled) {
149 auto ret = mHandleV1_0->setFeature(feature, enabled);
150 return HalResult<void>::fromReturn(ret);
151 }
152
createHintSession(int32_t,int32_t,const std::vector<int32_t> & threadIds,int64_t)153 HalResult<sp<hardware::power::IPowerHintSession>> HidlHalWrapperV1_0::createHintSession(
154 int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) {
155 ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available",
156 threadIds.size());
157 return HalResult<sp<Aidl::IPowerHintSession>>::unsupported();
158 }
159
getHintSessionPreferredRate()160 HalResult<int64_t> HidlHalWrapperV1_0::getHintSessionPreferredRate() {
161 ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available");
162 return HalResult<int64_t>::unsupported();
163 }
164
165 // -------------------------------------------------------------------------------------------------
166
sendPowerHint(V1_3::PowerHint hintId,uint32_t data)167 HalResult<void> HidlHalWrapperV1_1::sendPowerHint(V1_3::PowerHint hintId, uint32_t data) {
168 auto handle = static_cast<V1_1::IPower*>(mHandleV1_0.get());
169 auto ret = handle->powerHintAsync(static_cast<V1_0::PowerHint>(hintId), data);
170 return HalResult<void>::fromReturn(ret);
171 }
172
173 // -------------------------------------------------------------------------------------------------
174
sendPowerHint(V1_3::PowerHint hintId,uint32_t data)175 HalResult<void> HidlHalWrapperV1_2::sendPowerHint(V1_3::PowerHint hintId, uint32_t data) {
176 auto handle = static_cast<V1_2::IPower*>(mHandleV1_0.get());
177 auto ret = handle->powerHintAsync_1_2(static_cast<V1_2::PowerHint>(hintId), data);
178 return HalResult<void>::fromReturn(ret);
179 }
180
setBoost(Boost boost,int32_t durationMs)181 HalResult<void> HidlHalWrapperV1_2::setBoost(Boost boost, int32_t durationMs) {
182 switch (boost) {
183 case Boost::CAMERA_SHOT:
184 return sendPowerHint(V1_3::PowerHint::CAMERA_SHOT, durationMs);
185 case Boost::CAMERA_LAUNCH:
186 return sendPowerHint(V1_3::PowerHint::CAMERA_LAUNCH, durationMs);
187 default:
188 return HidlHalWrapperV1_1::setBoost(boost, durationMs);
189 }
190 }
191
setMode(Mode mode,bool enabled)192 HalResult<void> HidlHalWrapperV1_2::setMode(Mode mode, bool enabled) {
193 uint32_t data = enabled ? 1 : 0;
194 switch (mode) {
195 case Mode::CAMERA_STREAMING_SECURE:
196 case Mode::CAMERA_STREAMING_LOW:
197 case Mode::CAMERA_STREAMING_MID:
198 case Mode::CAMERA_STREAMING_HIGH:
199 return sendPowerHint(V1_3::PowerHint::CAMERA_STREAMING, data);
200 case Mode::AUDIO_STREAMING_LOW_LATENCY:
201 return sendPowerHint(V1_3::PowerHint::AUDIO_LOW_LATENCY, data);
202 default:
203 return HidlHalWrapperV1_1::setMode(mode, enabled);
204 }
205 }
206
207 // -------------------------------------------------------------------------------------------------
208
setMode(Mode mode,bool enabled)209 HalResult<void> HidlHalWrapperV1_3::setMode(Mode mode, bool enabled) {
210 uint32_t data = enabled ? 1 : 0;
211 if (mode == Mode::EXPENSIVE_RENDERING) {
212 return sendPowerHint(V1_3::PowerHint::EXPENSIVE_RENDERING, data);
213 }
214 return HidlHalWrapperV1_2::setMode(mode, enabled);
215 }
216
sendPowerHint(V1_3::PowerHint hintId,uint32_t data)217 HalResult<void> HidlHalWrapperV1_3::sendPowerHint(V1_3::PowerHint hintId, uint32_t data) {
218 auto handle = static_cast<V1_3::IPower*>(mHandleV1_0.get());
219 auto ret = handle->powerHintAsync_1_3(hintId, data);
220 return HalResult<void>::fromReturn(ret);
221 }
222
223 // -------------------------------------------------------------------------------------------------
224
setBoost(Boost boost,int32_t durationMs)225 HalResult<void> AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) {
226 std::unique_lock<std::mutex> lock(mBoostMutex);
227 size_t idx = static_cast<size_t>(boost);
228
229 // Quick return if boost is not supported by HAL
230 if (idx >= mBoostSupportedArray.size() || mBoostSupportedArray[idx] == HalSupport::OFF) {
231 ALOGV("Skipped setBoost %s because Power HAL doesn't support it", toString(boost).c_str());
232 return HalResult<void>::unsupported();
233 }
234
235 if (mBoostSupportedArray[idx] == HalSupport::UNKNOWN) {
236 bool isSupported = false;
237 auto isSupportedRet = mHandle->isBoostSupported(boost, &isSupported);
238 if (!isSupportedRet.isOk()) {
239 ALOGE("Skipped setBoost %s because check support failed with: %s",
240 toString(boost).c_str(), isSupportedRet.toString8().c_str());
241 // return HalResult::FAILED;
242 return HalResult<void>::fromStatus(isSupportedRet);
243 }
244
245 mBoostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
246 if (!isSupported) {
247 ALOGV("Skipped setBoost %s because Power HAL doesn't support it",
248 toString(boost).c_str());
249 return HalResult<void>::unsupported();
250 }
251 }
252 lock.unlock();
253
254 return toHalResult(mHandle->setBoost(boost, durationMs));
255 }
256
setMode(Mode mode,bool enabled)257 HalResult<void> AidlHalWrapper::setMode(Mode mode, bool enabled) {
258 std::unique_lock<std::mutex> lock(mModeMutex);
259 size_t idx = static_cast<size_t>(mode);
260
261 // Quick return if mode is not supported by HAL
262 if (idx >= mModeSupportedArray.size() || mModeSupportedArray[idx] == HalSupport::OFF) {
263 ALOGV("Skipped setMode %s because Power HAL doesn't support it", toString(mode).c_str());
264 return HalResult<void>::unsupported();
265 }
266
267 if (mModeSupportedArray[idx] == HalSupport::UNKNOWN) {
268 bool isSupported = false;
269 auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported);
270 if (!isSupportedRet.isOk()) {
271 return HalResult<void>::failed(isSupportedRet.toString8().c_str());
272 }
273
274 mModeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
275 if (!isSupported) {
276 ALOGV("Skipped setMode %s because Power HAL doesn't support it",
277 toString(mode).c_str());
278 return HalResult<void>::unsupported();
279 }
280 }
281 lock.unlock();
282
283 return toHalResult(mHandle->setMode(mode, enabled));
284 }
285
createHintSession(int32_t tgid,int32_t uid,const std::vector<int32_t> & threadIds,int64_t durationNanos)286 HalResult<sp<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSession(
287 int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) {
288 sp<IPowerHintSession> appSession;
289 return HalResult<sp<Aidl::IPowerHintSession>>::
290 fromStatus(mHandle->createHintSession(tgid, uid, threadIds, durationNanos, &appSession),
291 appSession);
292 }
293
getHintSessionPreferredRate()294 HalResult<int64_t> AidlHalWrapper::getHintSessionPreferredRate() {
295 int64_t rate = -1;
296 auto result = mHandle->getHintSessionPreferredRate(&rate);
297 return HalResult<int64_t>::fromStatus(result, rate);
298 }
299
300 // -------------------------------------------------------------------------------------------------
301
302 } // namespace power
303
304 } // namespace android
305