diff options
-rw-r--r-- | apps/test/chqts/src/general_test/send_event_stress_test.cc | 8 | ||||
-rw-r--r-- | build/nanopb.mk | 2 | ||||
-rw-r--r-- | host/common/chre_aidl_hal_client.cc | 9 | ||||
-rw-r--r-- | host/common/hal_client.cc | 51 | ||||
-rw-r--r-- | host/common/include/chre_host/hal_client.h | 125 | ||||
-rw-r--r-- | host/hal_generic/aidl/generic_context_hub_aidl.cc | 10 | ||||
-rw-r--r-- | host/hal_generic/aidl/generic_context_hub_aidl.h | 3 | ||||
-rw-r--r-- | host/hal_generic/common/multi_client_context_hub_base.cc | 10 | ||||
-rw-r--r-- | host/hal_generic/common/multi_client_context_hub_base.h | 3 | ||||
-rw-r--r-- | host/test/hal_generic/common/hal_client_manager_test.cc | 8 | ||||
-rw-r--r-- | host/test/hal_generic/common/hal_client_test.cc | 107 |
11 files changed, 250 insertions, 86 deletions
diff --git a/apps/test/chqts/src/general_test/send_event_stress_test.cc b/apps/test/chqts/src/general_test/send_event_stress_test.cc index 6bc7e631..41e8dfe1 100644 --- a/apps/test/chqts/src/general_test/send_event_stress_test.cc +++ b/apps/test/chqts/src/general_test/send_event_stress_test.cc @@ -84,8 +84,12 @@ void SendEventStressTest::setUp(uint32_t messageSize, sendFatalFailureToHost("Insufficient events available"); } - // sCompleteCallbacksLeft may be 0 or 1 at this point. We don't care. - // We just know we also expect all the sEventsLeft to have callbacks. + // If kMaxEventsToSend events are sent, we need to reset + // sCompleteCallbacksLeft because we only expect at most sEventsLeft to have + // callbacks. + if (sEventsLeft == kMaxEventsToSend) { + sCompleteCallbacksLeft = 0; + } sCompleteCallbacksLeft += sEventsLeft; sInMethod = false; diff --git a/build/nanopb.mk b/build/nanopb.mk index 188f8b3c..012d683a 100644 --- a/build/nanopb.mk +++ b/build/nanopb.mk @@ -110,7 +110,7 @@ NANOPB_GENERATOR_SRCS = $(NANOPB_PREFIX)/generator/proto/nanopb_pb2.py NANOPB_GENERATOR_SRCS += $(NANOPB_PREFIX)/generator/proto/plugin_pb2.py $(NANOPB_GENERATOR_SRCS): - cd $(NANOPB_PREFIX)/generator/proto && make + cd $(NANOPB_PREFIX)/generator/proto && $(MAKE) ifneq ($(NANOPB_OPTIONS),) NANOPB_OPTIONS_FLAG = --options-file=$(NANOPB_OPTIONS) diff --git a/host/common/chre_aidl_hal_client.cc b/host/common/chre_aidl_hal_client.cc index 4f357494..a6f377c4 100644 --- a/host/common/chre_aidl_hal_client.cc +++ b/host/common/chre_aidl_hal_client.cc @@ -30,6 +30,7 @@ #include <regex> #include <stdexcept> #include <string> +#include <unordered_set> #include <vector> #include "chre_api/chre/version.h" @@ -43,6 +44,7 @@ using ::aidl::android::hardware::contexthub::ContextHubInfo; using ::aidl::android::hardware::contexthub::ContextHubMessage; using ::aidl::android::hardware::contexthub::HostEndpointInfo; using ::aidl::android::hardware::contexthub::IContextHub; +using ::aidl::android::hardware::contexthub::MessageDeliveryStatus; using ::aidl::android::hardware::contexthub::NanoappBinary; using ::aidl::android::hardware::contexthub::NanoappInfo; using ::aidl::android::hardware::contexthub::NanSessionRequest; @@ -196,6 +198,13 @@ class ContextHubCallback : public BnContextHubCallback { return ScopedAStatus::ok(); } + ScopedAStatus handleMessageDeliveryStatus( + char16_t /* hostEndPointId */, + const MessageDeliveryStatus & /* messageDeliveryStatus */) override { + resetPromise(); + return ScopedAStatus::ok(); + } + ScopedAStatus getUuid(std::array<uint8_t, 16> *out_uuid) override { *out_uuid = kUuid; return ScopedAStatus::ok(); diff --git a/host/common/hal_client.cc b/host/common/hal_client.cc index bd706592..6a1c0bfa 100644 --- a/host/common/hal_client.cc +++ b/host/common/hal_client.cc @@ -31,6 +31,21 @@ using ::aidl::android::hardware::contexthub::IContextHub; using ::aidl::android::hardware::contexthub::IContextHubCallback; using ::ndk::ScopedAStatus; +std::unique_ptr<HalClient> HalClient::create( + const std::shared_ptr<IContextHubCallback> &callback, + int32_t contextHubId) { + if (callback == nullptr) { + LOGE("Callback function must not be null."); + return nullptr; + } + auto halClient = + std::unique_ptr<HalClient>(new HalClient(callback, contextHubId)); + if (halClient->initConnection() != HalError::SUCCESS) { + return nullptr; + } + return halClient; +} + HalError HalClient::initConnection() { std::lock_guard<std::shared_mutex> lockGuard{mConnectionLock}; @@ -69,7 +84,7 @@ HalError HalClient::initConnection() { LOGE("Unable to register callback: %s", status.getDescription().c_str()); return HalError::CALLBACK_REGISTRATION_FAILED; } - LOGI("Successfully (re)connected to HAL"); + LOGI("Successfully connected to HAL."); return HalError::SUCCESS; } @@ -81,10 +96,7 @@ void HalClient::onHalDisconnected(void *cookie) { std::lock_guard<std::shared_mutex> lock(halClient->mConnectionLock); halClient->mContextHub = nullptr; } - { - std::lock_guard<std::shared_mutex> lock(halClient->mStateLock); - halClient->mConnectedEndpoints.clear(); - } + HalError result = halClient->initConnection(); uint64_t duration = ::android::elapsedRealtime() - startTime; if (result != HalError::SUCCESS) { @@ -93,6 +105,7 @@ void HalClient::onHalDisconnected(void *cookie) { duration, result); return; } + tryReconnectEndpoints(halClient); LOGI("Reconnected to HAL after %" PRIu64 "ms", duration); } @@ -104,10 +117,10 @@ ScopedAStatus HalClient::connectEndpoint( // HAL and/or CHRE be the single place to control the behavior. LOGW("Endpoint id %" PRIu16 " is already connected.", endpointId); } - ScopedAStatus result = callIfConnectedOrError( + ScopedAStatus result = callIfConnected( [&]() { return mContextHub->onHostEndpointConnected(hostEndpointInfo); }); if (result.isOk()) { - insertConnectedEndpoint(hostEndpointInfo.hostEndpointId); + insertConnectedEndpoint(hostEndpointInfo); } else { LOGE("Failed to connect the endpoint id %" PRIu16, hostEndpointInfo.hostEndpointId); @@ -121,7 +134,7 @@ ScopedAStatus HalClient::disconnectEndpoint(HostEndpointId hostEndpointId) { // to let HAL and/or CHRE be the single place to control the behavior. LOGW("Endpoint id %" PRIu16 " is already disconnected.", hostEndpointId); } - ScopedAStatus result = callIfConnectedOrError([&]() { + ScopedAStatus result = callIfConnected([&]() { return mContextHub->onHostEndpointDisconnected(hostEndpointId); }); if (result.isOk()) { @@ -141,7 +154,27 @@ ScopedAStatus HalClient::sendMessage(const ContextHubMessage &message) { " is unknown or disconnected. Message sending will be skipped in the " "future."); } - return callIfConnectedOrError( + return callIfConnected( [&]() { return mContextHub->sendMessageToHub(mContextHubId, message); }); } + +void HalClient::tryReconnectEndpoints(HalClient *halClient) { + std::lock_guard<std::shared_mutex> lock(halClient->mStateLock); + for (const auto &[endpointId, endpointInfo] : + halClient->mConnectedEndpoints) { + if (!halClient + ->callIfConnected([&]() { + return halClient->mContextHub->onHostEndpointConnected( + endpointInfo); + }) + .isOk()) { + LOGE("Failed to set up the connected state for endpoint %" PRIu16 + " after HAL restarts.", + endpointId); + halClient->mConnectedEndpoints.erase(endpointId); + } else { + LOGI("Reconnected endpoint %" PRIu16 " to CHRE HAL.", endpointId); + } + } +} } // namespace android::chre
\ No newline at end of file diff --git a/host/common/include/chre_host/hal_client.h b/host/common/include/chre_host/hal_client.h index 49f93eb5..bc6db3bb 100644 --- a/host/common/include/chre_host/hal_client.h +++ b/host/common/include/chre_host/hal_client.h @@ -20,9 +20,10 @@ #include <cinttypes> #include <memory> #include <shared_mutex> -#include <unordered_set> +#include <unordered_map> #include <vector> +#include <aidl/android/hardware/contexthub/BnContextHubCallback.h> #include <aidl/android/hardware/contexthub/ContextHubMessage.h> #include <aidl/android/hardware/contexthub/HostEndpointInfo.h> #include <aidl/android/hardware/contexthub/IContextHub.h> @@ -36,13 +37,18 @@ namespace android::chre { +using ::aidl::android::hardware::contexthub::AsyncEventType; +using ::aidl::android::hardware::contexthub::BnContextHubCallback; using ::aidl::android::hardware::contexthub::ContextHubInfo; using ::aidl::android::hardware::contexthub::ContextHubMessage; using ::aidl::android::hardware::contexthub::HostEndpointInfo; using ::aidl::android::hardware::contexthub::IContextHub; using ::aidl::android::hardware::contexthub::IContextHubCallback; using ::aidl::android::hardware::contexthub::IContextHubDefault; +using ::aidl::android::hardware::contexthub::MessageDeliveryStatus; using ::aidl::android::hardware::contexthub::NanoappBinary; +using ::aidl::android::hardware::contexthub::NanoappInfo; +using ::aidl::android::hardware::contexthub::NanSessionRequest; using ::aidl::android::hardware::contexthub::Setting; using ::ndk::ScopedAStatus; @@ -55,21 +61,10 @@ using ::ndk::ScopedAStatus; * already connected to HAL. * * <p>When the binder connection to HAL is disconnected HalClient will have a - * death recipient to re-establish the connection. Be aware that it is a - * client's responsibility to reconnect all the endpoints. This is because when - * the binder connection is set up, it is possible that all the API calls can't - * reach CHRE yet if CHRE also restarts at the same time. A client should rely - * on IContextHubCallback.handleContextHubAsyncEvent() to handle the RESTARTED - * event which is a signal that CHRE is up running. - * TODO(b/309690054): In reality HAL rarely crashes. When it does, CHRE could - * still be up running so HalClient should try to re-establish the states of - * connected endpoints by calling connectEndpoint anyway after the - * binder link reconnects. - * - * TODO(b/309690054): When CHRE crashes, HAL will bypass this HalCLient library - * and notify the client directly via - * IContextHubCallback.handleContextHubAsyncEvent(). In this situation - * HalClient.mConnectedEndpoints become out-of-date. + * death recipient re-establish the connection and reconnect the previously + * connected endpoints. In a rare case that CHRE also restarts at the same time, + * a client should rely on IContextHubCallback.handleContextHubAsyncEvent() to + * handle the RESTARTED event which is a signal that CHRE is up running. * * TODO(b/297912356): The name of this class is the same as an internal struct * used by HalClientManager. Consider rename the latter one to avoid confusion @@ -78,19 +73,21 @@ using ::ndk::ScopedAStatus; class HalClient { public: static constexpr int32_t kDefaultContextHubId = 0; + + /** + * Create a HalClient unique pointer used to communicate with CHRE HAL. + * + * @param callback a non-null callback. + * @param contextHubId context hub id that only 0 is supported at this moment. + * + * @return null pointer if the creation fails. + */ static std::unique_ptr<HalClient> create( const std::shared_ptr<IContextHubCallback> &callback, - int32_t contextHubId = kDefaultContextHubId) { - auto halClient = - std::unique_ptr<HalClient>(new HalClient(callback, contextHubId)); - if (halClient->initConnection() != HalError::SUCCESS) { - return nullptr; - } - return halClient; - } + int32_t contextHubId = kDefaultContextHubId); ScopedAStatus queryNanoapps() { - return callIfConnectedOrError( + return callIfConnected( [&]() { return mContextHub->queryNanoapps(mContextHubId); }); } @@ -101,9 +98,66 @@ class HalClient { ScopedAStatus disconnectEndpoint(char16_t hostEndpointId); protected: + class HalClientCallback : public BnContextHubCallback { + public: + explicit HalClientCallback( + const std::shared_ptr<IContextHubCallback> &callback, + HalClient *halClient) + : mCallback(callback), mHalClient(halClient) {} + + ScopedAStatus handleNanoappInfo( + const std::vector<NanoappInfo> &appInfo) override { + return mCallback->handleNanoappInfo(appInfo); + } + + ScopedAStatus handleContextHubMessage( + const ContextHubMessage &msg, + const std::vector<std::string> &msgContentPerms) override { + return mCallback->handleContextHubMessage(msg, msgContentPerms); + } + + ScopedAStatus handleContextHubAsyncEvent(AsyncEventType event) override { + if (event == AsyncEventType::RESTARTED) { + LOGW("CHRE has restarted. Reconnecting endpoints."); + tryReconnectEndpoints(mHalClient); + } + return mCallback->handleContextHubAsyncEvent(event); + } + + ScopedAStatus handleTransactionResult(int32_t transactionId, + bool success) override { + return mCallback->handleTransactionResult(transactionId, success); + } + + ScopedAStatus handleNanSessionRequest( + const NanSessionRequest &request) override { + return mCallback->handleNanSessionRequest(request); + } + + ScopedAStatus handleMessageDeliveryStatus( + char16_t hostEndPointId, + const MessageDeliveryStatus &messageDeliveryStatus) override { + return mCallback->handleMessageDeliveryStatus(hostEndPointId, + messageDeliveryStatus); + } + + ScopedAStatus getUuid(std::array<uint8_t, 16> *outUuid) override { + return mCallback->getUuid(outUuid); + } + + ScopedAStatus getName(std::string *outName) override { + return mCallback->getName(outName); + } + + private: + std::shared_ptr<IContextHubCallback> mCallback; + HalClient *mHalClient; + }; + explicit HalClient(const std::shared_ptr<IContextHubCallback> &callback, int32_t contextHubId = kDefaultContextHubId) - : mContextHubId(contextHubId), mCallback(callback) { + : mContextHubId(contextHubId) { + mCallback = ndk::SharedRefBase::make<HalClientCallback>(callback, this); ABinderProcess_startThreadPool(); mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(onHalDisconnected)); @@ -122,8 +176,10 @@ class HalClient { /** The callback for a disconnected HAL binder connection. */ static void onHalDisconnected(void *cookie); - ScopedAStatus callIfConnectedOrError( - const std::function<ScopedAStatus()> &func) { + /** Reconnect previously connected endpoints after CHRE or HAL restarts. */ + static void tryReconnectEndpoints(HalClient *halClient); + + ScopedAStatus callIfConnected(const std::function<ScopedAStatus()> &func) { std::shared_lock<std::shared_mutex> sharedLock(mConnectionLock); if (mContextHub == nullptr) { return fromHalError(HalError::BINDER_DISCONNECTED); @@ -137,9 +193,9 @@ class HalClient { mConnectedEndpoints.end(); } - void insertConnectedEndpoint(HostEndpointId hostEndpointId) { + void insertConnectedEndpoint(const HostEndpointInfo &hostEndpointInfo) { std::lock_guard<std::shared_mutex> lock(mStateLock); - mConnectedEndpoints.insert(hostEndpointId); + mConnectedEndpoints[hostEndpointInfo.hostEndpointId] = hostEndpointInfo; } void removeConnectedEndpoint(HostEndpointId hostEndpointId) { @@ -147,6 +203,11 @@ class HalClient { mConnectedEndpoints.erase(hostEndpointId); } + void clearConnectedEndpoints() { + std::lock_guard<std::shared_mutex> lock(mStateLock); + mConnectedEndpoints.clear(); + } + static ScopedAStatus fromHalError(HalError errorCode) { return errorCode == HalError::SUCCESS ? ScopedAStatus::ok() @@ -159,7 +220,7 @@ class HalClient { // The lock guarding mConnectedEndpoints. std::shared_mutex mStateLock; - std::unordered_set<HostEndpointId> mConnectedEndpoints{}; + std::unordered_map<HostEndpointId, HostEndpointInfo> mConnectedEndpoints{}; // The lock guarding mContextHub. std::shared_mutex mConnectionLock; @@ -168,7 +229,7 @@ class HalClient { // Handler of the binder disconnection event with HAL. ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; - std::shared_ptr<IContextHubCallback> mCallback; + std::shared_ptr<HalClientCallback> mCallback; }; } // namespace android::chre diff --git a/host/hal_generic/aidl/generic_context_hub_aidl.cc b/host/hal_generic/aidl/generic_context_hub_aidl.cc index 1f0a3506..16c5c3c7 100644 --- a/host/hal_generic/aidl/generic_context_hub_aidl.cc +++ b/host/hal_generic/aidl/generic_context_hub_aidl.cc @@ -125,6 +125,9 @@ ScopedAStatus ContextHub::getContextHubs( hub.supportedPermissions = kSupportedPermissions; + // TODO(b/312417087): Implement reliable message support + hub.supportsReliableMessages = false; + out_contextHubInfos->push_back(hub); } @@ -297,6 +300,13 @@ ScopedAStatus ContextHub::setTestMode(bool enable) { return enable ? enableTestMode() : disableTestMode(); } +ScopedAStatus ContextHub::sendMessageDeliveryStatusToHub( + int32_t /* contextHubId */, + const MessageDeliveryStatus & /* messageDeliveryStatus */) { + // TODO(b/312417087): Implement reliable message support + return ndk::ScopedAStatus::ok(); +} + ScopedAStatus ContextHub::onHostEndpointConnected( const HostEndpointInfo &in_info) { std::lock_guard<std::mutex> lock(mConnectedHostEndpointsMutex); diff --git a/host/hal_generic/aidl/generic_context_hub_aidl.h b/host/hal_generic/aidl/generic_context_hub_aidl.h index 9c12c16c..024cb1e3 100644 --- a/host/hal_generic/aidl/generic_context_hub_aidl.h +++ b/host/hal_generic/aidl/generic_context_hub_aidl.h @@ -79,6 +79,9 @@ class ContextHub : public BnContextHub, ::ndk::ScopedAStatus sendMessageToHub( int32_t contextHubId, const ContextHubMessage &message) override; ::ndk::ScopedAStatus setTestMode(bool enable) override; + ::ndk::ScopedAStatus sendMessageDeliveryStatusToHub( + int32_t contextHubId, + const MessageDeliveryStatus &messageDeliveryStatus) override; ::ndk::ScopedAStatus onHostEndpointConnected( const HostEndpointInfo &in_info) override; ::ndk::ScopedAStatus onHostEndpointDisconnected( diff --git a/host/hal_generic/common/multi_client_context_hub_base.cc b/host/hal_generic/common/multi_client_context_hub_base.cc index 289d78ce..0c257c36 100644 --- a/host/hal_generic/common/multi_client_context_hub_base.cc +++ b/host/hal_generic/common/multi_client_context_hub_base.cc @@ -411,6 +411,13 @@ ScopedAStatus MultiClientContextHubBase::setTestMode(bool enable) { return fromResult(enable ? enableTestMode() : disableTestMode()); } +ScopedAStatus MultiClientContextHubBase::sendMessageDeliveryStatusToHub( + int32_t /* contextHubId */, + const MessageDeliveryStatus & /* messageDeliveryStatus */) { + // TODO(b/312417087): Implement reliable message support - transaction status + return ndk::ScopedAStatus::ok(); +} + bool MultiClientContextHubBase::enableTestMode() { std::unique_lock<std::mutex> lock(mTestModeMutex); if (mIsTestModeEnabled) { @@ -531,6 +538,9 @@ void MultiClientContextHubBase::handleHubInfoResponse( mContextHubInfo->chreApiMinorVersion = extractChreApiMinorVersion(version); mContextHubInfo->chrePatchVersion = extractChrePatchVersion(version); mContextHubInfo->supportedPermissions = kSupportedPermissions; + + // TODO(b/312417087): Implement reliable message support + mContextHubInfo->supportsReliableMessages = false; mHubInfoCondition.notify_all(); } diff --git a/host/hal_generic/common/multi_client_context_hub_base.h b/host/hal_generic/common/multi_client_context_hub_base.h index b35c444b..7d92e71e 100644 --- a/host/hal_generic/common/multi_client_context_hub_base.h +++ b/host/hal_generic/common/multi_client_context_hub_base.h @@ -78,6 +78,9 @@ class MultiClientContextHubBase ScopedAStatus onNanSessionStateChanged( const NanSessionStateUpdate &in_update) override; ScopedAStatus setTestMode(bool enable) override; + ScopedAStatus sendMessageDeliveryStatusToHub( + int32_t contextHubId, + const MessageDeliveryStatus &messageDeliveryStatus) override; // The callback function implementing ChreConnectionCallback void handleMessageFromChre(const unsigned char *messageBuffer, diff --git a/host/test/hal_generic/common/hal_client_manager_test.cc b/host/test/hal_generic/common/hal_client_manager_test.cc index 6c72a1c1..6236db71 100644 --- a/host/test/hal_generic/common/hal_client_manager_test.cc +++ b/host/test/hal_generic/common/hal_client_manager_test.cc @@ -36,6 +36,7 @@ namespace { using aidl::android::hardware::contexthub::AsyncEventType; using aidl::android::hardware::contexthub::BnContextHubCallback; using aidl::android::hardware::contexthub::ContextHubMessage; +using aidl::android::hardware::contexthub::MessageDeliveryStatus; using aidl::android::hardware::contexthub::NanoappInfo; using aidl::android::hardware::contexthub::NanSessionRequest; @@ -95,6 +96,13 @@ class ContextHubCallbackForTest : public BnContextHubCallback { const NanSessionRequest & /* request */) override { return ScopedAStatus::ok(); } + + ScopedAStatus handleMessageDeliveryStatus( + char16_t /* hostEndPointId */, + const MessageDeliveryStatus & /* messageDeliveryStatus */) override { + return ScopedAStatus::ok(); + } + ScopedAStatus getUuid(std::array<uint8_t, 16> *out_uuid) override { *out_uuid = mUuid; return ScopedAStatus::ok(); diff --git a/host/test/hal_generic/common/hal_client_test.cc b/host/test/hal_generic/common/hal_client_test.cc index e9a52992..eac5bd84 100644 --- a/host/test/hal_generic/common/hal_client_test.cc +++ b/host/test/hal_generic/common/hal_client_test.cc @@ -16,6 +16,8 @@ #include "chre_host/hal_client.h" #include "host/hal_generic/common/hal_error.h" +#include <unordered_set> + #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -27,6 +29,7 @@ namespace { using ::aidl::android::hardware::contexthub::ContextHubMessage; using ::aidl::android::hardware::contexthub::HostEndpointInfo; using ::aidl::android::hardware::contexthub::IContextHub; +using ::aidl::android::hardware::contexthub::IContextHubCallbackDefault; using ::aidl::android::hardware::contexthub::IContextHubDefault; using ::ndk::ScopedAStatus; @@ -38,17 +41,32 @@ using ::testing::IsEmpty; using ::testing::Return; using ::testing::UnorderedElementsAre; +using HostEndpointId = char16_t; +constexpr HostEndpointId kEndpointId = 0x10; + class HalClientForTest : public HalClient { public: HalClientForTest(const std::shared_ptr<IContextHub> &contextHub, - const std::unordered_set<char16_t> &connectedEndpoints) - : HalClient(/* callback= */ nullptr) { + const std::vector<HostEndpointId> &connectedEndpoints, + const std::shared_ptr<IContextHubCallback> &callback = + ndk::SharedRefBase::make<IContextHubCallbackDefault>()) + : HalClient(callback) { mContextHub = contextHub; - mConnectedEndpoints = connectedEndpoints; + for (const HostEndpointId &endpointId : connectedEndpoints) { + mConnectedEndpoints[endpointId] = {.hostEndpointId = endpointId}; + } } - std::unordered_set<char16_t> getConnectedEndpoints() { - return mConnectedEndpoints; + std::unordered_set<HostEndpointId> getConnectedEndpointIds() { + std::unordered_set<HostEndpointId> result{}; + for (const auto &[endpointId, unusedEndpointInfo] : mConnectedEndpoints) { + result.insert(endpointId); + } + return result; + } + + HalClientCallback *getClientCallback() { + return mCallback.get(); } }; @@ -56,8 +74,8 @@ class MockContextHub : public IContextHubDefault { public: MOCK_METHOD(ScopedAStatus, onHostEndpointConnected, (const HostEndpointInfo &info), (override)); - MOCK_METHOD(ScopedAStatus, onHostEndpointDisconnected, (char16_t endpointId), - (override)); + MOCK_METHOD(ScopedAStatus, onHostEndpointDisconnected, + (HostEndpointId endpointId), (override)); MOCK_METHOD(ScopedAStatus, queryNanoapps, (int32_t icontextHubId), (override)); MOCK_METHOD(ScopedAStatus, sendMessageToHub, @@ -69,8 +87,6 @@ class MockContextHub : public IContextHubDefault { TEST(HalClientTest, EndpointConnectionBasic) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - constexpr char16_t kEndpointId = 0x10; - std::unordered_set<char16_t> connectedEndpoints{}; const HostEndpointInfo kInfo = { .hostEndpointId = kEndpointId, .type = HostEndpointInfo::Type::NATIVE, @@ -78,9 +94,9 @@ TEST(HalClientTest, EndpointConnectionBasic) { .attributionTag{}, }; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); - EXPECT_THAT(halClient->getConnectedEndpoints(), IsEmpty()); + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{}); + EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty()); EXPECT_CALL(*mockContextHub, onHostEndpointConnected( @@ -88,15 +104,12 @@ TEST(HalClientTest, EndpointConnectionBasic) { .WillOnce(Return(ScopedAStatus::ok())); halClient->connectEndpoint(kInfo); - - EXPECT_THAT(halClient->getConnectedEndpoints(), + EXPECT_THAT(halClient->getConnectedEndpointIds(), UnorderedElementsAre(kEndpointId)); } TEST(HalClientTest, EndpointConnectionMultipleRequests) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - constexpr char16_t kEndpointId = 0x10; - std::unordered_set<char16_t> connectedEndpoints{}; const HostEndpointInfo kInfo = { .hostEndpointId = kEndpointId, .type = HostEndpointInfo::Type::NATIVE, @@ -104,9 +117,9 @@ TEST(HalClientTest, EndpointConnectionMultipleRequests) { .attributionTag{}, }; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); - EXPECT_THAT(halClient->getConnectedEndpoints(), IsEmpty()); + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{}); + EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty()); // multiple requests are tolerated EXPECT_CALL(*mockContextHub, @@ -118,33 +131,30 @@ TEST(HalClientTest, EndpointConnectionMultipleRequests) { halClient->connectEndpoint(kInfo); halClient->connectEndpoint(kInfo); - EXPECT_THAT(halClient->getConnectedEndpoints(), + EXPECT_THAT(halClient->getConnectedEndpointIds(), UnorderedElementsAre(kEndpointId)); } TEST(HalClientTest, EndpointDisconnectionBasic) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - constexpr char16_t kEndpointId = 0x10; - std::unordered_set<char16_t> connectedEndpoints{kEndpointId}; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); - EXPECT_THAT(halClient->getConnectedEndpoints(), + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{kEndpointId}); + + EXPECT_THAT(halClient->getConnectedEndpointIds(), UnorderedElementsAre(kEndpointId)); EXPECT_CALL(*mockContextHub, onHostEndpointDisconnected(kEndpointId)) .WillOnce(Return(ScopedAStatus::ok())); - halClient->disconnectEndpoint(kEndpointId); - EXPECT_THAT(halClient->getConnectedEndpoints(), IsEmpty()); + + EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty()); } TEST(HalClientTest, EndpointDisconnectionMultipleRequest) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - constexpr char16_t kEndpointId = 0x10; - std::unordered_set<char16_t> connectedEndpoints{kEndpointId}; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); - EXPECT_THAT(halClient->getConnectedEndpoints(), + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{kEndpointId}); + EXPECT_THAT(halClient->getConnectedEndpointIds(), UnorderedElementsAre(kEndpointId)); EXPECT_CALL(*mockContextHub, onHostEndpointDisconnected(kEndpointId)) @@ -154,36 +164,49 @@ TEST(HalClientTest, EndpointDisconnectionMultipleRequest) { halClient->disconnectEndpoint(kEndpointId); halClient->disconnectEndpoint(kEndpointId); - EXPECT_THAT(halClient->getConnectedEndpoints(), IsEmpty()); + EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty()); } TEST(HalClientTest, SendMessageBasic) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - constexpr char16_t kEndpointId = 0x10; const ContextHubMessage contextHubMessage = { .nanoappId = 0xbeef, .hostEndPoint = kEndpointId, .messageBody = {}, .permissions = {}, }; - std::unordered_set<char16_t> connectedEndpoints{kEndpointId}; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{kEndpointId}); EXPECT_CALL(*mockContextHub, sendMessageToHub(_, _)) .WillOnce(Return(ScopedAStatus::ok())); - halClient->sendMessage(contextHubMessage); } TEST(HalClientTest, QueryNanoapp) { auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); - std::unordered_set<char16_t> connectedEndpoints{}; - auto halClient = - std::make_unique<HalClientForTest>(mockContextHub, connectedEndpoints); + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, std::vector<HostEndpointId>{}); EXPECT_CALL(*mockContextHub, queryNanoapps(HalClient::kDefaultContextHubId)); - halClient->queryNanoapps(); } + +TEST(HalClientTest, HandleChreRestart) { + auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>(); + + auto halClient = std::make_unique<HalClientForTest>( + mockContextHub, + std::vector<HostEndpointId>{kEndpointId, kEndpointId + 1}); + + EXPECT_CALL(*mockContextHub, onHostEndpointConnected( + Field(&HostEndpointInfo::hostEndpointId, _))) + .WillOnce(Return(ScopedAStatus::ok())) + .WillOnce(Return(ScopedAStatus::ok())); + + halClient->getClientCallback()->handleContextHubAsyncEvent( + AsyncEventType::RESTARTED); + EXPECT_THAT(halClient->getConnectedEndpointIds(), + UnorderedElementsAre(kEndpointId, kEndpointId + 1)); +} } // namespace android::chre |