/* * 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 #include namespace Aidl = android::hardware::vibrator; namespace android { namespace vibrator { std::shared_ptr connectManagerHal(std::shared_ptr scheduler) { static bool gHalExists = true; if (gHalExists) { sp hal = waitForVintfService(); if (hal) { ALOGV("Successfully connected to VibratorManager HAL AIDL service."); return std::make_shared(std::move(scheduler), hal); } } gHalExists = false; return std::make_shared(); } static constexpr int MAX_RETRIES = 1; template HalResult ManagerHalController::processHalResult(HalResult result, const char* functionName) { if (result.isFailed()) { ALOGE("%s failed: %s", functionName, result.errorMessage()); std::lock_guard lock(mConnectedHalMutex); mConnectedHal->tryReconnect(); } return result; } template HalResult ManagerHalController::apply(ManagerHalController::hal_fn& halFn, const char* functionName) { std::shared_ptr hal = nullptr; { std::lock_guard 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::unsupported(); } } hal = mConnectedHal; } HalResult 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 lock(mConnectedHalMutex); if (mConnectedHal == nullptr) { mConnectedHal = mConnector(mCallbackScheduler); } } HalResult ManagerHalController::ping() { hal_fn pingFn = [](std::shared_ptr hal) { return hal->ping(); }; return apply(pingFn, "ping"); } void ManagerHalController::tryReconnect() { std::lock_guard lock(mConnectedHalMutex); if (mConnectedHal == nullptr) { mConnectedHal = mConnector(mCallbackScheduler); } else { mConnectedHal->tryReconnect(); } } HalResult ManagerHalController::getCapabilities() { hal_fn getCapabilitiesFn = [](std::shared_ptr hal) { return hal->getCapabilities(); }; return apply(getCapabilitiesFn, "getCapabilities"); } HalResult> ManagerHalController::getVibratorIds() { hal_fn> getVibratorIdsFn = [](std::shared_ptr hal) { return hal->getVibratorIds(); }; return apply(getVibratorIdsFn, "getVibratorIds"); } HalResult> ManagerHalController::getVibrator(int32_t id) { hal_fn> getVibratorFn = [&](std::shared_ptr hal) { return hal->getVibrator(id); }; return apply(getVibratorFn, "getVibrator"); } HalResult ManagerHalController::prepareSynced(const std::vector& ids) { hal_fn prepareSyncedFn = [&](std::shared_ptr hal) { return hal->prepareSynced(ids); }; return apply(prepareSyncedFn, "prepareSynced"); } HalResult ManagerHalController::triggerSynced( const std::function& completionCallback) { hal_fn triggerSyncedFn = [&](std::shared_ptr hal) { return hal->triggerSynced(completionCallback); }; return apply(triggerSyncedFn, "triggerSynced"); } HalResult ManagerHalController::cancelSynced() { hal_fn cancelSyncedFn = [](std::shared_ptr hal) { return hal->cancelSynced(); }; return apply(cancelSyncedFn, "cancelSynced"); } }; // namespace vibrator }; // namespace android