summaryrefslogtreecommitdiff
path: root/services/vibratorservice/VibratorManagerHalWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/vibratorservice/VibratorManagerHalWrapper.cpp')
-rw-r--r--services/vibratorservice/VibratorManagerHalWrapper.cpp206
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