Merge "Add wrapper for IVibratorManager.aidl to native vibrator service"
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index fa742c5..75228d6 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -35,7 +35,7 @@
"libhidlbase",
"liblog",
"libutils",
- "android.hardware.vibrator-cpp",
+ "android.hardware.vibrator-unstable-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 9672644..7fee82f 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "VibratorHalWrapper"
#include <android/hardware/vibrator/1.3/IVibrator.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <hardware/vibrator.h>
@@ -73,17 +72,6 @@
"android::hardware::vibrator::V1_0::Status = ";
template <typename T>
-HalResult<T> HalResult<T>::fromStatus(binder::Status status, T data) {
- if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
- return HalResult<T>::unsupported();
- }
- if (status.isOk()) {
- return HalResult<T>::ok(data);
- }
- return HalResult<T>::failed(std::string(status.toString8().c_str()));
-}
-
-template <typename T>
HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) {
switch (status) {
case V1_0::Status::OK:
@@ -145,28 +133,16 @@
// -------------------------------------------------------------------------------------------------
-class HalCallbackWrapper : public Aidl::BnVibratorCallback {
-public:
- HalCallbackWrapper(std::function<void()> completionCallback)
- : mCompletionCallback(completionCallback) {}
-
- binder::Status onComplete() override {
- mCompletionCallback();
- return binder::Status::ok();
- }
-
-private:
- const std::function<void()> mCompletionCallback;
-};
-
-// -------------------------------------------------------------------------------------------------
-
HalResult<void> AidlHalWrapper::ping() {
return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder());
}
void AidlHalWrapper::tryReconnect() {
- sp<Aidl::IVibrator> newHandle = checkVintfService<Aidl::IVibrator>();
+ auto result = mReconnectFn();
+ if (!result.isOk()) {
+ return;
+ }
+ sp<Aidl::IVibrator> newHandle = result.value();
if (newHandle) {
std::lock_guard<std::mutex> lock(mHandleMutex);
mHandle = std::move(newHandle);
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp
index 71955af..9c4166c 100644
--- a/services/vibratorservice/VibratorManagerHalWrapper.cpp
+++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp
@@ -20,11 +20,14 @@
#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() {
return mController->ping();
@@ -34,6 +37,10 @@
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));
@@ -47,7 +54,7 @@
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 = " +
+ return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX +
std::to_string(id));
}
@@ -63,6 +70,135 @@
return HalResult<void>::unsupported();
}
+// -------------------------------------------------------------------------------------------------
+
+std::shared_ptr<HalWrapper> AidlManagerHalWrapper::ManagedHalConnector::connect(
+ std::shared_ptr<CallbackScheduler> callbackScheduler) {
+ std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [&]() {
+ sp<Aidl::IVibrator> vibrator;
+ auto result = this->mManager->getHal()->getVibrator(this->mVibratorId, &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) {
+ auto connector = std::make_unique<ManagedHalConnector>(this, id);
+ auto controller =
+ std::make_unique<HalController>(std::move(connector), mCallbackScheduler);
+ 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
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index c1a03a1..d3130f4 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -23,7 +23,7 @@
"liblog",
"libutils",
"libvibratorservice",
- "android.hardware.vibrator-cpp",
+ "android.hardware.vibrator-unstable-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index bcb735d..638b483 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -19,6 +19,7 @@
#include <android-base/thread_annotations.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <binder/IServiceManager.h>
@@ -40,7 +41,15 @@
}
static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
- static HalResult<T> fromStatus(binder::Status status, T data);
+ static HalResult<T> fromStatus(binder::Status status, T data) {
+ if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
+ return HalResult<T>::unsupported();
+ }
+ if (status.isOk()) {
+ return HalResult<T>::ok(data);
+ }
+ return HalResult<T>::failed(std::string(status.toString8().c_str()));
+ }
static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data);
template <typename R>
@@ -99,6 +108,20 @@
: mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
};
+class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback {
+public:
+ HalCallbackWrapper(std::function<void()> completionCallback)
+ : mCompletionCallback(completionCallback) {}
+
+ binder::Status onComplete() override {
+ mCompletionCallback();
+ return binder::Status::ok();
+ }
+
+private:
+ const std::function<void()> mCompletionCallback;
+};
+
// -------------------------------------------------------------------------------------------------
// Vibrator HAL capabilities.
@@ -178,9 +201,16 @@
// Wrapper for the AIDL Vibrator HAL.
class AidlHalWrapper : public HalWrapper {
public:
- AidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler,
- sp<hardware::vibrator::IVibrator> handle)
- : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
+ AidlHalWrapper(
+ std::shared_ptr<CallbackScheduler> scheduler, sp<hardware::vibrator::IVibrator> handle,
+ std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> reconnectFn =
+ []() {
+ return HalResult<sp<hardware::vibrator::IVibrator>>::ok(
+ checkVintfService<hardware::vibrator::IVibrator>());
+ })
+ : HalWrapper(std::move(scheduler)),
+ mReconnectFn(reconnectFn),
+ mHandle(std::move(handle)) {}
virtual ~AidlHalWrapper() = default;
HalResult<void> ping() override final;
@@ -211,6 +241,7 @@
const std::function<void()>& completionCallback) override final;
private:
+ const std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> mReconnectFn;
std::mutex mHandleMutex;
std::mutex mCapabilitiesMutex;
std::mutex mSupportedEffectsMutex;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
index 99947a5..309d681 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
@@ -17,12 +17,47 @@
#ifndef ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H
#define ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H
+#include <android/hardware/vibrator/IVibratorManager.h>
#include <vibratorservice/VibratorHalController.h>
+#include <unordered_map>
namespace android {
namespace vibrator {
+// VibratorManager HAL capabilities.
+enum class ManagerCapabilities : int32_t {
+ NONE = 0,
+ SYNC = hardware::vibrator::IVibratorManager::CAP_SYNC,
+ PREPARE_ON = hardware::vibrator::IVibratorManager::CAP_PREPARE_ON,
+ PREPARE_PERFORM = hardware::vibrator::IVibratorManager::CAP_PREPARE_PERFORM,
+ PREPARE_COMPOSE = hardware::vibrator::IVibratorManager::CAP_PREPARE_COMPOSE,
+ MIXED_TRIGGER_ON = hardware::vibrator::IVibratorManager::IVibratorManager::CAP_MIXED_TRIGGER_ON,
+ MIXED_TRIGGER_PERFORM = hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_PERFORM,
+ MIXED_TRIGGER_COMPOSE = hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE,
+ TRIGGER_CALLBACK = hardware::vibrator::IVibratorManager::CAP_TRIGGER_CALLBACK
+};
+
+inline ManagerCapabilities operator|(ManagerCapabilities lhs, ManagerCapabilities rhs) {
+ using underlying = typename std::underlying_type<ManagerCapabilities>::type;
+ return static_cast<ManagerCapabilities>(static_cast<underlying>(lhs) |
+ static_cast<underlying>(rhs));
+}
+
+inline ManagerCapabilities& operator|=(ManagerCapabilities& lhs, ManagerCapabilities rhs) {
+ return lhs = lhs | rhs;
+}
+
+inline ManagerCapabilities operator&(ManagerCapabilities lhs, ManagerCapabilities rhs) {
+ using underlying = typename std::underlying_type<ManagerCapabilities>::type;
+ return static_cast<ManagerCapabilities>(static_cast<underlying>(lhs) &
+ static_cast<underlying>(rhs));
+}
+
+inline ManagerCapabilities& operator&=(ManagerCapabilities& lhs, ManagerCapabilities rhs) {
+ return lhs = lhs & rhs;
+}
+
// Wrapper for VibratorManager HAL handlers.
class ManagerHalWrapper {
public:
@@ -36,6 +71,7 @@
*/
virtual void tryReconnect() = 0;
+ virtual HalResult<ManagerCapabilities> getCapabilities() = 0;
virtual HalResult<std::vector<int32_t>> getVibratorIds() = 0;
virtual HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) = 0;
@@ -55,6 +91,7 @@
HalResult<void> ping() override final;
void tryReconnect() override final;
+ HalResult<ManagerCapabilities> getCapabilities() override final;
HalResult<std::vector<int32_t>> getVibratorIds() override final;
HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) override final;
@@ -66,6 +103,53 @@
const std::shared_ptr<HalController> mController;
};
+// Wrapper for the AIDL VibratorManager HAL.
+class AidlManagerHalWrapper : public ManagerHalWrapper {
+public:
+ explicit AidlManagerHalWrapper(std::shared_ptr<CallbackScheduler> callbackScheduler,
+ sp<hardware::vibrator::IVibratorManager> handle)
+ : mHandle(std::move(handle)), mCallbackScheduler(callbackScheduler) {}
+ virtual ~AidlManagerHalWrapper() = default;
+
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
+
+ HalResult<ManagerCapabilities> getCapabilities() 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:
+ std::mutex mHandleMutex;
+ std::mutex mCapabilitiesMutex;
+ std::mutex mVibratorsMutex;
+ sp<hardware::vibrator::IVibratorManager> mHandle GUARDED_BY(mHandleMutex);
+ std::optional<ManagerCapabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
+ std::optional<std::vector<int32_t>> mVibratorIds GUARDED_BY(mVibratorsMutex);
+ std::unordered_map<int32_t, std::shared_ptr<HalController>> mVibrators
+ GUARDED_BY(mVibratorsMutex);
+ std::shared_ptr<CallbackScheduler> mCallbackScheduler;
+
+ sp<hardware::vibrator::IVibratorManager> getHal();
+
+ // Connector that creates a HalWrapper from an IVibrator loaded from IVibratorManager.
+ class ManagedHalConnector : public HalConnector {
+ public:
+ ManagedHalConnector(AidlManagerHalWrapper* manager, int32_t vibratorId)
+ : mManager(manager), mVibratorId(vibratorId) {}
+ ~ManagedHalConnector() = default;
+
+ std::shared_ptr<HalWrapper> connect(std::shared_ptr<CallbackScheduler>) override final;
+
+ private:
+ AidlManagerHalWrapper* mManager;
+ const int32_t mVibratorId;
+ };
+};
+
}; // namespace vibrator
}; // namespace android
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 5fc6d45..6801f76 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",
+ "VibratorManagerHalWrapperAidlTest.cpp",
"VibratorManagerHalWrapperLegacyTest.cpp",
],
cflags: [
@@ -37,7 +38,7 @@
"liblog",
"libvibratorservice",
"libutils",
- "android.hardware.vibrator-cpp",
+ "android.hardware.vibrator-unstable-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
new file mode 100644
index 0000000..dd71a6a
--- /dev/null
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
@@ -0,0 +1,358 @@
+/*
+ * 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 "VibratorManagerHalWrapperAidlTest"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <utils/Log.h>
+
+#include <vibratorservice/VibratorManagerHalWrapper.h>
+
+#include "test_utils.h"
+
+using android::binder::Status;
+
+using android::hardware::vibrator::CompositeEffect;
+using android::hardware::vibrator::CompositePrimitive;
+using android::hardware::vibrator::Effect;
+using android::hardware::vibrator::EffectStrength;
+using android::hardware::vibrator::IVibrator;
+using android::hardware::vibrator::IVibratorCallback;
+using android::hardware::vibrator::IVibratorManager;
+
+using namespace android;
+using namespace testing;
+
+class MockBinder : public BBinder {
+public:
+ MOCK_METHOD(status_t, linkToDeath,
+ (const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags), (override));
+ MOCK_METHOD(status_t, unlinkToDeath,
+ (const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
+ wp<DeathRecipient>* outRecipient),
+ (override));
+ MOCK_METHOD(status_t, pingBinder, (), (override));
+};
+
+class MockIVibrator : public IVibrator {
+public:
+ MOCK_METHOD(Status, getCapabilities, (int32_t * ret), (override));
+ MOCK_METHOD(Status, off, (), (override));
+ MOCK_METHOD(Status, on, (int32_t timeout, const sp<IVibratorCallback>& cb), (override));
+ MOCK_METHOD(Status, perform,
+ (Effect e, EffectStrength s, const sp<IVibratorCallback>& cb, int32_t* ret),
+ (override));
+ MOCK_METHOD(Status, getSupportedEffects, (std::vector<Effect> * ret), (override));
+ MOCK_METHOD(Status, setAmplitude, (float amplitude), (override));
+ MOCK_METHOD(Status, setExternalControl, (bool enabled), (override));
+ MOCK_METHOD(Status, getCompositionDelayMax, (int32_t * ret), (override));
+ MOCK_METHOD(Status, getCompositionSizeMax, (int32_t * ret), (override));
+ MOCK_METHOD(Status, getSupportedPrimitives, (std::vector<CompositePrimitive> * ret),
+ (override));
+ MOCK_METHOD(Status, getPrimitiveDuration, (CompositePrimitive p, int32_t* ret), (override));
+ MOCK_METHOD(Status, compose,
+ (const std::vector<CompositeEffect>& e, const sp<IVibratorCallback>& cb),
+ (override));
+ MOCK_METHOD(Status, getSupportedAlwaysOnEffects, (std::vector<Effect> * ret), (override));
+ MOCK_METHOD(Status, alwaysOnEnable, (int32_t id, Effect e, EffectStrength s), (override));
+ MOCK_METHOD(Status, alwaysOnDisable, (int32_t id), (override));
+ MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
+ MOCK_METHOD(std::string, getInterfaceHash, (), (override));
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+class MockIVibratorManager : public IVibratorManager {
+public:
+ MOCK_METHOD(Status, getCapabilities, (int32_t * ret), (override));
+ MOCK_METHOD(Status, getVibratorIds, (std::vector<int32_t> * ret), (override));
+ MOCK_METHOD(Status, getVibrator, (int32_t id, sp<IVibrator>* ret), (override));
+ MOCK_METHOD(Status, prepareSynced, (const std::vector<int32_t>& ids), (override));
+ MOCK_METHOD(Status, triggerSynced, (const sp<IVibratorCallback>& cb), (override));
+ MOCK_METHOD(Status, cancelSynced, (), (override));
+ MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
+ MOCK_METHOD(std::string, getInterfaceHash, (), (override));
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+// -------------------------------------------------------------------------------------------------
+
+class VibratorManagerHalWrapperAidlTest : public Test {
+public:
+ void SetUp() override {
+ mMockBinder = new StrictMock<MockBinder>();
+ mMockVibrator = new StrictMock<MockIVibrator>();
+ mMockHal = new StrictMock<MockIVibratorManager>();
+ mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>();
+ mWrapper = std::make_unique<vibrator::AidlManagerHalWrapper>(mMockScheduler, mMockHal);
+ ASSERT_NE(mWrapper, nullptr);
+ }
+
+protected:
+ std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr;
+ std::unique_ptr<vibrator::ManagerHalWrapper> mWrapper = nullptr;
+ sp<StrictMock<MockIVibratorManager>> mMockHal = nullptr;
+ sp<StrictMock<MockIVibrator>> mMockVibrator = nullptr;
+ sp<StrictMock<MockBinder>> mMockBinder = nullptr;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+static const std::vector<int32_t> kVibratorIds = {1, 2};
+static constexpr int kVibratorId = 1;
+
+ACTION(TriggerCallback) {
+ if (arg0 != nullptr) {
+ arg0->onComplete();
+ }
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestPing) {
+ EXPECT_CALL(*mMockHal.get(), onAsBinder())
+ .Times(Exactly(2))
+ .WillRepeatedly(Return(mMockBinder.get()));
+ EXPECT_CALL(*mMockBinder.get(), pingBinder())
+ .Times(Exactly(2))
+ .WillOnce(Return(android::OK))
+ .WillRepeatedly(Return(android::DEAD_OBJECT));
+
+ ASSERT_TRUE(mWrapper->ping().isOk());
+ ASSERT_TRUE(mWrapper->ping().isFailed());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesDoesNotCacheFailedResult) {
+ EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
+ .Times(Exactly(3))
+ .WillOnce(
+ Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status())));
+
+ ASSERT_TRUE(mWrapper->getCapabilities().isUnsupported());
+ ASSERT_TRUE(mWrapper->getCapabilities().isFailed());
+
+ auto result = mWrapper->getCapabilities();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(vibrator::ManagerCapabilities::SYNC, result.value());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesCachesResult) {
+ EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status())));
+
+ std::vector<std::thread> threads;
+ for (int i = 0; i < 10; i++) {
+ threads.push_back(std::thread([&]() {
+ auto result = mWrapper->getCapabilities();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(vibrator::ManagerCapabilities::SYNC, result.value());
+ }));
+ }
+ std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
+
+ auto result = mWrapper->getCapabilities();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(vibrator::ManagerCapabilities::SYNC, result.value());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorIdsDoesNotCacheFailedResult) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(3))
+ .WillOnce(
+ Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ ASSERT_TRUE(mWrapper->getVibratorIds().isUnsupported());
+ ASSERT_TRUE(mWrapper->getVibratorIds().isFailed());
+
+ auto result = mWrapper->getVibratorIds();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(kVibratorIds, result.value());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorIdsCachesResult) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ std::vector<std::thread> threads;
+ for (int i = 0; i < 10; i++) {
+ threads.push_back(std::thread([&]() {
+ auto result = mWrapper->getVibratorIds();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(kVibratorIds, result.value());
+ }));
+ }
+ std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
+
+ auto result = mWrapper->getVibratorIds();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(kVibratorIds, result.value());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithValidIdReturnsController) {
+ {
+ InSequence seq;
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status())));
+ }
+
+ auto result = mWrapper->getVibrator(kVibratorId);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_NE(nullptr, result.value().get());
+ ASSERT_TRUE(result.value().get()->init());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithInvalidIdFails) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ ASSERT_TRUE(mWrapper->getVibrator(0).isFailed());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorRecoversVibratorPointer) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _))
+ .Times(Exactly(3))
+ .WillOnce(DoAll(SetArgPointee<1>(nullptr),
+ Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status())));
+
+ EXPECT_CALL(*mMockVibrator.get(), getCapabilities(_))
+ .Times(Exactly(3))
+ .WillOnce(
+ Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status())));
+
+ // Get vibrator controller is successful even if first getVibrator.
+ auto result = mWrapper->getVibrator(kVibratorId);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_NE(nullptr, result.value().get());
+
+ auto vibrator = result.value();
+ // First getVibrator call fails.
+ ASSERT_FALSE(vibrator->init());
+ // First and second getCapabilities calls fail, reload IVibrator with getVibrator.
+ ASSERT_FALSE(vibrator->getCapabilities().isOk());
+ // Third call to getCapabilities worked after IVibrator reloaded.
+ ASSERT_TRUE(vibrator->getCapabilities().isOk());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestPrepareSynced) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), getVibrator(_, _))
+ .Times(Exactly(2))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), prepareSynced(Eq(kVibratorIds)))
+ .Times(Exactly(3))
+ .WillOnce(
+ Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(Return(Status()));
+
+ ASSERT_TRUE(mWrapper->getVibratorIds().isOk());
+ ASSERT_TRUE(mWrapper->prepareSynced(kVibratorIds).isUnsupported());
+ ASSERT_TRUE(mWrapper->prepareSynced(kVibratorIds).isFailed());
+ ASSERT_TRUE(mWrapper->prepareSynced(kVibratorIds).isOk());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestTriggerSyncedWithCallbackSupport) {
+ {
+ InSequence seq;
+ EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_TRIGGER_CALLBACK),
+ Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), triggerSynced(_))
+ .Times(Exactly(3))
+ .WillOnce(Return(
+ Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(TriggerCallback(), Return(Status())));
+ }
+
+ std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+ auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+ ASSERT_TRUE(mWrapper->triggerSynced(callback).isUnsupported());
+ ASSERT_TRUE(mWrapper->triggerSynced(callback).isFailed());
+ ASSERT_TRUE(mWrapper->triggerSynced(callback).isOk());
+ ASSERT_EQ(1, *callbackCounter.get());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestTriggerSyncedWithoutCallbackSupport) {
+ {
+ InSequence seq;
+ EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), triggerSynced(Eq(nullptr)))
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(Status()));
+ }
+
+ std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+ auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+ ASSERT_TRUE(mWrapper->triggerSynced(callback).isOk());
+ ASSERT_EQ(0, *callbackCounter.get());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSynced) {
+ EXPECT_CALL(*mMockHal.get(), cancelSynced())
+ .Times(Exactly(3))
+ .WillOnce(
+ Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(Return(Status()));
+
+ ASSERT_TRUE(mWrapper->cancelSynced().isUnsupported());
+ ASSERT_TRUE(mWrapper->cancelSynced().isFailed());
+ ASSERT_TRUE(mWrapper->cancelSynced().isOk());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSyncedReloadsAllControllers) {
+ EXPECT_CALL(*mMockHal.get(), getVibratorIds(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), getVibrator(_, _))
+ .Times(Exactly(2))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status())));
+
+ EXPECT_CALL(*mMockHal.get(), cancelSynced()).Times(Exactly(1)).WillRepeatedly(Return(Status()));
+
+ ASSERT_TRUE(mWrapper->getVibratorIds().isOk());
+ ASSERT_TRUE(mWrapper->cancelSynced().isOk());
+}
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
index d5520a1..6c2aabb 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
@@ -78,6 +78,12 @@
mWrapper->tryReconnect();
}
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestGetCapabilities) {
+ auto result = mWrapper->getCapabilities();
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(vibrator::ManagerCapabilities::NONE, result.value());
+}
+
TEST_F(VibratorManagerHalWrapperLegacyTest, TestGetVibratorIds) {
std::vector<int32_t> expectedIds;
expectedIds.push_back(0);