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