blob: db27bd900902402e4b09ac4e0576be906370db29 [file] [log] [blame]
Lais Andrade9e9fcc92020-04-07 20:13:08 +01001/*
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 "VibratorHalWrapper"
18
19#include <android/hardware/vibrator/1.3/IVibrator.h>
20#include <android/hardware/vibrator/BnVibratorCallback.h>
21#include <android/hardware/vibrator/IVibrator.h>
22#include <hardware/vibrator.h>
23
24#include <utils/Log.h>
25
26#include <vibratorservice/VibratorHalWrapper.h>
27
28using android::hardware::vibrator::CompositeEffect;
29using android::hardware::vibrator::Effect;
30using android::hardware::vibrator::EffectStrength;
31
32using std::chrono::milliseconds;
33
34namespace V1_0 = android::hardware::vibrator::V1_0;
35namespace V1_1 = android::hardware::vibrator::V1_1;
36namespace V1_2 = android::hardware::vibrator::V1_2;
37namespace V1_3 = android::hardware::vibrator::V1_3;
38namespace Aidl = android::hardware::vibrator;
39
40namespace android {
41
42namespace vibrator {
43
44// -------------------------------------------------------------------------------------------------
45
46template <class T>
Lais Andraded39ff7d2020-05-19 10:42:51 +000047HalResult<T> loadCached(const std::function<HalResult<T>()>& loadFn, std::optional<T>& cache) {
48 if (cache.has_value()) {
49 return HalResult<T>::ok(cache.value());
50 }
51 HalResult<T> ret = loadFn();
52 if (ret.isOk()) {
53 cache.emplace(ret.value());
54 }
55 return ret;
56}
57
58template <class T>
Lais Andrade9e9fcc92020-04-07 20:13:08 +010059bool isStaticCastValid(Effect effect) {
60 T castEffect = static_cast<T>(effect);
61 auto iter = hardware::hidl_enum_range<T>();
62 return castEffect >= *iter.begin() && castEffect <= *std::prev(iter.end());
63}
64
65template <class I, class T>
66using perform_fn = hardware::Return<void> (I::*)(T, V1_0::EffectStrength,
67 V1_0::IVibrator::perform_cb);
68
69template <class I, class T>
70HalResult<milliseconds> perform(perform_fn<I, T> performFn, sp<I> handle, T effect,
71 EffectStrength strength) {
72 V1_0::Status status;
73 int32_t lengthMs;
74 V1_0::IVibrator::perform_cb effectCallback = [&status, &lengthMs](V1_0::Status retStatus,
75 uint32_t retLengthMs) {
76 status = retStatus;
77 lengthMs = retLengthMs;
78 };
79
80 V1_0::EffectStrength effectStrength = static_cast<V1_0::EffectStrength>(strength);
81 auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback);
82
83 return HalResult<milliseconds>::fromReturn(result, status, milliseconds(lengthMs));
84}
85
86// -------------------------------------------------------------------------------------------------
87
88template <typename T>
89HalResult<T> HalResult<T>::ok(T value) {
90 return HalResult(value);
91}
92
93template <typename T>
94HalResult<T> HalResult<T>::failed() {
95 return HalResult(/* unsupported= */ false);
96}
97
98template <typename T>
99HalResult<T> HalResult<T>::unsupported() {
100 return HalResult(/* unsupported= */ true);
101}
102
103template <typename T>
104HalResult<T> HalResult<T>::fromStatus(binder::Status status, T data) {
105 if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
106 return HalResult<T>::unsupported();
107 }
108 if (status.isOk()) {
109 return HalResult<T>::ok(data);
110 }
111 return HalResult<T>::failed();
112}
113
114template <typename T>
115HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) {
116 switch (status) {
117 case V1_0::Status::OK:
118 return HalResult<T>::ok(data);
119 case V1_0::Status::UNSUPPORTED_OPERATION:
120 return HalResult<T>::unsupported();
121 default:
122 return HalResult<T>::failed();
123 }
124}
125
126template <typename T>
127template <typename R>
128HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) {
129 return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed();
130}
131
132template <typename T>
133template <typename R>
134HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) {
135 return ret.isOk() ? HalResult<T>::fromStatus(status, data) : HalResult<T>::failed();
136}
137
138// -------------------------------------------------------------------------------------------------
139
140HalResult<void> HalResult<void>::ok() {
141 return HalResult();
142}
143
144HalResult<void> HalResult<void>::failed() {
145 return HalResult(/* failed= */ true);
146}
147
148HalResult<void> HalResult<void>::unsupported() {
149 return HalResult(/* failed= */ false, /* unsupported= */ true);
150}
151
152HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
153 if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
154 return HalResult<void>::unsupported();
155 }
156 if (status.isOk()) {
157 return HalResult<void>::ok();
158 }
159 return HalResult<void>::failed();
160}
161
162HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) {
163 switch (status) {
164 case V1_0::Status::OK:
165 return HalResult<void>::ok();
166 case V1_0::Status::UNSUPPORTED_OPERATION:
167 return HalResult<void>::unsupported();
168 default:
169 return HalResult<void>::failed();
170 }
171}
172
173template <typename R>
174HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {
175 return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed();
176}
177
178// -------------------------------------------------------------------------------------------------
179
180class HalCallbackWrapper : public Aidl::BnVibratorCallback {
181public:
182 HalCallbackWrapper(const std::function<void()>& completionCallback)
183 : mCompletionCallback(completionCallback) {}
184
185 binder::Status onComplete() override {
186 mCompletionCallback();
187 return binder::Status::ok();
188 }
189
190private:
191 const std::function<void()> mCompletionCallback;
192};
193
194// -------------------------------------------------------------------------------------------------
195
196HalResult<void> AidlHalWrapper::ping() {
197 return IInterface::asBinder(mHandle)->pingBinder() ? HalResult<void>::ok()
198 : HalResult<void>::failed();
199}
200
201HalResult<void> AidlHalWrapper::on(milliseconds timeout,
202 const std::function<void()>& completionCallback) {
203 auto cb = new HalCallbackWrapper(completionCallback);
204 return HalResult<void>::fromStatus(mHandle->on(timeout.count(), cb));
205}
206
207HalResult<void> AidlHalWrapper::off() {
208 return HalResult<void>::fromStatus(mHandle->off());
209}
210
211HalResult<void> AidlHalWrapper::setAmplitude(int32_t amplitude) {
212 float convertedAmplitude = static_cast<float>(amplitude) / std::numeric_limits<uint8_t>::max();
213 return HalResult<void>::fromStatus(mHandle->setAmplitude(convertedAmplitude));
214}
215
216HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) {
217 return HalResult<void>::fromStatus(mHandle->setExternalControl(enabled));
218}
219
220HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
221 return HalResult<void>::fromStatus(mHandle->alwaysOnEnable(id, effect, strength));
222}
223
224HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
225 return HalResult<void>::fromStatus(mHandle->alwaysOnDisable(id));
226}
227
228HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000229 std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
230 static auto loadFn = [this]() {
231 int32_t capabilities = 0;
232 auto result = mHandle->getCapabilities(&capabilities);
233 return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
234 };
235 return loadCached<Capabilities>(loadFn, mCapabilities);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100236}
237
238HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffects() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000239 std::lock_guard<std::mutex> lock(mSupportedEffectsMutex);
240 static auto loadFn = [this]() {
241 std::vector<Effect> supportedEffects;
242 auto result = mHandle->getSupportedEffects(&supportedEffects);
243 return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
244 };
245 return loadCached<std::vector<Effect>>(loadFn, mSupportedEffects);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100246}
247
248HalResult<milliseconds> AidlHalWrapper::performEffect(
249 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
250 int32_t lengthMs;
251 auto cb = new HalCallbackWrapper(completionCallback);
252 auto result = mHandle->perform(effect, strength, cb, &lengthMs);
253 return HalResult<milliseconds>::fromStatus(result, milliseconds(lengthMs));
254}
255
256HalResult<void> AidlHalWrapper::performComposedEffect(
257 const std::vector<CompositeEffect>& primitiveEffects,
258 const std::function<void()>& completionCallback) {
259 auto cb = new HalCallbackWrapper(completionCallback);
260 return HalResult<void>::fromStatus(mHandle->compose(primitiveEffects, cb));
261}
262
263// -------------------------------------------------------------------------------------------------
264
265HalResult<void> HidlHalWrapperV1_0::ping() {
266 auto result = mHandleV1_0->ping();
267 return HalResult<void>::fromReturn(result);
268}
269
270HalResult<void> HidlHalWrapperV1_0::on(milliseconds timeout, const std::function<void()>&) {
271 auto result = mHandleV1_0->on(timeout.count());
272 auto status = result.withDefault(V1_0::Status::UNKNOWN_ERROR);
273 return HalResult<void>::fromStatus(status);
274}
275
276HalResult<void> HidlHalWrapperV1_0::off() {
277 auto result = mHandleV1_0->off();
278 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
279}
280
281HalResult<void> HidlHalWrapperV1_0::setAmplitude(int32_t amplitude) {
282 auto result = mHandleV1_0->setAmplitude(static_cast<uint8_t>(amplitude));
283 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
284}
285
286HalResult<void> HidlHalWrapperV1_0::setExternalControl(bool) {
287 ALOGV("Skipped setExternalControl because Vibrator HAL does not support it");
288 return HalResult<void>::unsupported();
289}
290
291HalResult<void> HidlHalWrapperV1_0::alwaysOnEnable(int32_t, Effect, EffectStrength) {
292 ALOGV("Skipped alwaysOnEnable because Vibrator HAL AIDL is not available");
293 return HalResult<void>::unsupported();
294}
295
296HalResult<void> HidlHalWrapperV1_0::alwaysOnDisable(int32_t) {
297 ALOGV("Skipped alwaysOnDisable because Vibrator HAL AIDL is not available");
298 return HalResult<void>::unsupported();
299}
300
301HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000302 std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
303 return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
304 mCapabilities);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100305}
306
307HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
308 ALOGV("Skipped getSupportedEffects because Vibrator HAL AIDL is not available");
309 return HalResult<std::vector<Effect>>::unsupported();
310}
311
312HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(Effect effect, EffectStrength strength,
313 const std::function<void()>&) {
314 if (isStaticCastValid<V1_0::Effect>(effect)) {
315 V1_0::Effect e = static_cast<V1_0::Effect>(effect);
316 return perform(&V1_0::IVibrator::perform, mHandleV1_0, e, strength);
317 }
318
319 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
320 Aidl::toString(effect).c_str());
321 return HalResult<milliseconds>::unsupported();
322}
323
324HalResult<void> HidlHalWrapperV1_0::performComposedEffect(const std::vector<CompositeEffect>&,
325 const std::function<void()>&) {
326 ALOGV("Skipped composed effect because Vibrator HAL AIDL is not available");
327 return HalResult<void>::unsupported();
328}
329
Lais Andraded39ff7d2020-05-19 10:42:51 +0000330HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
331 hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
332 Capabilities capabilities =
333 result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
334 return HalResult<Capabilities>::fromReturn(result, capabilities);
335}
336
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100337// -------------------------------------------------------------------------------------------------
338
339HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(Effect effect, EffectStrength strength,
340 const std::function<void()>&) {
341 if (isStaticCastValid<V1_0::Effect>(effect)) {
342 V1_0::Effect e = static_cast<V1_0::Effect>(effect);
343 return perform(&V1_0::IVibrator::perform, mHandleV1_0, e, strength);
344 }
345 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
346 V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
347 return perform(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength);
348 }
349
350 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
351 Aidl::toString(effect).c_str());
352 return HalResult<milliseconds>::unsupported();
353}
354
355// -------------------------------------------------------------------------------------------------
356
357HalResult<milliseconds> HidlHalWrapperV1_2::performEffect(Effect effect, EffectStrength strength,
358 const std::function<void()>&) {
359 if (isStaticCastValid<V1_0::Effect>(effect)) {
360 V1_0::Effect e = static_cast<V1_0::Effect>(effect);
361 return perform(&V1_0::IVibrator::perform, mHandleV1_0, e, strength);
362 }
363 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
364 V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
365 return perform(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength);
366 }
367 if (isStaticCastValid<V1_2::Effect>(effect)) {
368 V1_2::Effect e = static_cast<V1_2::Effect>(effect);
369 return perform(&V1_2::IVibrator::perform_1_2, mHandleV1_2, e, strength);
370 }
371
372 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
373 Aidl::toString(effect).c_str());
374 return HalResult<milliseconds>::unsupported();
375}
376
377// -------------------------------------------------------------------------------------------------
378
379HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
380 auto result = mHandleV1_3->setExternalControl(static_cast<uint32_t>(enabled));
381 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
382}
383
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100384HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(Effect effect, EffectStrength strength,
385 const std::function<void()>&) {
386 if (isStaticCastValid<V1_0::Effect>(effect)) {
387 V1_0::Effect e = static_cast<V1_0::Effect>(effect);
388 return perform(&V1_0::IVibrator::perform, mHandleV1_0, e, strength);
389 }
390 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
391 V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
392 return perform(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength);
393 }
394 if (isStaticCastValid<V1_2::Effect>(effect)) {
395 V1_2::Effect e = static_cast<V1_2::Effect>(effect);
396 return perform(&V1_2::IVibrator::perform_1_2, mHandleV1_2, e, strength);
397 }
398 if (isStaticCastValid<V1_3::Effect>(effect)) {
399 V1_3::Effect e = static_cast<V1_3::Effect>(effect);
400 return perform(&V1_3::IVibrator::perform_1_3, mHandleV1_3, e, strength);
401 }
402
403 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
404 Aidl::toString(effect).c_str());
405 return HalResult<milliseconds>::unsupported();
406}
407
Lais Andraded39ff7d2020-05-19 10:42:51 +0000408HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
409 HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
410 if (!parentResult.isOk()) {
411 // Loading for previous HAL versions already failed, so propagate failure.
412 return parentResult;
413 }
414
415 Capabilities capabilities = parentResult.value();
416 auto result = mHandleV1_3->supportsExternalControl();
417 capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
418 return HalResult<Capabilities>::fromReturn(result, capabilities);
419}
420
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100421// -------------------------------------------------------------------------------------------------
422
423}; // namespace vibrator
424
425}; // namespace android