diff options
Diffstat (limited to 'services/vibratorservice/VibratorManagerHalWrapper.cpp')
-rw-r--r-- | services/vibratorservice/VibratorManagerHalWrapper.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp new file mode 100644 index 0000000000..6e660e7e41 --- /dev/null +++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp @@ -0,0 +1,206 @@ +/* + * 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 "VibratorManagerHalWrapper" + +#include <utils/Log.h> + +#include <vibratorservice/VibratorManagerHalWrapper.h> + +namespace Aidl = android::hardware::vibrator; + +namespace android { + +namespace vibrator { + +constexpr int32_t SINGLE_VIBRATOR_ID = 0; +const constexpr char* MISSING_VIBRATOR_MESSAGE_PREFIX = "No vibrator with id="; + +HalResult<void> LegacyManagerHalWrapper::ping() { + auto pingFn = [](HalWrapper* hal) { return hal->ping(); }; + return mController->doWithRetry<void>(pingFn, "ping"); +} + +void LegacyManagerHalWrapper::tryReconnect() { + mController->tryReconnect(); +} + +HalResult<ManagerCapabilities> LegacyManagerHalWrapper::getCapabilities() { + return HalResult<ManagerCapabilities>::ok(ManagerCapabilities::NONE); +} + +HalResult<std::vector<int32_t>> LegacyManagerHalWrapper::getVibratorIds() { + if (mController->init()) { + return HalResult<std::vector<int32_t>>::ok(std::vector<int32_t>(1, SINGLE_VIBRATOR_ID)); + } + // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. + return HalResult<std::vector<int32_t>>::ok(std::vector<int32_t>()); +} + +HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(int32_t id) { + if (id == SINGLE_VIBRATOR_ID && mController->init()) { + return HalResult<std::shared_ptr<HalController>>::ok(mController); + } + // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. + return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + + std::to_string(id)); +} + +HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) { + return HalResult<void>::unsupported(); +} + +HalResult<void> LegacyManagerHalWrapper::triggerSynced(const std::function<void()>&) { + return HalResult<void>::unsupported(); +} + +HalResult<void> LegacyManagerHalWrapper::cancelSynced() { + return HalResult<void>::unsupported(); +} + +// ------------------------------------------------------------------------------------------------- + +std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( + int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) { + std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=]() { + sp<Aidl::IVibrator> vibrator; + auto result = this->getHal()->getVibrator(vibratorId, &vibrator); + return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator); + }; + auto result = reconnectFn(); + if (!result.isOk()) { + return nullptr; + } + auto vibrator = result.value(); + if (!vibrator) { + return nullptr; + } + return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), + std::move(vibrator), reconnectFn)); +} + +HalResult<void> AidlManagerHalWrapper::ping() { + return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); +} + +void AidlManagerHalWrapper::tryReconnect() { + sp<Aidl::IVibratorManager> newHandle = checkVintfService<Aidl::IVibratorManager>(); + if (newHandle) { + std::lock_guard<std::mutex> lock(mHandleMutex); + mHandle = std::move(newHandle); + } +} + +HalResult<ManagerCapabilities> AidlManagerHalWrapper::getCapabilities() { + std::lock_guard<std::mutex> lock(mCapabilitiesMutex); + if (mCapabilities.has_value()) { + // Return copy of cached value. + return HalResult<ManagerCapabilities>::ok(*mCapabilities); + } + int32_t cap = 0; + auto result = getHal()->getCapabilities(&cap); + auto ret = HalResult<ManagerCapabilities>::fromStatus(result, + static_cast<ManagerCapabilities>(cap)); + if (ret.isOk()) { + // Cache copy of returned value. + mCapabilities.emplace(ret.value()); + } + return ret; +} + +HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() { + std::lock_guard<std::mutex> lock(mVibratorsMutex); + if (mVibratorIds.has_value()) { + // Return copy of cached values. + return HalResult<std::vector<int32_t>>::ok(*mVibratorIds); + } + std::vector<int32_t> ids; + auto result = getHal()->getVibratorIds(&ids); + auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids); + if (ret.isOk()) { + // Cache copy of returned value and the individual controllers. + mVibratorIds.emplace(ret.value()); + for (auto& id : ids) { + HalController::Connector connector = [&, id](auto scheduler) { + return this->connectToVibrator(id, scheduler); + }; + auto controller = std::make_unique<HalController>(mCallbackScheduler, connector); + mVibrators[id] = std::move(controller); + } + } + return ret; +} + +HalResult<std::shared_ptr<HalController>> AidlManagerHalWrapper::getVibrator(int32_t id) { + // Make sure we cache vibrator ids and initialize the individual controllers. + getVibratorIds(); + std::lock_guard<std::mutex> lock(mVibratorsMutex); + auto it = mVibrators.find(id); + if (it != mVibrators.end()) { + return HalResult<std::shared_ptr<HalController>>::ok(it->second); + } + return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + + std::to_string(id)); +} + +HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) { + auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids)); + if (ret.isOk()) { + // Force reload of all vibrator controllers that were prepared for a sync operation here. + // This will trigger calls to getVibrator(id) on each controller, so they can use the + // latest service provided by this manager. + std::lock_guard<std::mutex> lock(mVibratorsMutex); + for (auto& id : ids) { + auto it = mVibrators.find(id); + if (it != mVibrators.end()) { + it->second->tryReconnect(); + } + } + } + return ret; +} + +HalResult<void> AidlManagerHalWrapper::triggerSynced( + const std::function<void()>& completionCallback) { + HalResult<ManagerCapabilities> capabilities = getCapabilities(); + bool supportsCallback = capabilities.isOk() && + static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); + auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; + return HalResult<void>::fromStatus(getHal()->triggerSynced(cb)); +} + +HalResult<void> AidlManagerHalWrapper::cancelSynced() { + auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced()); + if (ret.isOk()) { + // Force reload of all vibrator controllers that were prepared for a sync operation before. + // This will trigger calls to getVibrator(id) on each controller, so they can use the + // latest service provided by this manager. + std::lock_guard<std::mutex> lock(mVibratorsMutex); + for (auto& entry : mVibrators) { + entry.second->tryReconnect(); + } + } + return ret; +} + +sp<Aidl::IVibratorManager> AidlManagerHalWrapper::getHal() { + std::lock_guard<std::mutex> lock(mHandleMutex); + return mHandle; +} + +}; // namespace vibrator + +}; // namespace android |