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