Merge "Introduce IVibratorManager.aidl"
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);