| /* |
| * 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. |
| */ |
| |
| #define LOG_TAG "VibratorManagerHalController" |
| |
| #include <utils/Log.h> |
| |
| #include <vibratorservice/VibratorManagerHalController.h> |
| |
| namespace Aidl = android::hardware::vibrator; |
| |
| namespace android { |
| |
| namespace vibrator { |
| |
| std::shared_ptr<ManagerHalWrapper> connectManagerHal(std::shared_ptr<CallbackScheduler> scheduler) { |
| static bool gHalExists = true; |
| if (gHalExists) { |
| sp<Aidl::IVibratorManager> hal = waitForVintfService<Aidl::IVibratorManager>(); |
| if (hal) { |
| ALOGV("Successfully connected to VibratorManager HAL AIDL service."); |
| return std::make_shared<AidlManagerHalWrapper>(std::move(scheduler), hal); |
| } |
| } |
| |
| gHalExists = false; |
| return std::make_shared<LegacyManagerHalWrapper>(); |
| } |
| |
| static constexpr int MAX_RETRIES = 1; |
| |
| template <typename T> |
| HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) { |
| if (result.isFailed()) { |
| ALOGE("%s failed: %s", functionName, result.errorMessage()); |
| std::lock_guard<std::mutex> lock(mConnectedHalMutex); |
| mConnectedHal->tryReconnect(); |
| } |
| return result; |
| } |
| |
| template <typename T> |
| HalResult<T> ManagerHalController::apply(ManagerHalController::hal_fn<T>& halFn, |
| const char* functionName) { |
| std::shared_ptr<ManagerHalWrapper> hal = nullptr; |
| { |
| std::lock_guard<std::mutex> lock(mConnectedHalMutex); |
| if (mConnectedHal == nullptr) { |
| // Init was never called, so connect to HAL for the first time during this call. |
| mConnectedHal = mConnector(mCallbackScheduler); |
| |
| if (mConnectedHal == nullptr) { |
| ALOGV("Skipped %s because VibratorManager HAL is not available", functionName); |
| return HalResult<T>::unsupported(); |
| } |
| } |
| hal = mConnectedHal; |
| } |
| |
| HalResult<T> ret = processHalResult(halFn(hal), functionName); |
| for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) { |
| ret = processHalResult(halFn(hal), functionName); |
| } |
| |
| return ret; |
| } |
| |
| // ------------------------------------------------------------------------------------------------- |
| |
| void ManagerHalController::init() { |
| std::lock_guard<std::mutex> lock(mConnectedHalMutex); |
| if (mConnectedHal == nullptr) { |
| mConnectedHal = mConnector(mCallbackScheduler); |
| } |
| } |
| |
| HalResult<void> ManagerHalController::ping() { |
| hal_fn<void> pingFn = [](std::shared_ptr<ManagerHalWrapper> hal) { return hal->ping(); }; |
| return apply(pingFn, "ping"); |
| } |
| |
| void ManagerHalController::tryReconnect() { |
| std::lock_guard<std::mutex> lock(mConnectedHalMutex); |
| if (mConnectedHal == nullptr) { |
| mConnectedHal = mConnector(mCallbackScheduler); |
| } else { |
| mConnectedHal->tryReconnect(); |
| } |
| } |
| |
| HalResult<ManagerCapabilities> ManagerHalController::getCapabilities() { |
| hal_fn<ManagerCapabilities> getCapabilitiesFn = [](std::shared_ptr<ManagerHalWrapper> hal) { |
| return hal->getCapabilities(); |
| }; |
| return apply(getCapabilitiesFn, "getCapabilities"); |
| } |
| |
| HalResult<std::vector<int32_t>> ManagerHalController::getVibratorIds() { |
| hal_fn<std::vector<int32_t>> getVibratorIdsFn = [](std::shared_ptr<ManagerHalWrapper> hal) { |
| return hal->getVibratorIds(); |
| }; |
| return apply(getVibratorIdsFn, "getVibratorIds"); |
| } |
| |
| HalResult<std::shared_ptr<HalController>> ManagerHalController::getVibrator(int32_t id) { |
| hal_fn<std::shared_ptr<HalController>> getVibratorFn = |
| [&](std::shared_ptr<ManagerHalWrapper> hal) { return hal->getVibrator(id); }; |
| return apply(getVibratorFn, "getVibrator"); |
| } |
| |
| HalResult<void> ManagerHalController::prepareSynced(const std::vector<int32_t>& ids) { |
| hal_fn<void> prepareSyncedFn = [&](std::shared_ptr<ManagerHalWrapper> hal) { |
| return hal->prepareSynced(ids); |
| }; |
| return apply(prepareSyncedFn, "prepareSynced"); |
| } |
| |
| HalResult<void> ManagerHalController::triggerSynced( |
| const std::function<void()>& completionCallback) { |
| hal_fn<void> triggerSyncedFn = [&](std::shared_ptr<ManagerHalWrapper> hal) { |
| return hal->triggerSynced(completionCallback); |
| }; |
| return apply(triggerSyncedFn, "triggerSynced"); |
| } |
| |
| HalResult<void> ManagerHalController::cancelSynced() { |
| hal_fn<void> cancelSyncedFn = [](std::shared_ptr<ManagerHalWrapper> hal) { |
| return hal->cancelSynced(); |
| }; |
| return apply(cancelSyncedFn, "cancelSynced"); |
| } |
| |
| }; // namespace vibrator |
| |
| }; // namespace android |