From a2c3db1e70bfb661148bdc32776f2efd219afae6 Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Wed, 16 Dec 2020 15:04:02 -0500 Subject: [PATCH] Add VTS tests for new methods in contexthub HAL 1.2 Bug: 166846988 Test: Run against production HAL Change-Id: I9e22f41736d54501cd74c7d56f61db8e771529df --- .../VtsHalContexthubV1_0TargetTest.cpp | 35 +--- .../VtsHalContexthubV1_1TargetTest.cpp | 5 +- .../VtsHalContexthubV1_2TargetTest.cpp | 171 +++++++++++++++++- .../common/vts/ContexthubCallbackBase.h | 3 +- contexthub/common/vts/VtsHalContexthubUtils.h | 27 +++ 5 files changed, 203 insertions(+), 38 deletions(-) diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp index 8a90173bf1..356ad97327 100644 --- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp +++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp @@ -52,40 +52,17 @@ using ::android::hardware::contexthub::vts_utils::ContexthubCallbackBase; using ::android::hardware::contexthub::vts_utils::ContexthubHidlTestBase; using ::android::hardware::contexthub::vts_utils::getHalAndHubIdList; using ::android::hardware::contexthub::vts_utils::getHubsSync; +using ::android::hardware::contexthub::vts_utils::kNonExistentAppId; +using ::android::hardware::contexthub::vts_utils::waitForCallback; namespace { -// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This -// app ID is reserved and must never appear in the list of loaded apps. -constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555; - const std::vector> kTestParameters = getHalAndHubIdList(); class ContexthubHidlTest : public ContexthubHidlTestBase {}; -// Wait for a callback to occur (signaled by the given future) up to the -// provided timeout. If the future is invalid or the callback does not come -// within the given time, returns false. -template -bool waitForCallback(std::future future, ReturnType* result, - std::chrono::milliseconds timeout = std::chrono::seconds(5)) { - auto expiration = std::chrono::system_clock::now() + timeout; - - EXPECT_NE(result, nullptr); - EXPECT_TRUE(future.valid()); - if (result != nullptr && future.valid()) { - std::future_status status = future.wait_until(expiration); - EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback"; - - if (status == std::future_status::ready) { - *result = future.get(); - return true; - } - } - - return false; -} +class ContexthubCallbackV1_0 : public ContexthubCallbackBase {}; // Ensures that the metadata reported in getHubs() is sane TEST_P(ContexthubHidlTest, TestGetHubs) { @@ -110,7 +87,7 @@ TEST_P(ContexthubHidlTest, TestGetHubs) { TEST_P(ContexthubHidlTest, TestRegisterCallback) { ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId()); - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback(new ContexthubCallbackV1_0())); } TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { @@ -119,7 +96,7 @@ TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { } // Helper callback that puts the async appInfo callback data into a promise -class QueryAppsCallback : public ContexthubCallbackBase { +class QueryAppsCallback : public ContexthubCallbackV1_0 { public: virtual Return handleAppsInfo(const hidl_vec& appInfo) override { ALOGD("Got app info callback with %zu apps", appInfo.size()); @@ -150,7 +127,7 @@ TEST_P(ContexthubHidlTest, TestQueryApps) { // Helper callback that puts the TransactionResult for the expectedTxnId into a // promise -class TxnResultCallback : public ContexthubCallbackBase { +class TxnResultCallback : public ContexthubCallbackV1_0 { public: virtual Return handleTxnResult(uint32_t txnId, TransactionResult result) override { ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %" PRIu32 diff --git a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp index 5f1dad97cb..acf4be0c45 100644 --- a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp +++ b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp @@ -31,6 +31,7 @@ #include +using ::android::hardware::contexthub::V1_0::IContexthubCallback; using ::android::hardware::contexthub::V1_1::IContexthub; using ::android::hardware::contexthub::V1_1::Setting; using ::android::hardware::contexthub::V1_1::SettingValue; @@ -45,10 +46,12 @@ const std::vector> kTestParameters = class ContexthubHidlTest : public ContexthubHidlTestBase {}; +class ContexthubCallbackV1_0 : public ContexthubCallbackBase {}; + TEST_P(ContexthubHidlTest, TestOnSettingChanged) { // In VTS, we only test that sending the values doesn't cause things to blow up - other test // suites verify the expected E2E behavior in CHRE - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback(new ContexthubCallbackV1_0())); hubApi->onSettingChanged(Setting::LOCATION, SettingValue::DISABLED); hubApi->onSettingChanged(Setting::LOCATION, SettingValue::ENABLED); ASSERT_OK(registerCallback(nullptr)); diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp index 782edae610..c50d43c137 100644 --- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp +++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp @@ -32,45 +32,202 @@ #include +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::contexthub::V1_0::ContextHub; +using ::android::hardware::contexthub::V1_0::Result; +using ::android::hardware::contexthub::V1_0::TransactionResult; using ::android::hardware::contexthub::V1_1::SettingValue; +using ::android::hardware::contexthub::V1_2::ContextHubMsg; +using ::android::hardware::contexthub::V1_2::HubAppInfo; using ::android::hardware::contexthub::V1_2::IContexthub; +using ::android::hardware::contexthub::V1_2::IContexthubCallback; using ::android::hardware::contexthub::V1_2::Setting; +using ::android::hardware::contexthub::vts_utils::asBaseType; using ::android::hardware::contexthub::vts_utils::ContexthubCallbackBase; using ::android::hardware::contexthub::vts_utils::ContexthubHidlTestBase; using ::android::hardware::contexthub::vts_utils::getHalAndHubIdList; +using ::android::hardware::contexthub::vts_utils::kNonExistentAppId; +using ::android::hardware::contexthub::vts_utils::waitForCallback; namespace { const std::vector> kTestParameters = getHalAndHubIdList(); -class ContexthubHidlTest : public ContexthubHidlTestBase {}; +class ContexthubCallbackV1_2 : public ContexthubCallbackBase { + public: + virtual Return handleClientMsg_1_2( + const ContextHubMsg& /*msg*/, + const hidl_vec& /*msgContentPerms*/) override { + ALOGD("Got client message callback"); + return Void(); + } + + virtual Return handleAppsInfo_1_2(const hidl_vec& /*appInfo*/) override { + ALOGD("Got app info callback"); + return Void(); + } +}; + +class ContexthubHidlTest : public ContexthubHidlTestBase { + public: + Result registerCallback_1_2(sp cb) { + return hubApi->registerCallback_1_2(getHubId(), cb); + } +}; + +// Ensures that the metadata reported in getHubs_1_2() is valid +TEST_P(ContexthubHidlTest, TestGetHubs_1_2) { + hidl_vec hubList; + hubApi->getHubs_1_2( + [&hubList](const hidl_vec& hubs, + const hidl_vec& /*hubPermissions*/) { hubList = hubs; }); + + ALOGD("System reports %zu hubs", hubList.size()); + + for (const ContextHub& hub : hubList) { + ALOGD("Checking hub ID %" PRIu32, hub.hubId); + + EXPECT_FALSE(hub.name.empty()); + EXPECT_FALSE(hub.vendor.empty()); + EXPECT_FALSE(hub.toolchain.empty()); + EXPECT_GT(hub.peakMips, 0); + EXPECT_GE(hub.stoppedPowerDrawMw, 0); + EXPECT_GE(hub.sleepPowerDrawMw, 0); + EXPECT_GT(hub.peakPowerDrawMw, 0); + + // Minimum 128 byte MTU as required by CHRE API v1.0 + EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128)); + } +} + +TEST_P(ContexthubHidlTest, TestRegisterCallback) { + ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId()); + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); +} + +TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { + ALOGD("TestRegisterNullCallback called, hubId %" PRIu32, getHubId()); + ASSERT_OK(registerCallback_1_2(nullptr)); +} // In VTS, we only test that sending the values doesn't cause things to blow up - other test // suites verify the expected E2E behavior in CHRE TEST_P(ContexthubHidlTest, TestOnWifiSettingChanged) { - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::DISABLED); hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::ENABLED); - ASSERT_OK(registerCallback(nullptr)); + ASSERT_OK(registerCallback_1_2(nullptr)); } TEST_P(ContexthubHidlTest, TestOnAirplaneModeSettingChanged) { - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::DISABLED); hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::ENABLED); - ASSERT_OK(registerCallback(nullptr)); + ASSERT_OK(registerCallback_1_2(nullptr)); } TEST_P(ContexthubHidlTest, TestOnGlobalMicDisableSettingChanged) { - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::DISABLED); hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::ENABLED); - ASSERT_OK(registerCallback(nullptr)); + ASSERT_OK(registerCallback_1_2(nullptr)); +} + +// Helper callback that puts the async appInfo callback data into a promise +class QueryAppsCallback : public ContexthubCallbackV1_2 { + public: + virtual Return handleAppsInfo_1_2(const hidl_vec& appInfo) override { + ALOGD("Got app info callback with %zu apps", appInfo.size()); + promise.set_value(appInfo); + return Void(); + } + + std::promise> promise; +}; + +// Calls queryApps() and checks the returned metadata +TEST_P(ContexthubHidlTest, TestQueryApps) { + hidl_vec hubPerms; + hubApi->getHubs_1_2([&hubPerms](const hidl_vec& /*hubs*/, + const hidl_vec& hubPermissions) { + hubPerms = hubPermissions; + }); + + ALOGD("TestQueryApps called, hubId %u", getHubId()); + sp cb = new QueryAppsCallback(); + ASSERT_OK(registerCallback_1_2(cb)); + + Result result = hubApi->queryApps(getHubId()); + ASSERT_OK(result); + + ALOGD("Waiting for app info callback"); + hidl_vec appList; + ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appList)); + for (const HubAppInfo& appInfo : appList) { + EXPECT_NE(appInfo.info_1_0.appId, UINT64_C(0)); + EXPECT_NE(appInfo.info_1_0.appId, kNonExistentAppId); + for (std::string permission : appInfo.permissions) { + ASSERT_TRUE(hubPerms.contains(permission)); + } + } +} + +// Helper callback that puts the TransactionResult for the expectedTxnId into a +// promise +class TxnResultCallback : public ContexthubCallbackV1_2 { + public: + virtual Return handleTxnResult(uint32_t txnId, TransactionResult result) override { + ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %" PRIu32 + ") with result %" PRId32, + txnId, expectedTxnId, result); + if (txnId == expectedTxnId) { + promise.set_value(result); + } + return Void(); + } + + uint32_t expectedTxnId = 0; + std::promise promise; +}; + +// Parameterized fixture that sets the callback to TxnResultCallback +class ContexthubTxnTest : public ContexthubHidlTest { + public: + virtual void SetUp() override { + ContexthubHidlTest::SetUp(); + ASSERT_OK(registerCallback_1_2(cb)); + } + + sp cb = new TxnResultCallback(); +}; + +TEST_P(ContexthubTxnTest, TestSendMessageToNonExistentNanoApp) { + ContextHubMsg msg; + msg.msg_1_0.appName = kNonExistentAppId; + msg.msg_1_0.msgType = 1; + msg.msg_1_0.msg.resize(4); + std::fill(msg.msg_1_0.msg.begin(), msg.msg_1_0.msg.end(), 0); + + ALOGD("Sending message to non-existent nanoapp"); + Result result = hubApi->sendMessageToHub_1_2(getHubId(), msg); + if (result != Result::OK && result != Result::BAD_PARAMS && + result != Result::TRANSACTION_FAILED) { + FAIL() << "Got result " << asBaseType(result) << ", expected OK, BAD_PARAMS" + << ", or TRANSACTION_FAILED"; + } } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest); INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters), android::hardware::PrintInstanceTupleNameToString<>); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubTxnTest); +INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubTxnTest, testing::ValuesIn(kTestParameters), + android::hardware::PrintInstanceTupleNameToString<>); + } // anonymous namespace diff --git a/contexthub/common/vts/ContexthubCallbackBase.h b/contexthub/common/vts/ContexthubCallbackBase.h index 124a11601a..24d6c52705 100644 --- a/contexthub/common/vts/ContexthubCallbackBase.h +++ b/contexthub/common/vts/ContexthubCallbackBase.h @@ -27,7 +27,8 @@ namespace vts_utils { // Base callback implementation that just logs all callbacks by default, but // records a failure if -class ContexthubCallbackBase : public V1_0::IContexthubCallback { +template +class ContexthubCallbackBase : public CallbackType { public: virtual Return handleClientMsg(const V1_0::ContextHubMsg& /*msg*/) override { ALOGD("Got client message callback"); diff --git a/contexthub/common/vts/VtsHalContexthubUtils.h b/contexthub/common/vts/VtsHalContexthubUtils.h index 8f9b6946d9..dff1865f4c 100644 --- a/contexthub/common/vts/VtsHalContexthubUtils.h +++ b/contexthub/common/vts/VtsHalContexthubUtils.h @@ -30,6 +30,10 @@ namespace hardware { namespace contexthub { namespace vts_utils { +// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This +// app ID is reserved and must never appear in the list of loaded apps. +constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555; + #define ASSERT_OK(result) ASSERT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK) #define EXPECT_OK(result) EXPECT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK) @@ -64,6 +68,29 @@ static std::vector> getHalAndHubIdList() { return parameters; } +// Wait for a callback to occur (signaled by the given future) up to the +// provided timeout. If the future is invalid or the callback does not come +// within the given time, returns false. +template +bool waitForCallback(std::future future, ReturnType* result, + std::chrono::milliseconds timeout = std::chrono::seconds(5)) { + auto expiration = std::chrono::system_clock::now() + timeout; + + EXPECT_NE(result, nullptr); + EXPECT_TRUE(future.valid()); + if (result != nullptr && future.valid()) { + std::future_status status = future.wait_until(expiration); + EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback"; + + if (status == std::future_status::ready) { + *result = future.get(); + return true; + } + } + + return false; +} + } // namespace vts_utils } // namespace contexthub } // namespace hardware