aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/test/chqts/src/general_test/send_event_stress_test.cc8
-rw-r--r--build/nanopb.mk2
-rw-r--r--host/common/chre_aidl_hal_client.cc9
-rw-r--r--host/common/hal_client.cc51
-rw-r--r--host/common/include/chre_host/hal_client.h125
-rw-r--r--host/hal_generic/aidl/generic_context_hub_aidl.cc10
-rw-r--r--host/hal_generic/aidl/generic_context_hub_aidl.h3
-rw-r--r--host/hal_generic/common/multi_client_context_hub_base.cc10
-rw-r--r--host/hal_generic/common/multi_client_context_hub_base.h3
-rw-r--r--host/test/hal_generic/common/hal_client_manager_test.cc8
-rw-r--r--host/test/hal_generic/common/hal_client_test.cc107
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