Introduce IVibratorManager.aidl
Introduce interface for vibrator manager HAL.
A default implementation is made available to the existing
android.hardware.vibrator-service.example, which now provides a top
level devault IVibrator and a top level IVibratorManager with a
different vibrator in it.
VTS tests were also introduced for the new manager, and existing tests
for IVibrator where changed to run in all top level and managed HAL
instances found on a device.
Bug: 166586119
Test: atest VtsHalVibratorTargetTest
atest VtsHalVibratorManagerTargetTest
Change-Id: Iec9175167e795bc03c4f3d873e2ac6682ed52512
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 7a9feb2..ff925d9 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -534,6 +534,13 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.vibrator</name>
+ <interface>
+ <name>IVibratorManager</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.vr</name>
<version>1.0</version>
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
index ed40d25..80f7727 100644
--- a/tests/extension/vibrator/aidl/default/Android.bp
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -19,7 +19,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.vibrator-ndk_platform",
- "android.hardware.tests.extension.vibrator-ndk_platform",
+ "android.hardware.vibrator-unstable-ndk_platform",
+ "android.hardware.tests.extension.vibrator-unstable-ndk_platform",
],
}
diff --git a/vibrator/aidl/TEST_MAPPING b/vibrator/aidl/TEST_MAPPING
index 5ae32e7..2414b84 100644
--- a/vibrator/aidl/TEST_MAPPING
+++ b/vibrator/aidl/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "VtsHalVibratorTargetTest"
+ },
+ {
+ "name": "VtsHalVibratorManagerTargetTest"
}
]
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
new file mode 100644
index 0000000..99cd448
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+interface IVibratorManager {
+ int getCapabilities();
+ int[] getVibratorIds();
+ android.hardware.vibrator.IVibrator getVibrator(in int vibratorId);
+ void prepareSynced(in int[] vibratorIds);
+ void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback);
+ void cancelSynced();
+ const int CAP_SYNC = 1;
+ const int CAP_PREPARE_ON = 2;
+ const int CAP_PREPARE_PERFORM = 4;
+ const int CAP_PREPARE_COMPOSE = 8;
+ const int CAP_MIXED_TRIGGER_ON = 16;
+ const int CAP_MIXED_TRIGGER_PERFORM = 32;
+ const int CAP_MIXED_TRIGGER_COMPOSE = 64;
+ const int CAP_TRIGGER_CALLBACK = 128;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl
new file mode 100644
index 0000000..eb5e9cc
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vibrator;
+
+import android.hardware.vibrator.IVibrator;
+import android.hardware.vibrator.IVibratorCallback;
+
+@VintfStability
+interface IVibratorManager {
+ /**
+ * Whether prepare/trigger synced are supported.
+ */
+ const int CAP_SYNC = 1 << 0;
+ /**
+ * Whether IVibrator 'on' can be used with 'prepareSynced' function.
+ */
+ const int CAP_PREPARE_ON = 1 << 1;
+ /**
+ * Whether IVibrator 'perform' can be used with 'prepareSynced' function.
+ */
+ const int CAP_PREPARE_PERFORM = 1 << 2;
+ /**
+ * Whether IVibrator 'compose' can be used with 'prepareSynced' function.
+ */
+ const int CAP_PREPARE_COMPOSE = 1 << 3;
+ /**
+ * Whether IVibrator 'on' can be triggered with other functions in sync with 'triggerSynced'.
+ */
+ const int CAP_MIXED_TRIGGER_ON = 1 << 4;
+ /**
+ * Whether IVibrator 'perform' can be triggered with other functions in sync with 'triggerSynced'.
+ */
+ const int CAP_MIXED_TRIGGER_PERFORM = 1 << 5;
+ /**
+ * Whether IVibrator 'compose' can be triggered with other functions in sync with 'triggerSynced'.
+ */
+ const int CAP_MIXED_TRIGGER_COMPOSE = 1 << 6;
+ /**
+ * Whether on w/ IVibratorCallback can be used w/ 'trigerSynced' function.
+ */
+ const int CAP_TRIGGER_CALLBACK = 1 << 7;
+
+ /**
+ * Determine capabilities of the vibrator manager HAL (CAP_* mask)
+ */
+ int getCapabilities();
+
+ /**
+ * List the id of available vibrators. This result should be static and not change.
+ */
+ int[] getVibratorIds();
+
+ /**
+ * Return an available vibrator identified with given id.
+ */
+ IVibrator getVibrator(in int vibratorId);
+
+ /**
+ * Start preparation for a synced vibration
+ *
+ * This function must only be called after the previous synced vibration was triggered or
+ * canceled (through cancelSynced()).
+ *
+ * Doing this operation while any of the specified vibrators is already on is undefined behavior.
+ * Clients should explicitly call off in each vibrator.
+ *
+ * @param vibratorIds ids of the vibrators to play vibrations in sync.
+ */
+ void prepareSynced(in int[] vibratorIds);
+
+ /**
+ * Trigger a prepared synced vibration
+ *
+ * Trigger a previously-started preparation for synced vibration, if any.
+ * A callback is only expected to be supported when getCapabilities CAP_TRIGGER_CALLBACK
+ * is specified.
+ *
+ * @param callback A callback used to inform Frameworks of state change, if supported.
+ */
+ void triggerSynced(in IVibratorCallback callback);
+
+ /**
+ * Cancel preparation of synced vibration
+ *
+ * Cancel a previously-started preparation for synced vibration, if any.
+ */
+ void cancelSynced();
+}
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 9e6d9cf..f9d45bb 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -4,10 +4,13 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.vibrator-ndk_platform",
+ "android.hardware.vibrator-unstable-ndk_platform",
],
export_include_dirs: ["include"],
- srcs: ["Vibrator.cpp"],
+ srcs: [
+ "Vibrator.cpp",
+ "VibratorManager.cpp",
+ ],
visibility: [
":__subpackages__",
"//hardware/interfaces/tests/extension/vibrator:__subpackages__",
@@ -23,7 +26,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.vibrator-ndk_platform",
+ "android.hardware.vibrator-unstable-ndk_platform",
],
static_libs: [
"libvibratorexampleimpl",
diff --git a/vibrator/aidl/default/VibratorManager.cpp b/vibrator/aidl/default/VibratorManager.cpp
new file mode 100644
index 0000000..7cf9e6a
--- /dev/null
+++ b/vibrator/aidl/default/VibratorManager.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include "vibrator-impl/VibratorManager.h"
+
+#include <android-base/logging.h>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+
+static constexpr int32_t kDefaultVibratorId = 1;
+
+ndk::ScopedAStatus VibratorManager::getCapabilities(int32_t* _aidl_return) {
+ LOG(INFO) << "Vibrator manager reporting capabilities";
+ *_aidl_return =
+ IVibratorManager::CAP_SYNC | IVibratorManager::CAP_PREPARE_ON |
+ IVibratorManager::CAP_PREPARE_PERFORM | IVibratorManager::CAP_PREPARE_COMPOSE |
+ IVibratorManager::CAP_MIXED_TRIGGER_ON | IVibratorManager::CAP_MIXED_TRIGGER_PERFORM |
+ IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE | IVibratorManager::CAP_TRIGGER_CALLBACK;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VibratorManager::getVibratorIds(std::vector<int32_t>* _aidl_return) {
+ LOG(INFO) << "Vibrator manager getting vibrator ids";
+ *_aidl_return = {kDefaultVibratorId};
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VibratorManager::getVibrator(int32_t vibratorId,
+ std::shared_ptr<IVibrator>* _aidl_return) {
+ LOG(INFO) << "Vibrator manager getting vibrator " << vibratorId;
+ if (vibratorId == kDefaultVibratorId) {
+ *_aidl_return = mDefaultVibrator;
+ return ndk::ScopedAStatus::ok();
+ } else {
+ *_aidl_return = nullptr;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+}
+
+ndk::ScopedAStatus VibratorManager::prepareSynced(const std::vector<int32_t>& vibratorIds) {
+ LOG(INFO) << "Vibrator Manager prepare synced";
+ if (vibratorIds.size() == 1 && vibratorIds[0] == kDefaultVibratorId) {
+ return ndk::ScopedAStatus::ok();
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+}
+
+ndk::ScopedAStatus VibratorManager::triggerSynced(
+ const std::shared_ptr<IVibratorCallback>& callback) {
+ LOG(INFO) << "Vibrator Manager trigger synced";
+ std::thread([=] {
+ if (callback != nullptr) {
+ LOG(INFO) << "Notifying perform complete";
+ callback->onComplete();
+ }
+ }).detach();
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VibratorManager::cancelSynced() {
+ LOG(INFO) << "Vibrator Manager cancel synced";
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace vibrator
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h
new file mode 100644
index 0000000..319eb05
--- /dev/null
+++ b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/vibrator/BnVibratorManager.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+
+class VibratorManager : public BnVibratorManager {
+ public:
+ VibratorManager(std::shared_ptr<IVibrator> vibrator) : mDefaultVibrator(std::move(vibrator)){};
+ ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus getVibratorIds(std::vector<int32_t>* _aidl_return) override;
+ ndk::ScopedAStatus getVibrator(int32_t vibratorId,
+ std::shared_ptr<IVibrator>* _aidl_return) override;
+ ndk::ScopedAStatus prepareSynced(const std::vector<int32_t>& vibratorIds) override;
+ ndk::ScopedAStatus triggerSynced(const std::shared_ptr<IVibratorCallback>& callback) override;
+ ndk::ScopedAStatus cancelSynced() override;
+
+ private:
+ std::shared_ptr<IVibrator> mDefaultVibrator;
+};
+
+} // namespace vibrator
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp
index ebb0905..bd834d2 100644
--- a/vibrator/aidl/default/main.cpp
+++ b/vibrator/aidl/default/main.cpp
@@ -15,19 +15,29 @@
*/
#include "vibrator-impl/Vibrator.h"
+#include "vibrator-impl/VibratorManager.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
using aidl::android::hardware::vibrator::Vibrator;
+using aidl::android::hardware::vibrator::VibratorManager;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
- std::shared_ptr<Vibrator> vib = ndk::SharedRefBase::make<Vibrator>();
- const std::string instance = std::string() + Vibrator::descriptor + "/default";
- binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str());
+ // make a default vibrator service
+ auto vib = ndk::SharedRefBase::make<Vibrator>();
+ const std::string vibName = std::string() + Vibrator::descriptor + "/default";
+ binder_status_t status = AServiceManager_addService(vib->asBinder().get(), vibName.c_str());
+ CHECK(status == STATUS_OK);
+
+ // make the vibrator manager service with a different vibrator
+ auto managedVib = ndk::SharedRefBase::make<Vibrator>();
+ auto vibManager = ndk::SharedRefBase::make<VibratorManager>(std::move(managedVib));
+ const std::string vibManagerName = std::string() + VibratorManager::descriptor + "/default";
+ status = AServiceManager_addService(vibManager->asBinder().get(), vibManagerName.c_str());
CHECK(status == STATUS_OK);
ABinderProcess_joinThreadPool();
diff --git a/vibrator/aidl/default/vibrator-default.xml b/vibrator/aidl/default/vibrator-default.xml
index 49b11ec..9f9cd40 100644
--- a/vibrator/aidl/default/vibrator-default.xml
+++ b/vibrator/aidl/default/vibrator-default.xml
@@ -3,4 +3,8 @@
<name>android.hardware.vibrator</name>
<fqname>IVibrator/default</fqname>
</hal>
+ <hal format="aidl">
+ <name>android.hardware.vibrator</name>
+ <fqname>IVibratorManager/default</fqname>
+ </hal>
</manifest>
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index 28cb4d9..d06b50e 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -9,7 +9,26 @@
"libbinder",
],
static_libs: [
- "android.hardware.vibrator-cpp",
+ "android.hardware.vibrator-unstable-cpp",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalVibratorManagerTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalVibratorManagerTargetTest.cpp"],
+ shared_libs: [
+ "libbinder",
+ ],
+ static_libs: [
+ "android.hardware.vibrator-unstable-cpp",
],
test_suites: [
"general-tests",
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
new file mode 100644
index 0000000..9789188
--- /dev/null
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <android/hardware/vibrator/BnVibratorCallback.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <android/hardware/vibrator/IVibratorManager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <cmath>
+#include <future>
+
+using android::ProcessState;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::vibrator::BnVibratorCallback;
+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::IVibratorManager;
+using std::chrono::high_resolution_clock;
+
+const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
+ android::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
+ android::enum_range<EffectStrength>().end()};
+const std::vector<CompositePrimitive> kPrimitives{android::enum_range<CompositePrimitive>().begin(),
+ android::enum_range<CompositePrimitive>().end()};
+
+class CompletionCallback : public BnVibratorCallback {
+ public:
+ CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
+ Status onComplete() override {
+ mCallback();
+ return Status::ok();
+ }
+
+ private:
+ std::function<void()> mCallback;
+};
+
+class VibratorAidl : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ manager = android::waitForDeclaredService<IVibratorManager>(String16(GetParam().c_str()));
+ ASSERT_NE(manager, nullptr);
+ ASSERT_TRUE(manager->getCapabilities(&capabilities).isOk());
+ EXPECT_TRUE(manager->getVibratorIds(&vibratorIds).isOk());
+ }
+
+ sp<IVibratorManager> manager;
+ int32_t capabilities;
+ std::vector<int32_t> vibratorIds;
+};
+
+TEST_P(VibratorAidl, ValidateExistingVibrators) {
+ sp<IVibrator> vibrator;
+ for (auto& id : vibratorIds) {
+ EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ ASSERT_NE(vibrator, nullptr);
+ }
+}
+
+TEST_P(VibratorAidl, GetVibratorWithInvalidId) {
+ int32_t invalidId = *max_element(vibratorIds.begin(), vibratorIds.end()) + 1;
+ sp<IVibrator> vibrator;
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ manager->getVibrator(invalidId, &vibrator).exceptionCode());
+ ASSERT_EQ(vibrator, nullptr);
+}
+
+TEST_P(VibratorAidl, ValidatePrepareSyncedExistingVibrators) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (vibratorIds.empty()) return;
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+}
+
+TEST_P(VibratorAidl, PrepareSyncedEmptySetIsInvalid) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ std::vector<int32_t> emptyIds;
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, manager->prepareSynced(emptyIds).exceptionCode());
+}
+
+TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) {
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
+ manager->prepareSynced(vibratorIds).exceptionCode());
+ }
+}
+
+TEST_P(VibratorAidl, PrepareOnNotSupported) {
+ if (vibratorIds.empty()) return;
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
+ uint32_t durationMs = 250;
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+ sp<IVibrator> vibrator;
+ for (auto& id : vibratorIds) {
+ EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ ASSERT_NE(vibrator, nullptr);
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
+ vibrator->on(durationMs, nullptr).exceptionCode());
+ }
+ EXPECT_TRUE(manager->cancelSynced().isOk());
+ }
+}
+
+TEST_P(VibratorAidl, PreparePerformNotSupported) {
+ if (vibratorIds.empty()) return;
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+ sp<IVibrator> vibrator;
+ for (auto& id : vibratorIds) {
+ EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ ASSERT_NE(vibrator, nullptr);
+ int32_t lengthMs = 0;
+ Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ }
+ EXPECT_TRUE(manager->cancelSynced().isOk());
+ }
+}
+
+TEST_P(VibratorAidl, PrepareComposeNotSupported) {
+ if (vibratorIds.empty()) return;
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
+ std::vector<CompositeEffect> composite;
+ CompositeEffect effect;
+ effect.delayMs = 10;
+ effect.primitive = kPrimitives[0];
+ effect.scale = 1.0f;
+ composite.emplace_back(effect);
+
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+ sp<IVibrator> vibrator;
+ for (auto& id : vibratorIds) {
+ EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ ASSERT_NE(vibrator, nullptr);
+ Status status = vibrator->compose(composite, nullptr);
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ }
+ EXPECT_TRUE(manager->cancelSynced().isOk());
+ }
+}
+
+TEST_P(VibratorAidl, TriggerWithCallback) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) return;
+ if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) return;
+ if (vibratorIds.empty()) return;
+
+ std::promise<void> completionPromise;
+ std::future<void> completionFuture{completionPromise.get_future()};
+ sp<CompletionCallback> callback =
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ uint32_t durationMs = 250;
+ std::chrono::milliseconds timeout{durationMs * 2};
+
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+ sp<IVibrator> vibrator;
+ for (auto& id : vibratorIds) {
+ EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+ ASSERT_NE(vibrator, nullptr);
+ EXPECT_TRUE(vibrator->on(durationMs, nullptr).isOk());
+ }
+
+ EXPECT_TRUE(manager->triggerSynced(callback).isOk());
+ EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
+ EXPECT_TRUE(manager->cancelSynced().isOk());
+}
+
+TEST_P(VibratorAidl, TriggerSyncNotSupported) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) {
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
+ manager->triggerSynced(nullptr).exceptionCode());
+ }
+}
+
+TEST_P(VibratorAidl, TriggerCallbackNotSupported) {
+ if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
+ if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
+ sp<CompletionCallback> callback = new CompletionCallback([] {});
+ EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
+ manager->triggerSynced(callback).exceptionCode());
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
+INSTANTIATE_TEST_SUITE_P(
+ Vibrator, VibratorAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IVibratorManager::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 888a403..dfd2524 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -18,6 +18,7 @@
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
+#include <android/hardware/vibrator/IVibratorManager.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
@@ -34,6 +35,7 @@
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::IVibrator;
+using android::hardware::vibrator::IVibratorManager;
using std::chrono::high_resolution_clock;
const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
@@ -77,10 +79,28 @@
std::function<void()> mCallback;
};
-class VibratorAidl : public testing::TestWithParam<std::string> {
+class VibratorAidl : public testing::TestWithParam<std::tuple<int32_t, int32_t>> {
public:
virtual void SetUp() override {
- vibrator = android::waitForDeclaredService<IVibrator>(String16(GetParam().c_str()));
+ int32_t managerIdx = std::get<0>(GetParam());
+ int32_t vibratorId = std::get<1>(GetParam());
+ auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
+
+ if (managerIdx < 0) {
+ // Testing a unmanaged vibrator, using vibratorId as index from registered HALs
+ auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
+ ASSERT_LT(vibratorId, vibratorAidlNames.size());
+ auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str());
+ vibrator = android::waitForDeclaredService<IVibrator>(vibratorName);
+ } else {
+ // Testing a managed vibrator, using vibratorId to retrieve it from the manager
+ ASSERT_LT(managerIdx, managerAidlNames.size());
+ auto managerName = String16(managerAidlNames[managerIdx].c_str());
+ auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
+ auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator);
+ ASSERT_TRUE(vibratorResult.isOk());
+ }
+
ASSERT_NE(vibrator, nullptr);
ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
}
@@ -518,10 +538,41 @@
}
}
+std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
+ std::vector<std::tuple<int32_t, int32_t>> tuples;
+ auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
+ std::vector<int32_t> vibratorIds;
+
+ for (int i = 0; i < managerAidlNames.size(); i++) {
+ auto managerName = String16(managerAidlNames[i].c_str());
+ auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
+ if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
+ for (auto& vibratorId : vibratorIds) {
+ tuples.push_back(std::make_tuple(i, vibratorId));
+ }
+ }
+ }
+
+ auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
+ for (int i = 0; i < vibratorAidlNames.size(); i++) {
+ tuples.push_back(std::make_tuple(-1, i));
+ }
+
+ return tuples;
+}
+
+std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType>& info) {
+ const auto& [managerIdx, vibratorId] = info.param;
+ if (managerIdx < 0) {
+ return std::string("TOP_LEVEL_VIBRATOR_") + std::to_string(vibratorId);
+ }
+ return std::string("MANAGER_") + std::to_string(managerIdx) + "_VIBRATOR_ID_" +
+ std::to_string(vibratorId);
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
-INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl,
- testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)),
- android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()),
+ PrintGeneratedTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);