diff options
-rw-r--r-- | compatibility_matrices/compatibility_matrix.current.xml | 7 | ||||
-rw-r--r-- | tests/extension/vibrator/aidl/default/Android.bp | 4 | ||||
-rw-r--r-- | vibrator/aidl/TEST_MAPPING | 3 | ||||
-rw-r--r-- | vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl | 35 | ||||
-rw-r--r-- | vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl | 102 | ||||
-rw-r--r-- | vibrator/aidl/default/Android.bp | 9 | ||||
-rw-r--r-- | vibrator/aidl/default/VibratorManager.cpp | 87 | ||||
-rw-r--r-- | vibrator/aidl/default/include/vibrator-impl/VibratorManager.h | 44 | ||||
-rw-r--r-- | vibrator/aidl/default/main.cpp | 16 | ||||
-rw-r--r-- | vibrator/aidl/default/vibrator-default.xml | 4 | ||||
-rw-r--r-- | vibrator/aidl/vts/Android.bp | 21 | ||||
-rw-r--r-- | vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp | 220 | ||||
-rw-r--r-- | vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp | 61 |
13 files changed, 599 insertions, 14 deletions
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 7a9feb2eab..ff925d90f1 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 ed40d259ab..80f7727646 100644 --- a/tests/extension/vibrator/aidl/default/Android.bp +++ b/tests/extension/vibrator/aidl/default/Android.bp @@ -19,7 +19,7 @@ cc_binary { 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 5ae32e744c..2414b8464f 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 0000000000..99cd448f41 --- /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 0000000000..eb5e9ccd3f --- /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 9e6d9cf2d9..f9d45bb001 100644 --- a/vibrator/aidl/default/Android.bp +++ b/vibrator/aidl/default/Android.bp @@ -4,10 +4,13 @@ cc_library_static { 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 @@ cc_binary { 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 0000000000..7cf9e6a5d8 --- /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 0000000000..319eb05c1f --- /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 ebb0905a3a..bd834d2a21 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 49b11ec8da..9f9cd40c4e 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 28cb4d9856..d06b50efe3 100644 --- a/vibrator/aidl/vts/Android.bp +++ b/vibrator/aidl/vts/Android.bp @@ -9,7 +9,26 @@ cc_test { "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 0000000000..9789188858 --- /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 888a4031bf..dfd2524114 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::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(), @@ -77,10 +79,28 @@ class CompletionCallback : public BnVibratorCallback { 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 @@ TEST_P(VibratorAidl, AlwaysOn) { } } +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); |