diff options
Diffstat (limited to 'services/vibratorservice/include/vibratorservice/VibratorHalController.h')
-rw-r--r-- | services/vibratorservice/include/vibratorservice/VibratorHalController.h | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h new file mode 100644 index 0000000000..6c31e2b882 --- /dev/null +++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h @@ -0,0 +1,121 @@ +/* + * 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_VIBRATORHALCONTROLLER_H +#define ANDROID_OS_VIBRATORHALCONTROLLER_H + +#include <android-base/thread_annotations.h> +#include <android/hardware/vibrator/IVibrator.h> + +#include <vibratorservice/VibratorCallbackScheduler.h> +#include <vibratorservice/VibratorHalWrapper.h> + +namespace android { + +namespace vibrator { + +std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler); + +template <typename T> +using HalFunction = std::function<T(HalWrapper*)>; + +// Controller for Vibrator HAL handle. +// This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects +// after each failed api call. This also ensures connecting to the service is thread-safe. +class HalController { +public: + using Connector = + std::function<std::shared_ptr<HalWrapper>(std::shared_ptr<CallbackScheduler>)>; + + HalController() : HalController(std::make_shared<CallbackScheduler>(), &connectHal) {} + HalController(std::shared_ptr<CallbackScheduler> callbackScheduler, Connector connector) + : mConnector(connector), + mConnectedHal(nullptr), + mCallbackScheduler(std::move(callbackScheduler)) {} + virtual ~HalController() = default; + + /* Connects to the newest HAL version available, possibly waiting for the registered service to + * become available. This will automatically be called at the first API usage if it was not + * manually called beforehand. Calling this manually during the setup phase can avoid slowing + * the first API call later on. Returns true if any HAL version is available, false otherwise. + */ + virtual bool init(); + + /* Reloads HAL service instance without waiting. This relies on the HAL version found by init() + * to rapidly reconnect to the specific HAL service, or defers to init() if it was never called. + */ + virtual void tryReconnect(); + + /* Returns info loaded from the connected HAL. This allows partial results to be returned if any + * of the Info fields has failed, but also retried on any failure. + */ + Info getInfo() { + static Info sDefaultInfo = InfoCache().get(); + return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); + } + + /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the + * result has failed. Parameter functionName is for logging purposes. + */ + template <typename T> + HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { + return apply(halFn, HalResult<T>::unsupported(), functionName); + } + +private: + static constexpr int MAX_RETRIES = 1; + + Connector mConnector; + std::mutex mConnectedHalMutex; + // Shared pointer to allow local copies to be used by different threads. + std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex); + // Shared pointer to allow copies to be passed to possible recreated mConnectedHal instances. + std::shared_ptr<CallbackScheduler> mCallbackScheduler; + + /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the + * result has failed. Given default value is returned when no HAL is available, and given + * function name is for logging purposes. + */ + template <typename T> + T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) { + if (!init()) { + ALOGV("Skipped %s because Vibrator HAL is not available", functionName); + return defaultValue; + } + std::shared_ptr<HalWrapper> hal; + { + std::lock_guard<std::mutex> lock(mConnectedHalMutex); + hal = mConnectedHal; + } + + for (int i = 0; i < MAX_RETRIES; i++) { + T result = halFn(hal.get()); + if (result.checkAndLogFailure(functionName)) { + tryReconnect(); + } else { + return result; + } + } + + return halFn(hal.get()); + } +}; + +}; // namespace vibrator + +}; // namespace android + +#endif // ANDROID_OS_VIBRATORHALCONTROLLER_H |