diff --git a/uwb/aidl/default/uwb_chip.cpp b/uwb/aidl/default/uwb_chip.cpp index 727bcf133a..fe64fa7125 100644 --- a/uwb/aidl/default/uwb_chip.cpp +++ b/uwb/aidl/default/uwb_chip.cpp @@ -16,13 +16,17 @@ #include "uwb.h" +namespace { +constexpr static int kVendorUciVersion = 1; +} + namespace android { namespace hardware { namespace uwb { namespace impl { using namespace ::aidl::android::hardware::uwb; -UwbChip::UwbChip(const std::string& name) : name_(name) {} +UwbChip::UwbChip(const std::string& name) : name_(name), mClientCallback(nullptr) {} UwbChip::~UwbChip() {} ::ndk::ScopedAStatus UwbChip::getName(std::string* name) { @@ -30,25 +34,30 @@ UwbChip::~UwbChip() {} return ndk::ScopedAStatus::ok(); } -::ndk::ScopedAStatus UwbChip::open( - const std::shared_ptr& /* clientCallback */) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +::ndk::ScopedAStatus UwbChip::open(const std::shared_ptr& clientCallback) { + mClientCallback = clientCallback; + mClientCallback->onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK); + return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus UwbChip::close() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + mClientCallback->onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK); + mClientCallback = nullptr; + return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus UwbChip::coreInit() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::ok(); } -::ndk::ScopedAStatus UwbChip::getSupportedVendorUciVersion(int32_t* /* version */) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +::ndk::ScopedAStatus UwbChip::getSupportedVendorUciVersion(int32_t* version) { + *version = kVendorUciVersion; + return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus UwbChip::sendUciMessage(const std::vector& /* data */, int32_t* /* bytes_written */) { + // TODO(b/195992658): Need emulator support for UCI stack. return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } } // namespace impl diff --git a/uwb/aidl/default/uwb_chip.h b/uwb/aidl/default/uwb_chip.h index 5d3f55cff8..ef1d5b634e 100644 --- a/uwb/aidl/default/uwb_chip.h +++ b/uwb/aidl/default/uwb_chip.h @@ -43,6 +43,7 @@ class UwbChip : public BnUwbChip { private: std::string name_; + std::shared_ptr mClientCallback; }; } // namespace impl } // namespace uwb diff --git a/uwb/aidl/vts/Android.bp b/uwb/aidl/vts/Android.bp new file mode 100644 index 0000000000..4d9f65307b --- /dev/null +++ b/uwb/aidl/vts/Android.bp @@ -0,0 +1,28 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalUwbTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalUwbTargetTest.cpp"], + shared_libs: [ + "libbinder", + "libbinder_ndk", + ], + static_libs: [ + "android.hardware.uwb-V1-ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/uwb/aidl/vts/OWNERS b/uwb/aidl/vts/OWNERS new file mode 100644 index 0000000000..c4ad4164e1 --- /dev/null +++ b/uwb/aidl/vts/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 1042770 +include platform/packages/modules/Uwb:/OWNERS diff --git a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp new file mode 100644 index 0000000000..9ac2678d3f --- /dev/null +++ b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2021 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 std::shared_ptrecific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using aidl::android::hardware::uwb::BnUwbClientCallback; +using aidl::android::hardware::uwb::IUwb; +using aidl::android::hardware::uwb::IUwbChip; +using aidl::android::hardware::uwb::IUwbClientCallback; +using aidl::android::hardware::uwb::UwbEvent; +using aidl::android::hardware::uwb::UwbStatus; +using android::ProcessState; +using android::String16; +using ndk::ScopedAStatus; +using ndk::SpAIBinder; + +namespace { +constexpr static int kCallbackTimeoutMs = 250; +} // namespace + +class UwbClientCallback : public BnUwbClientCallback { + public: + UwbClientCallback(const std::function&)>& on_uci_message_cb, + const std::function& on_hal_event_cb) + : on_uci_message_cb_(on_uci_message_cb), on_hal_event_cb_(on_hal_event_cb) {} + + ScopedAStatus onUciMessage(const std::vector& data) override { + on_uci_message_cb_(data); + return ScopedAStatus::ok(); + } + + ScopedAStatus onHalEvent(UwbEvent uwb_event, UwbStatus uwb_status) override { + on_hal_event_cb_(uwb_event, uwb_status); + return ScopedAStatus::ok(); + } + + private: + std::function&)> on_uci_message_cb_; + std::function on_hal_event_cb_; +}; + +class UwbAidl : public testing::TestWithParam { + public: + virtual void SetUp() override { + iuwb_ = IUwb::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); + ASSERT_NE(iuwb_, nullptr); + } + std::shared_ptr iuwb_; + + // TODO (b/197638976): We pick the first chip here. Need to fix this + // for supporting multiple chips in the future. + std::string getAnyChipName() { + std::vector chip_names; + ScopedAStatus status = iuwb_->getChips(&chip_names); + EXPECT_TRUE(status.isOk()); + EXPECT_FALSE(chip_names.empty()); + return chip_names[0]; + } + + // TODO (b/197638976): We pick the first chip here. Need to fix this + // for supporting multiple chips in the future. + std::shared_ptr getAnyChip() { + std::shared_ptr iuwb_chip; + ScopedAStatus status = iuwb_->getChip(getAnyChipName(), &iuwb_chip); + EXPECT_TRUE(status.isOk()); + EXPECT_NE(iuwb_chip, nullptr); + return iuwb_chip; + } + + std::shared_ptr getAnyChipAndOpen() { + std::promise open_cb_promise; + std::future open_cb_future{open_cb_promise.get_future()}; + std::shared_ptr callback = ndk::SharedRefBase::make( + [](auto /* data */) {}, + [&open_cb_promise](auto event, auto /* status */) { + if (event == UwbEvent::OPEN_CPLT) { + open_cb_promise.set_value(); + } + }); + std::chrono::milliseconds timeout{kCallbackTimeoutMs}; + const auto iuwb_chip = getAnyChip(); + EXPECT_TRUE(iuwb_chip->open(callback).isOk()); + EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready); + return iuwb_chip; + } +}; + +TEST_P(UwbAidl, GetChips) { + std::vector chip_names; + ScopedAStatus status = iuwb_->getChips(&chip_names); + EXPECT_TRUE(status.isOk()); + EXPECT_FALSE(chip_names.empty()); +} + +TEST_P(UwbAidl, GetChip) { + std::shared_ptr iuwb_chip; + ScopedAStatus status = iuwb_->getChip(getAnyChipName(), &iuwb_chip); + EXPECT_TRUE(status.isOk()); + EXPECT_NE(iuwb_chip, nullptr); +} + +TEST_P(UwbAidl, ChipOpen) { + std::promise open_cb_promise; + std::future open_cb_future{open_cb_promise.get_future()}; + std::shared_ptr callback = ndk::SharedRefBase::make( + [](auto /* data */) {}, + [&open_cb_promise](auto event, auto /* status */) { + if (event == UwbEvent::OPEN_CPLT) { + open_cb_promise.set_value(); + } + }); + std::chrono::milliseconds timeout{kCallbackTimeoutMs}; + const auto iuwb_chip = getAnyChip(); + EXPECT_TRUE(iuwb_chip->open(callback).isOk()); + EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready); +} + +TEST_P(UwbAidl, ChipClose) { + std::promise open_cb_promise; + std::future open_cb_future{open_cb_promise.get_future()}; + std::promise close_cb_promise; + std::future close_cb_future{close_cb_promise.get_future()}; + std::shared_ptr callback = ndk::SharedRefBase::make( + [](auto /* data */) {}, + [&open_cb_promise, &close_cb_promise](auto event, auto /* status */) { + if (event == UwbEvent::OPEN_CPLT) { + open_cb_promise.set_value(); + } + if (event == UwbEvent::CLOSE_CPLT) { + close_cb_promise.set_value(); + } + }); + std::chrono::milliseconds timeout{kCallbackTimeoutMs}; + const auto iuwb_chip = getAnyChip(); + EXPECT_TRUE(iuwb_chip->open(callback).isOk()); + EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready); + EXPECT_TRUE(iuwb_chip->close().isOk()); + EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready); +} + +TEST_P(UwbAidl, ChipCoreInit) { + const auto iuwb_chip = getAnyChipAndOpen(); + EXPECT_TRUE(iuwb_chip->coreInit().isOk()); +} + +TEST_P(UwbAidl, ChipGetSupportedVendorUciVersion) { + const auto iuwb_chip = getAnyChipAndOpen(); + EXPECT_TRUE(iuwb_chip->coreInit().isOk()); + + int version; + EXPECT_TRUE(iuwb_chip->getSupportedVendorUciVersion(&version).isOk()); + EXPECT_GT(version, 0); +} + +TEST_P(UwbAidl, ChipGetName) { + std::string chip_name = getAnyChipName(); + std::shared_ptr iuwb_chip; + ScopedAStatus status = iuwb_->getChip(chip_name, &iuwb_chip); + EXPECT_TRUE(status.isOk()); + EXPECT_NE(iuwb_chip, nullptr); + + std::string retrieved_chip_name; + status = iuwb_chip->getName(&retrieved_chip_name); + EXPECT_TRUE(status.isOk()); + EXPECT_EQ(retrieved_chip_name, chip_name); +} + +/** +TEST_P(UwbAidl, ChipSendUciMessage_GetDeviceInfo) { +const auto iuwb_chip = getAnyChipAndOpen(callback); +EXPECT_TRUE(iuwb_chip->coreInit(callback).isOk()); + +const std::vector +EXPECT_TRUE(iuwb_chip->sendUciMessage().isOk()); +} */ + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UwbAidl); +INSTANTIATE_TEST_SUITE_P(Uwb, UwbAidl, + testing::ValuesIn(android::getAidlHalInstanceNames(IUwb::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +}