blob: 94db5381442516e49ec9fbd2826c7e59bbe6c35b [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
Lais Andrade10d9dc72020-05-20 12:00:49 +000026#include <vibratorservice/VibratorCallbackScheduler.h>
Lais Andrade9e9fcc92020-04-07 20:13:08 +010027#include <vibratorservice/VibratorHalWrapper.h>
28
29using android::hardware::vibrator::CompositeEffect;
30using android::hardware::vibrator::Effect;
31using android::hardware::vibrator::EffectStrength;
32
33using std::chrono::milliseconds;
34
35namespace V1_0 = android::hardware::vibrator::V1_0;
36namespace V1_1 = android::hardware::vibrator::V1_1;
37namespace V1_2 = android::hardware::vibrator::V1_2;
38namespace V1_3 = android::hardware::vibrator::V1_3;
39namespace Aidl = android::hardware::vibrator;
40
41namespace android {
42
43namespace vibrator {
44
45// -------------------------------------------------------------------------------------------------
46
47template <class T>
Lais Andraded39ff7d2020-05-19 10:42:51 +000048HalResult<T> loadCached(const std::function<HalResult<T>()>& loadFn, std::optional<T>& cache) {
49 if (cache.has_value()) {
Lais Andrade10d9dc72020-05-20 12:00:49 +000050 // Return copy of cached value.
51 return HalResult<T>::ok(*cache);
Lais Andraded39ff7d2020-05-19 10:42:51 +000052 }
53 HalResult<T> ret = loadFn();
54 if (ret.isOk()) {
Lais Andrade10d9dc72020-05-20 12:00:49 +000055 // Cache copy of returned value.
Lais Andraded39ff7d2020-05-19 10:42:51 +000056 cache.emplace(ret.value());
57 }
58 return ret;
59}
60
61template <class T>
Lais Andrade9e9fcc92020-04-07 20:13:08 +010062bool isStaticCastValid(Effect effect) {
63 T castEffect = static_cast<T>(effect);
64 auto iter = hardware::hidl_enum_range<T>();
65 return castEffect >= *iter.begin() && castEffect <= *std::prev(iter.end());
66}
67
Lais Andrade9e9fcc92020-04-07 20:13:08 +010068// -------------------------------------------------------------------------------------------------
69
70template <typename T>
Lais Andrade9e9fcc92020-04-07 20:13:08 +010071HalResult<T> HalResult<T>::fromStatus(binder::Status status, T data) {
72 if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
73 return HalResult<T>::unsupported();
74 }
75 if (status.isOk()) {
76 return HalResult<T>::ok(data);
77 }
78 return HalResult<T>::failed();
79}
80
81template <typename T>
82HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) {
83 switch (status) {
84 case V1_0::Status::OK:
85 return HalResult<T>::ok(data);
86 case V1_0::Status::UNSUPPORTED_OPERATION:
87 return HalResult<T>::unsupported();
88 default:
89 return HalResult<T>::failed();
90 }
91}
92
93template <typename T>
94template <typename R>
95HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) {
96 return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed();
97}
98
99template <typename T>
100template <typename R>
101HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) {
102 return ret.isOk() ? HalResult<T>::fromStatus(status, data) : HalResult<T>::failed();
103}
104
105// -------------------------------------------------------------------------------------------------
106
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100107HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
108 if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
109 return HalResult<void>::unsupported();
110 }
111 if (status.isOk()) {
112 return HalResult<void>::ok();
113 }
114 return HalResult<void>::failed();
115}
116
117HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) {
118 switch (status) {
119 case V1_0::Status::OK:
120 return HalResult<void>::ok();
121 case V1_0::Status::UNSUPPORTED_OPERATION:
122 return HalResult<void>::unsupported();
123 default:
124 return HalResult<void>::failed();
125 }
126}
127
128template <typename R>
129HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {
130 return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed();
131}
132
133// -------------------------------------------------------------------------------------------------
134
135class HalCallbackWrapper : public Aidl::BnVibratorCallback {
136public:
Lais Andrade10d9dc72020-05-20 12:00:49 +0000137 HalCallbackWrapper(std::function<void()> completionCallback)
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100138 : mCompletionCallback(completionCallback) {}
139
140 binder::Status onComplete() override {
141 mCompletionCallback();
142 return binder::Status::ok();
143 }
144
145private:
146 const std::function<void()> mCompletionCallback;
147};
148
149// -------------------------------------------------------------------------------------------------
150
151HalResult<void> AidlHalWrapper::ping() {
152 return IInterface::asBinder(mHandle)->pingBinder() ? HalResult<void>::ok()
153 : HalResult<void>::failed();
154}
155
156HalResult<void> AidlHalWrapper::on(milliseconds timeout,
157 const std::function<void()>& completionCallback) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000158 HalResult<Capabilities> capabilities = getCapabilities();
159 bool supportsCallback = capabilities.isOk() &&
160 static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK);
161 auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
162
163 auto ret = HalResult<void>::fromStatus(mHandle->on(timeout.count(), cb));
164 if (!supportsCallback && ret.isOk()) {
165 mCallbackScheduler->schedule(completionCallback, timeout);
166 }
167
168 return ret;
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100169}
170
171HalResult<void> AidlHalWrapper::off() {
172 return HalResult<void>::fromStatus(mHandle->off());
173}
174
175HalResult<void> AidlHalWrapper::setAmplitude(int32_t amplitude) {
176 float convertedAmplitude = static_cast<float>(amplitude) / std::numeric_limits<uint8_t>::max();
177 return HalResult<void>::fromStatus(mHandle->setAmplitude(convertedAmplitude));
178}
179
180HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) {
181 return HalResult<void>::fromStatus(mHandle->setExternalControl(enabled));
182}
183
184HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
185 return HalResult<void>::fromStatus(mHandle->alwaysOnEnable(id, effect, strength));
186}
187
188HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
189 return HalResult<void>::fromStatus(mHandle->alwaysOnDisable(id));
190}
191
192HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000193 std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
Lais Andrade10d9dc72020-05-20 12:00:49 +0000194 return loadCached<Capabilities>(std::bind(&AidlHalWrapper::getCapabilitiesInternal, this),
195 mCapabilities);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100196}
197
198HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffects() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000199 std::lock_guard<std::mutex> lock(mSupportedEffectsMutex);
Lais Andrade10d9dc72020-05-20 12:00:49 +0000200 return loadCached<std::vector<Effect>>(std::bind(&AidlHalWrapper::getSupportedEffectsInternal,
201 this),
202 mSupportedEffects);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100203}
204
205HalResult<milliseconds> AidlHalWrapper::performEffect(
206 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000207 HalResult<Capabilities> capabilities = getCapabilities();
208 bool supportsCallback = capabilities.isOk() &&
209 static_cast<int32_t>(capabilities.value() & Capabilities::PERFORM_CALLBACK);
210 auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
211
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100212 int32_t lengthMs;
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100213 auto result = mHandle->perform(effect, strength, cb, &lengthMs);
Lais Andrade10d9dc72020-05-20 12:00:49 +0000214 milliseconds length = milliseconds(lengthMs);
215
216 auto ret = HalResult<milliseconds>::fromStatus(result, length);
217 if (!supportsCallback && ret.isOk()) {
218 mCallbackScheduler->schedule(completionCallback, length);
219 }
220
221 return ret;
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100222}
223
224HalResult<void> AidlHalWrapper::performComposedEffect(
225 const std::vector<CompositeEffect>& primitiveEffects,
226 const std::function<void()>& completionCallback) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000227 // This method should always support callbacks, so no need to double check.
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100228 auto cb = new HalCallbackWrapper(completionCallback);
229 return HalResult<void>::fromStatus(mHandle->compose(primitiveEffects, cb));
230}
231
Lais Andrade10d9dc72020-05-20 12:00:49 +0000232HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
233 int32_t capabilities = 0;
234 auto result = mHandle->getCapabilities(&capabilities);
235 return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
236}
237
238HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() {
239 std::vector<Effect> supportedEffects;
240 auto result = mHandle->getSupportedEffects(&supportedEffects);
241 return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
242}
243
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100244// -------------------------------------------------------------------------------------------------
245
246HalResult<void> HidlHalWrapperV1_0::ping() {
247 auto result = mHandleV1_0->ping();
248 return HalResult<void>::fromReturn(result);
249}
250
Lais Andrade10d9dc72020-05-20 12:00:49 +0000251HalResult<void> HidlHalWrapperV1_0::on(milliseconds timeout,
252 const std::function<void()>& completionCallback) {
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100253 auto result = mHandleV1_0->on(timeout.count());
Lais Andrade10d9dc72020-05-20 12:00:49 +0000254 auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
255 if (ret.isOk()) {
256 mCallbackScheduler->schedule(completionCallback, timeout);
257 }
258 return ret;
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100259}
260
261HalResult<void> HidlHalWrapperV1_0::off() {
262 auto result = mHandleV1_0->off();
263 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
264}
265
266HalResult<void> HidlHalWrapperV1_0::setAmplitude(int32_t amplitude) {
267 auto result = mHandleV1_0->setAmplitude(static_cast<uint8_t>(amplitude));
268 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
269}
270
271HalResult<void> HidlHalWrapperV1_0::setExternalControl(bool) {
272 ALOGV("Skipped setExternalControl because Vibrator HAL does not support it");
273 return HalResult<void>::unsupported();
274}
275
276HalResult<void> HidlHalWrapperV1_0::alwaysOnEnable(int32_t, Effect, EffectStrength) {
277 ALOGV("Skipped alwaysOnEnable because Vibrator HAL AIDL is not available");
278 return HalResult<void>::unsupported();
279}
280
281HalResult<void> HidlHalWrapperV1_0::alwaysOnDisable(int32_t) {
282 ALOGV("Skipped alwaysOnDisable because Vibrator HAL AIDL is not available");
283 return HalResult<void>::unsupported();
284}
285
286HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
Lais Andraded39ff7d2020-05-19 10:42:51 +0000287 std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
288 return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
289 mCapabilities);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100290}
291
292HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
293 ALOGV("Skipped getSupportedEffects because Vibrator HAL AIDL is not available");
294 return HalResult<std::vector<Effect>>::unsupported();
295}
296
Lais Andrade10d9dc72020-05-20 12:00:49 +0000297HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(
298 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100299 if (isStaticCastValid<V1_0::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000300 return performInternalV1_0(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100301 }
302
303 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
304 Aidl::toString(effect).c_str());
305 return HalResult<milliseconds>::unsupported();
306}
307
308HalResult<void> HidlHalWrapperV1_0::performComposedEffect(const std::vector<CompositeEffect>&,
309 const std::function<void()>&) {
310 ALOGV("Skipped composed effect because Vibrator HAL AIDL is not available");
311 return HalResult<void>::unsupported();
312}
313
Lais Andraded39ff7d2020-05-19 10:42:51 +0000314HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
315 hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
316 Capabilities capabilities =
317 result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
318 return HalResult<Capabilities>::fromReturn(result, capabilities);
319}
320
Lais Andrade10d9dc72020-05-20 12:00:49 +0000321template <class I, class T>
322HalResult<milliseconds> HidlHalWrapperV1_0::performInternal(
323 perform_fn<I, T> performFn, sp<I> handle, T effect, EffectStrength strength,
324 const std::function<void()>& completionCallback) {
325 V1_0::Status status;
326 int32_t lengthMs;
327 auto effectCallback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
328 status = retStatus;
329 lengthMs = retLengthMs;
330 };
331
332 V1_0::EffectStrength effectStrength = static_cast<V1_0::EffectStrength>(strength);
333 auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback);
334 milliseconds length = milliseconds(lengthMs);
335
336 auto ret = HalResult<milliseconds>::fromReturn(result, status, length);
337 if (ret.isOk()) {
338 mCallbackScheduler->schedule(completionCallback, length);
339 }
340
341 return ret;
342}
343
344HalResult<milliseconds> HidlHalWrapperV1_0::performInternalV1_0(
345 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
346 V1_0::Effect e = static_cast<V1_0::Effect>(effect);
347 return performInternal(&V1_0::IVibrator::perform, mHandleV1_0, e, strength, completionCallback);
348}
349
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100350// -------------------------------------------------------------------------------------------------
351
Lais Andrade10d9dc72020-05-20 12:00:49 +0000352HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(
353 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100354 if (isStaticCastValid<V1_0::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000355 return performInternalV1_0(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100356 }
357 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000358 return performInternalV1_1(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100359 }
360
361 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
362 Aidl::toString(effect).c_str());
363 return HalResult<milliseconds>::unsupported();
364}
365
Lais Andrade10d9dc72020-05-20 12:00:49 +0000366HalResult<milliseconds> HidlHalWrapperV1_1::performInternalV1_1(
367 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
368 V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
369 return performInternal(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength,
370 completionCallback);
371}
372
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100373// -------------------------------------------------------------------------------------------------
374
Lais Andrade10d9dc72020-05-20 12:00:49 +0000375HalResult<milliseconds> HidlHalWrapperV1_2::performEffect(
376 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100377 if (isStaticCastValid<V1_0::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000378 return performInternalV1_0(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100379 }
380 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000381 return performInternalV1_1(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100382 }
383 if (isStaticCastValid<V1_2::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000384 return performInternalV1_2(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100385 }
386
387 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
388 Aidl::toString(effect).c_str());
389 return HalResult<milliseconds>::unsupported();
390}
391
Lais Andrade10d9dc72020-05-20 12:00:49 +0000392HalResult<milliseconds> HidlHalWrapperV1_2::performInternalV1_2(
393 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
394 V1_2::Effect e = static_cast<V1_2::Effect>(effect);
395 return performInternal(&V1_2::IVibrator::perform_1_2, mHandleV1_2, e, strength,
396 completionCallback);
397}
398
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100399// -------------------------------------------------------------------------------------------------
400
401HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
402 auto result = mHandleV1_3->setExternalControl(static_cast<uint32_t>(enabled));
403 return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
404}
405
Lais Andrade10d9dc72020-05-20 12:00:49 +0000406HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(
407 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100408 if (isStaticCastValid<V1_0::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000409 return performInternalV1_0(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100410 }
411 if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000412 return performInternalV1_1(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100413 }
414 if (isStaticCastValid<V1_2::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000415 return performInternalV1_2(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100416 }
417 if (isStaticCastValid<V1_3::Effect>(effect)) {
Lais Andrade10d9dc72020-05-20 12:00:49 +0000418 return performInternalV1_3(effect, strength, completionCallback);
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100419 }
420
421 ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
422 Aidl::toString(effect).c_str());
423 return HalResult<milliseconds>::unsupported();
424}
425
Lais Andraded39ff7d2020-05-19 10:42:51 +0000426HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
427 HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
428 if (!parentResult.isOk()) {
429 // Loading for previous HAL versions already failed, so propagate failure.
430 return parentResult;
431 }
432
433 Capabilities capabilities = parentResult.value();
434 auto result = mHandleV1_3->supportsExternalControl();
435 capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
436 return HalResult<Capabilities>::fromReturn(result, capabilities);
437}
438
Lais Andrade10d9dc72020-05-20 12:00:49 +0000439HalResult<milliseconds> HidlHalWrapperV1_3::performInternalV1_3(
440 Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
441 V1_3::Effect e = static_cast<V1_3::Effect>(effect);
442 return performInternal(&V1_3::IVibrator::perform_1_3, mHandleV1_3, e, strength,
443 completionCallback);
444}
445
Lais Andrade9e9fcc92020-04-07 20:13:08 +0100446// -------------------------------------------------------------------------------------------------
447
448}; // namespace vibrator
449
450}; // namespace android