Create vibrator manager HAL wrapper
Create wrapper class for the future IVibratorManager HAL service, with a
legacy implementation over existing IVibrator HAL services (using
existing wrappers and controller for those).
Bug: 166586119
Test: atest libvibratorservice_test
Change-Id: If20a7ab8398e4456d0665d8c3bd1d6806697ed5b
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index c45a1a1..fa742c5 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -19,6 +19,7 @@
"VibratorCallbackScheduler.cpp",
"VibratorHalController.cpp",
"VibratorHalWrapper.cpp",
+ "VibratorManagerHalWrapper.cpp",
],
aidl: {
diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp
index 46175ad..e8606ca 100644
--- a/services/vibratorservice/VibratorHalController.cpp
+++ b/services/vibratorservice/VibratorHalController.cpp
@@ -46,8 +46,6 @@
// -------------------------------------------------------------------------------------------------
-static constexpr int MAX_RETRIES = 1;
-
std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
static bool gHalExists = true;
if (!gHalExists) {
@@ -89,6 +87,8 @@
// -------------------------------------------------------------------------------------------------
+static constexpr int MAX_RETRIES = 1;
+
template <typename T>
HalResult<T> HalController::processHalResult(HalResult<T> result, const char* functionName) {
if (result.isFailed()) {
@@ -126,11 +126,12 @@
// -------------------------------------------------------------------------------------------------
-void HalController::init() {
+bool HalController::init() {
std::lock_guard<std::mutex> lock(mConnectedHalMutex);
if (mConnectedHal == nullptr) {
mConnectedHal = mHalConnector->connect(mCallbackScheduler);
}
+ return mConnectedHal != nullptr;
}
HalResult<void> HalController::ping() {
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp
new file mode 100644
index 0000000..71955af
--- /dev/null
+++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 android {
+
+namespace vibrator {
+
+constexpr int32_t SINGLE_VIBRATOR_ID = 0;
+
+HalResult<void> LegacyManagerHalWrapper::ping() {
+ return mController->ping();
+}
+
+void LegacyManagerHalWrapper::tryReconnect() {
+ mController->tryReconnect();
+}
+
+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("No vibrator with id = " +
+ 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();
+}
+
+}; // namespace vibrator
+
+}; // namespace android
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
index 3b61f42..d1028a4 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
@@ -51,11 +51,19 @@
mConnectedHal(nullptr) {}
virtual ~HalController() = default;
- void init();
+ /* Connects to the newest HAL version available, possibly waiting for the registered service to
+ * become available. This will automatically be called at the first API usage if it was not
+ * manually called beforehand. Calling this manually during the setup phase can avoid slowing
+ * the first API call later on. Returns true if any HAL version is available, false otherwise.
+ */
+ virtual bool init();
- HalResult<void> ping() final override;
- void tryReconnect() final override;
+ /* reloads HAL service instance without waiting. This relies on the HAL version found by init()
+ * to rapidly reconnect to the specific HAL service, or defers to init() if it was never called.
+ */
+ virtual void tryReconnect() override;
+ virtual HalResult<void> ping() override;
HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) final override;
HalResult<void> off() final override;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 7b99bbb..bcb735d 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -140,9 +140,12 @@
: mCallbackScheduler(std::move(scheduler)) {}
virtual ~HalWrapper() = default;
- virtual HalResult<void> ping() = 0;
+ /* reloads wrapped HAL service instance without waiting. This can be used to reconnect when the
+ * service restarts, to rapidly retry after a failure.
+ */
virtual void tryReconnect() = 0;
+ virtual HalResult<void> ping() = 0;
virtual HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) = 0;
virtual HalResult<void> off() = 0;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
new file mode 100644
index 0000000..99947a5
--- /dev/null
+++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H
+#define ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H
+
+#include <vibratorservice/VibratorHalController.h>
+
+namespace android {
+
+namespace vibrator {
+
+// Wrapper for VibratorManager HAL handlers.
+class ManagerHalWrapper {
+public:
+ ManagerHalWrapper() = default;
+ virtual ~ManagerHalWrapper() = default;
+
+ virtual HalResult<void> ping() = 0;
+
+ /* reloads wrapped HAL service instance without waiting. This can be used to reconnect when the
+ * service restarts, to rapidly retry after a failure.
+ */
+ virtual void tryReconnect() = 0;
+
+ virtual HalResult<std::vector<int32_t>> getVibratorIds() = 0;
+ virtual HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) = 0;
+
+ virtual HalResult<void> prepareSynced(const std::vector<int32_t>& ids) = 0;
+ virtual HalResult<void> triggerSynced(const std::function<void()>& completionCallback) = 0;
+ virtual HalResult<void> cancelSynced() = 0;
+};
+
+// Wrapper for the VibratorManager over single Vibrator HAL.
+class LegacyManagerHalWrapper : public ManagerHalWrapper {
+public:
+ LegacyManagerHalWrapper() : LegacyManagerHalWrapper(std::make_shared<HalController>()) {}
+ explicit LegacyManagerHalWrapper(std::shared_ptr<HalController> controller)
+ : mController(std::move(controller)) {}
+ virtual ~LegacyManagerHalWrapper() = default;
+
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
+
+ HalResult<std::vector<int32_t>> getVibratorIds() override final;
+ HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) override final;
+
+ HalResult<void> prepareSynced(const std::vector<int32_t>& ids) override final;
+ HalResult<void> triggerSynced(const std::function<void()>& completionCallback) override final;
+ HalResult<void> cancelSynced() override final;
+
+private:
+ const std::shared_ptr<HalController> mController;
+};
+
+}; // namespace vibrator
+
+}; // namespace android
+
+#endif // ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 9033124..5fc6d45 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -23,6 +23,7 @@
"VibratorHalWrapperHidlV1_1Test.cpp",
"VibratorHalWrapperHidlV1_2Test.cpp",
"VibratorHalWrapperHidlV1_3Test.cpp",
+ "VibratorManagerHalWrapperLegacyTest.cpp",
],
cflags: [
"-Wall",
diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp
index f04e016..cda5e9a 100644
--- a/services/vibratorservice/test/VibratorHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp
@@ -184,11 +184,11 @@
// -------------------------------------------------------------------------------------------------
TEST_F(VibratorHalControllerTest, TestInit) {
- mController->init();
+ ASSERT_TRUE(mController->init());
ASSERT_EQ(1, mConnectCounter);
// Noop when wrapper was already initialized.
- mController->init();
+ ASSERT_TRUE(mController->init());
ASSERT_EQ(1, mConnectCounter);
}
@@ -339,6 +339,7 @@
std::make_unique<vibrator::HalController>(std::move(failingHalConnector), nullptr);
ASSERT_EQ(0, mConnectCounter);
+ ASSERT_FALSE(mController->init());
ASSERT_TRUE(mController->ping().isUnsupported());
ASSERT_TRUE(mController->on(10ms, []() {}).isUnsupported());
ASSERT_TRUE(mController->off().isUnsupported());
@@ -356,7 +357,7 @@
.isUnsupported());
// One connection attempt per api call.
- ASSERT_EQ(12, mConnectCounter);
+ ASSERT_EQ(13, mConnectCounter);
}
TEST_F(VibratorHalControllerTest, TestScheduledCallbackSurvivesReconnection) {
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
new file mode 100644
index 0000000..d5520a1
--- /dev/null
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "VibratorManagerHalWrapperLegacyTest"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <utils/Log.h>
+
+#include <vibratorservice/VibratorManagerHalWrapper.h>
+
+using android::hardware::vibrator::CompositeEffect;
+using android::hardware::vibrator::CompositePrimitive;
+using android::hardware::vibrator::Effect;
+using android::hardware::vibrator::EffectStrength;
+
+using std::chrono::milliseconds;
+
+using namespace android;
+using namespace testing;
+
+// -------------------------------------------------------------------------------------------------
+
+class MockHalController : public vibrator::HalController {
+public:
+ MockHalController() = default;
+ virtual ~MockHalController() = default;
+
+ MOCK_METHOD(bool, init, (), (override));
+ MOCK_METHOD(vibrator::HalResult<void>, ping, (), (override));
+ MOCK_METHOD(void, tryReconnect, (), (override));
+};
+
+// -------------------------------------------------------------------------------------------------
+
+class VibratorManagerHalWrapperLegacyTest : public Test {
+public:
+ void SetUp() override {
+ mMockController = std::make_shared<StrictMock<MockHalController>>();
+ mWrapper = std::make_unique<vibrator::LegacyManagerHalWrapper>(mMockController);
+ ASSERT_NE(mWrapper, nullptr);
+ }
+
+protected:
+ std::shared_ptr<StrictMock<MockHalController>> mMockController = nullptr;
+ std::unique_ptr<vibrator::ManagerHalWrapper> mWrapper = nullptr;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestPing) {
+ EXPECT_CALL(*mMockController.get(), ping())
+ .Times(Exactly(2))
+ .WillOnce(Return(vibrator::HalResult<void>::failed("message")))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
+
+ ASSERT_TRUE(mWrapper->ping().isFailed());
+ ASSERT_TRUE(mWrapper->ping().isOk());
+}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestTryReconnect) {
+ EXPECT_CALL(*mMockController.get(), tryReconnect()).Times(Exactly(1));
+
+ mWrapper->tryReconnect();
+}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestGetVibratorIds) {
+ std::vector<int32_t> expectedIds;
+ expectedIds.push_back(0);
+
+ EXPECT_CALL(*mMockController.get(), init())
+ .Times(Exactly(2))
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
+
+ auto result = mWrapper->getVibratorIds();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(std::vector<int32_t>(), result.value());
+
+ result = mWrapper->getVibratorIds();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(expectedIds, result.value());
+}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestGetVibratorWithValidIdReturnsController) {
+ EXPECT_CALL(*mMockController.get(), init())
+ .Times(Exactly(2))
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
+
+ ASSERT_TRUE(mWrapper->getVibrator(0).isFailed());
+
+ auto result = mWrapper->getVibrator(0);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(mMockController.get(), result.value().get());
+}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestGetVibratorWithInvalidIdFails) {
+ ASSERT_TRUE(mWrapper->getVibrator(-1).isFailed());
+}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestSyncedOperationsUnsupported) {
+ std::vector<int32_t> vibratorIds;
+ vibratorIds.push_back(0);
+
+ ASSERT_TRUE(mWrapper->prepareSynced(vibratorIds).isUnsupported());
+ ASSERT_TRUE(mWrapper->triggerSynced([]() {}).isUnsupported());
+ ASSERT_TRUE(mWrapper->cancelSynced().isUnsupported());
+}