summaryrefslogtreecommitdiff
path: root/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
diff options
context:
space:
mode:
Diffstat (limited to 'services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h')
-rw-r--r--services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h505
1 files changed, 505 insertions, 0 deletions
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
new file mode 100644
index 0000000000..68d6647ede
--- /dev/null
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_VIBRATORHALWRAPPER_H
+#define ANDROID_OS_VIBRATORHALWRAPPER_H
+
+#include <android-base/thread_annotations.h>
+#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <android/hardware/vibrator/BnVibratorCallback.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
+
+#include <vibratorservice/VibratorCallbackScheduler.h>
+
+namespace android {
+
+namespace vibrator {
+
+// -------------------------------------------------------------------------------------------------
+
+// Result of a call to the Vibrator HAL wrapper, holding data if successful.
+template <typename T>
+class HalResult {
+public:
+ static HalResult<T> ok(T value) { return HalResult(value); }
+ static HalResult<T> failed(std::string msg) {
+ return HalResult(std::move(msg), /* unsupported= */ false);
+ }
+ static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
+
+ static HalResult<T> fromStatus(binder::Status status, T data) {
+ if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is
+ // the same as the operation being unsupported by this HAL. Should not retry.
+ return HalResult<T>::unsupported();
+ }
+ if (status.isOk()) {
+ return HalResult<T>::ok(data);
+ }
+ return HalResult<T>::failed(status.toString8().c_str());
+ }
+ static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data);
+
+ template <typename R>
+ static HalResult<T> fromReturn(hardware::Return<R>& ret, T data);
+
+ template <typename R>
+ static HalResult<T> fromReturn(hardware::Return<R>& ret,
+ hardware::vibrator::V1_0::Status status, T data);
+
+ // This will throw std::bad_optional_access if this result is not ok.
+ const T& value() const { return mValue.value(); }
+ const T valueOr(T&& defaultValue) const { return mValue.value_or(defaultValue); }
+ bool isOk() const { return !mUnsupported && mValue.has_value(); }
+ bool isFailed() const { return !mUnsupported && !mValue.has_value(); }
+ bool isUnsupported() const { return mUnsupported; }
+ const char* errorMessage() const { return mErrorMessage.c_str(); }
+ bool checkAndLogFailure(const char* functionName) const {
+ if (isFailed()) {
+ ALOGE("%s failed: %s", functionName, errorMessage());
+ return true;
+ }
+ return false;
+ }
+
+private:
+ std::optional<T> mValue;
+ std::string mErrorMessage;
+ bool mUnsupported;
+
+ explicit HalResult(T value)
+ : mValue(std::make_optional(value)), mErrorMessage(), mUnsupported(false) {}
+ explicit HalResult(std::string errorMessage, bool unsupported)
+ : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {}
+};
+
+// Empty result of a call to the Vibrator HAL wrapper.
+template <>
+class HalResult<void> {
+public:
+ static HalResult<void> ok() { return HalResult(); }
+ static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); }
+ static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); }
+
+ static HalResult<void> fromStatus(status_t status);
+ static HalResult<void> fromStatus(binder::Status status);
+ static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status status);
+
+ template <typename R>
+ static HalResult<void> fromReturn(hardware::Return<R>& ret);
+
+ bool isOk() const { return !mUnsupported && !mFailed; }
+ bool isFailed() const { return !mUnsupported && mFailed; }
+ bool isUnsupported() const { return mUnsupported; }
+ const char* errorMessage() const { return mErrorMessage.c_str(); }
+ bool checkAndLogFailure(const char* functionName) const {
+ if (isFailed()) {
+ ALOGE("%s failed: %s", functionName, errorMessage());
+ return true;
+ }
+ return false;
+ }
+
+private:
+ std::string mErrorMessage;
+ bool mFailed;
+ bool mUnsupported;
+
+ explicit HalResult(bool unsupported = false)
+ : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {}
+ explicit HalResult(std::string errorMessage)
+ : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
+};
+
+class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback {
+public:
+ HalCallbackWrapper(std::function<void()> completionCallback)
+ : mCompletionCallback(completionCallback) {}
+
+ binder::Status onComplete() override {
+ mCompletionCallback();
+ return binder::Status::ok();
+ }
+
+private:
+ const std::function<void()> mCompletionCallback;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+// Vibrator HAL capabilities.
+enum class Capabilities : int32_t {
+ NONE = 0,
+ ON_CALLBACK = hardware::vibrator::IVibrator::CAP_ON_CALLBACK,
+ PERFORM_CALLBACK = hardware::vibrator::IVibrator::CAP_PERFORM_CALLBACK,
+ AMPLITUDE_CONTROL = hardware::vibrator::IVibrator::CAP_AMPLITUDE_CONTROL,
+ EXTERNAL_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_CONTROL,
+ EXTERNAL_AMPLITUDE_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL,
+ COMPOSE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_EFFECTS,
+ COMPOSE_PWLE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_PWLE_EFFECTS,
+ ALWAYS_ON_CONTROL = hardware::vibrator::IVibrator::CAP_ALWAYS_ON_CONTROL,
+};
+
+inline Capabilities operator|(Capabilities lhs, Capabilities rhs) {
+ using underlying = typename std::underlying_type<Capabilities>::type;
+ return static_cast<Capabilities>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
+}
+
+inline Capabilities& operator|=(Capabilities& lhs, Capabilities rhs) {
+ return lhs = lhs | rhs;
+}
+
+inline Capabilities operator&(Capabilities lhs, Capabilities rhs) {
+ using underlying = typename std::underlying_type<Capabilities>::type;
+ return static_cast<Capabilities>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
+}
+
+inline Capabilities& operator&=(Capabilities& lhs, Capabilities rhs) {
+ return lhs = lhs & rhs;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+class Info {
+public:
+ const HalResult<Capabilities> capabilities;
+ const HalResult<std::vector<hardware::vibrator::Effect>> supportedEffects;
+ const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
+ const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
+ const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
+ const HalResult<std::chrono::milliseconds> primitiveDelayMax;
+ const HalResult<std::chrono::milliseconds> pwlePrimitiveDurationMax;
+ const HalResult<int32_t> compositionSizeMax;
+ const HalResult<int32_t> pwleSizeMax;
+ const HalResult<float> minFrequency;
+ const HalResult<float> resonantFrequency;
+ const HalResult<float> frequencyResolution;
+ const HalResult<float> qFactor;
+ const HalResult<std::vector<float>> maxAmplitudes;
+
+ bool checkAndLogFailure(const char*) const {
+ return capabilities.checkAndLogFailure("getCapabilities") ||
+ supportedEffects.checkAndLogFailure("getSupportedEffects") ||
+ supportedBraking.checkAndLogFailure("getSupportedBraking") ||
+ supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
+ primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
+ primitiveDelayMax.checkAndLogFailure("getPrimitiveDelayMax") ||
+ pwlePrimitiveDurationMax.checkAndLogFailure("getPwlePrimitiveDurationMax") ||
+ compositionSizeMax.checkAndLogFailure("getCompositionSizeMax") ||
+ pwleSizeMax.checkAndLogFailure("getPwleSizeMax") ||
+ minFrequency.checkAndLogFailure("getMinFrequency") ||
+ resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
+ frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
+ qFactor.checkAndLogFailure("getQFactor") ||
+ maxAmplitudes.checkAndLogFailure("getMaxAmplitudes");
+ }
+};
+
+class InfoCache {
+public:
+ Info get() {
+ return {mCapabilities,
+ mSupportedEffects,
+ mSupportedBraking,
+ mSupportedPrimitives,
+ mPrimitiveDurations,
+ mPrimitiveDelayMax,
+ mPwlePrimitiveDurationMax,
+ mCompositionSizeMax,
+ mPwleSizeMax,
+ mMinFrequency,
+ mResonantFrequency,
+ mFrequencyResolution,
+ mQFactor,
+ mMaxAmplitudes};
+ }
+
+private:
+ static const constexpr char* MSG = "never loaded";
+ HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::Effect>> mSupportedEffects =
+ HalResult<std::vector<hardware::vibrator::Effect>>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::Braking>> mSupportedBraking =
+ HalResult<std::vector<hardware::vibrator::Braking>>::failed(MSG);
+ HalResult<std::vector<hardware::vibrator::CompositePrimitive>> mSupportedPrimitives =
+ HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
+ HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
+ HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
+ HalResult<std::chrono::milliseconds> mPrimitiveDelayMax =
+ HalResult<std::chrono::milliseconds>::failed(MSG);
+ HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax =
+ HalResult<std::chrono::milliseconds>::failed(MSG);
+ HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG);
+ HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG);
+ HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
+ HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
+ HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
+ HalResult<float> mQFactor = HalResult<float>::failed(MSG);
+ HalResult<std::vector<float>> mMaxAmplitudes = HalResult<std::vector<float>>::failed(MSG);
+
+ friend class HalWrapper;
+};
+
+// Wrapper for Vibrator HAL handlers.
+class HalWrapper {
+public:
+ explicit HalWrapper(std::shared_ptr<CallbackScheduler> scheduler)
+ : mCallbackScheduler(std::move(scheduler)) {}
+ virtual ~HalWrapper() = default;
+
+ /* reloads wrapped HAL service instance without waiting. This can be used to reconnect when the
+ * service restarts, to rapidly retry after a failure.
+ */
+ virtual void tryReconnect() = 0;
+
+ Info getInfo();
+
+ virtual HalResult<void> ping() = 0;
+ virtual HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) = 0;
+ virtual HalResult<void> off() = 0;
+
+ virtual HalResult<void> setAmplitude(float amplitude) = 0;
+ virtual HalResult<void> setExternalControl(bool enabled) = 0;
+
+ virtual HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) = 0;
+ virtual HalResult<void> alwaysOnDisable(int32_t id) = 0;
+
+ virtual HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) = 0;
+
+ virtual HalResult<std::chrono::milliseconds> performComposedEffect(
+ const std::vector<hardware::vibrator::CompositeEffect>& primitives,
+ const std::function<void()>& completionCallback);
+
+ virtual HalResult<void> performPwleEffect(
+ const std::vector<hardware::vibrator::PrimitivePwle>& primitives,
+ const std::function<void()>& completionCallback);
+
+protected:
+ // Shared pointer to allow CallbackScheduler to outlive this wrapper.
+ const std::shared_ptr<CallbackScheduler> mCallbackScheduler;
+
+ // Load and cache vibrator info, returning cached result is present.
+ HalResult<Capabilities> getCapabilities();
+ HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurations();
+
+ // Request vibrator info to HAL skipping cache.
+ virtual HalResult<Capabilities> getCapabilitiesInternal() = 0;
+ virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal();
+ virtual HalResult<std::vector<hardware::vibrator::Braking>> getSupportedBrakingInternal();
+ virtual HalResult<std::vector<hardware::vibrator::CompositePrimitive>>
+ getSupportedPrimitivesInternal();
+ virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
+ const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
+ virtual HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal();
+ virtual HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal();
+ virtual HalResult<int32_t> getCompositionSizeMaxInternal();
+ virtual HalResult<int32_t> getPwleSizeMaxInternal();
+ virtual HalResult<float> getMinFrequencyInternal();
+ virtual HalResult<float> getResonantFrequencyInternal();
+ virtual HalResult<float> getFrequencyResolutionInternal();
+ virtual HalResult<float> getQFactorInternal();
+ virtual HalResult<std::vector<float>> getMaxAmplitudesInternal();
+
+private:
+ std::mutex mInfoMutex;
+ InfoCache mInfoCache GUARDED_BY(mInfoMutex);
+};
+
+// Wrapper for the AIDL Vibrator HAL.
+class AidlHalWrapper : public HalWrapper {
+public:
+ AidlHalWrapper(
+ std::shared_ptr<CallbackScheduler> scheduler, sp<hardware::vibrator::IVibrator> handle,
+ std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> reconnectFn =
+ []() {
+ return HalResult<sp<hardware::vibrator::IVibrator>>::ok(
+ checkVintfService<hardware::vibrator::IVibrator>());
+ })
+ : HalWrapper(std::move(scheduler)),
+ mReconnectFn(reconnectFn),
+ mHandle(std::move(handle)) {}
+ virtual ~AidlHalWrapper() = default;
+
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
+
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
+
+ HalResult<void> setAmplitude(float amplitude) override final;
+ HalResult<void> setExternalControl(bool enabled) override final;
+
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
+
+ HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) override final;
+
+ HalResult<std::chrono::milliseconds> performComposedEffect(
+ const std::vector<hardware::vibrator::CompositeEffect>& primitives,
+ const std::function<void()>& completionCallback) override final;
+
+ HalResult<void> performPwleEffect(
+ const std::vector<hardware::vibrator::PrimitivePwle>& primitives,
+ const std::function<void()>& completionCallback) override final;
+
+protected:
+ HalResult<Capabilities> getCapabilitiesInternal() override final;
+ HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal() override final;
+ HalResult<std::vector<hardware::vibrator::Braking>> getSupportedBrakingInternal()
+ override final;
+ HalResult<std::vector<hardware::vibrator::CompositePrimitive>> getSupportedPrimitivesInternal()
+ override final;
+ HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
+ const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
+ override final;
+ HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal() override final;
+ HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal() override final;
+ HalResult<int32_t> getCompositionSizeMaxInternal() override final;
+ HalResult<int32_t> getPwleSizeMaxInternal() override final;
+ HalResult<float> getMinFrequencyInternal() override final;
+ HalResult<float> getResonantFrequencyInternal() override final;
+ HalResult<float> getFrequencyResolutionInternal() override final;
+ HalResult<float> getQFactorInternal() override final;
+ HalResult<std::vector<float>> getMaxAmplitudesInternal() override final;
+
+private:
+ const std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> mReconnectFn;
+ std::mutex mHandleMutex;
+ sp<hardware::vibrator::IVibrator> mHandle GUARDED_BY(mHandleMutex);
+
+ sp<hardware::vibrator::IVibrator> getHal();
+};
+
+// Wrapper for the HDIL Vibrator HALs.
+template <typename I>
+class HidlHalWrapper : public HalWrapper {
+public:
+ HidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler, sp<I> handle)
+ : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
+ virtual ~HidlHalWrapper() = default;
+
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
+
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
+
+ HalResult<void> setAmplitude(float amplitude) override final;
+ virtual HalResult<void> setExternalControl(bool enabled) override;
+
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
+
+protected:
+ std::mutex mHandleMutex;
+ sp<I> mHandle GUARDED_BY(mHandleMutex);
+
+ virtual HalResult<Capabilities> getCapabilitiesInternal() override;
+
+ template <class T>
+ using perform_fn =
+ hardware::Return<void> (I::*)(T, hardware::vibrator::V1_0::EffectStrength,
+ hardware::vibrator::V1_0::IVibrator::perform_cb);
+
+ template <class T>
+ HalResult<std::chrono::milliseconds> performInternal(
+ perform_fn<T> performFn, sp<I> handle, T effect,
+ hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback);
+
+ sp<I> getHal();
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.0.
+class HidlHalWrapperV1_0 : public HidlHalWrapper<hardware::vibrator::V1_0::IVibrator> {
+public:
+ HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_0::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_0::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_0() = default;
+
+ HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) override final;
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.1.
+class HidlHalWrapperV1_1 : public HidlHalWrapper<hardware::vibrator::V1_1::IVibrator> {
+public:
+ HidlHalWrapperV1_1(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_1::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_1::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_1() = default;
+
+ HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) override final;
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.2.
+class HidlHalWrapperV1_2 : public HidlHalWrapper<hardware::vibrator::V1_2::IVibrator> {
+public:
+ HidlHalWrapperV1_2(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_2::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_2::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_2() = default;
+
+ HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) override final;
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.3.
+class HidlHalWrapperV1_3 : public HidlHalWrapper<hardware::vibrator::V1_3::IVibrator> {
+public:
+ HidlHalWrapperV1_3(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_3::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_3::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_3() = default;
+
+ HalResult<void> setExternalControl(bool enabled) override final;
+
+ HalResult<std::chrono::milliseconds> performEffect(
+ hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
+ const std::function<void()>& completionCallback) override final;
+
+protected:
+ HalResult<Capabilities> getCapabilitiesInternal() override final;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+}; // namespace vibrator
+
+}; // namespace android
+
+#endif // ANDROID_OS_VIBRATORHALWRAPPER_H