You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.8 KiB
207 lines
7.8 KiB
/*
|
|
* 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
|