blob: 13412667e039c91a89e401a63fed7524e995b8e7 [file] [log] [blame]
/*
* 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)).c_str());
}
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 = [=, this]() {
sp<Aidl::IVibrator> vibrator;
auto result = this->getHal()->getVibrator(vibratorId, &vibrator);
return HalResultFactory::fromStatus<sp<Aidl::IVibrator>>(result, vibrator);
};
auto result = reconnectFn();
if (!result.isOk()) {
return nullptr;
}
auto vibrator = result.value();
if (!vibrator) {
return nullptr;
}
return std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator),
reconnectFn);
}
HalResult<void> AidlManagerHalWrapper::ping() {
return HalResultFactory::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 capabilities = static_cast<ManagerCapabilities>(cap);
auto ret = HalResultFactory::fromStatus<ManagerCapabilities>(result, capabilities);
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 = HalResultFactory::fromStatus<std::vector<int32_t>>(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)).c_str());
}
HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) {
auto ret = HalResultFactory::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 HalResultFactory::fromStatus(getHal()->triggerSynced(cb));
}
HalResult<void> AidlManagerHalWrapper::cancelSynced() {
auto ret = HalResultFactory::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