/* * 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 #include 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 LegacyManagerHalWrapper::ping() { auto pingFn = [](HalWrapper* hal) { return hal->ping(); }; return mController->doWithRetry(pingFn, "ping"); } void LegacyManagerHalWrapper::tryReconnect() { mController->tryReconnect(); } HalResult LegacyManagerHalWrapper::getCapabilities() { return HalResult::ok(ManagerCapabilities::NONE); } HalResult> LegacyManagerHalWrapper::getVibratorIds() { if (mController->init()) { return HalResult>::ok(std::vector(1, SINGLE_VIBRATOR_ID)); } // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. return HalResult>::ok(std::vector()); } HalResult> LegacyManagerHalWrapper::getVibrator(int32_t id) { if (id == SINGLE_VIBRATOR_ID && mController->init()) { return HalResult>::ok(mController); } // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. return HalResult>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); } HalResult LegacyManagerHalWrapper::prepareSynced(const std::vector&) { return HalResult::unsupported(); } HalResult LegacyManagerHalWrapper::triggerSynced(const std::function&) { return HalResult::unsupported(); } HalResult LegacyManagerHalWrapper::cancelSynced() { return HalResult::unsupported(); } // ------------------------------------------------------------------------------------------------- std::shared_ptr AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr callbackScheduler) { std::function>()> reconnectFn = [=]() { sp vibrator; auto result = this->getHal()->getVibrator(vibratorId, &vibrator); return HalResult>::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(std::move(callbackScheduler), std::move(vibrator), reconnectFn)); } HalResult AidlManagerHalWrapper::ping() { return HalResult::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlManagerHalWrapper::tryReconnect() { sp newHandle = checkVintfService(); if (newHandle) { std::lock_guard lock(mHandleMutex); mHandle = std::move(newHandle); } } HalResult AidlManagerHalWrapper::getCapabilities() { std::lock_guard lock(mCapabilitiesMutex); if (mCapabilities.has_value()) { // Return copy of cached value. return HalResult::ok(*mCapabilities); } int32_t cap = 0; auto result = getHal()->getCapabilities(&cap); auto ret = HalResult::fromStatus(result, static_cast(cap)); if (ret.isOk()) { // Cache copy of returned value. mCapabilities.emplace(ret.value()); } return ret; } HalResult> AidlManagerHalWrapper::getVibratorIds() { std::lock_guard lock(mVibratorsMutex); if (mVibratorIds.has_value()) { // Return copy of cached values. return HalResult>::ok(*mVibratorIds); } std::vector ids; auto result = getHal()->getVibratorIds(&ids); auto ret = HalResult>::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(mCallbackScheduler, connector); mVibrators[id] = std::move(controller); } } return ret; } HalResult> AidlManagerHalWrapper::getVibrator(int32_t id) { // Make sure we cache vibrator ids and initialize the individual controllers. getVibratorIds(); std::lock_guard lock(mVibratorsMutex); auto it = mVibrators.find(id); if (it != mVibrators.end()) { return HalResult>::ok(it->second); } return HalResult>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); } HalResult AidlManagerHalWrapper::prepareSynced(const std::vector& ids) { auto ret = HalResult::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 lock(mVibratorsMutex); for (auto& id : ids) { auto it = mVibrators.find(id); if (it != mVibrators.end()) { it->second->tryReconnect(); } } } return ret; } HalResult AidlManagerHalWrapper::triggerSynced( const std::function& completionCallback) { HalResult capabilities = getCapabilities(); bool supportsCallback = capabilities.isOk() && static_cast(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; return HalResult::fromStatus(getHal()->triggerSynced(cb)); } HalResult AidlManagerHalWrapper::cancelSynced() { auto ret = HalResult::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 lock(mVibratorsMutex); for (auto& entry : mVibrators) { entry.second->tryReconnect(); } } return ret; } sp AidlManagerHalWrapper::getHal() { std::lock_guard lock(mHandleMutex); return mHandle; } }; // namespace vibrator }; // namespace android