1 /*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "message_hub_manager.h"
18
19 #include <cstddef>
20 #include <memory>
21 #include <random>
22 #include <unordered_map>
23
24 #include <aidl/android/hardware/contexthub/IContextHub.h>
25
26 #include "chre/platform/log.h"
27
28 #include "gmock/gmock.h"
29 #include "gtest/gtest.h"
30
31 namespace android::hardware::contexthub::common::implementation {
32 namespace {
33
34 using ::aidl::android::hardware::contexthub::EndpointId;
35 using ::aidl::android::hardware::contexthub::EndpointInfo;
36 using ::aidl::android::hardware::contexthub::ErrorCode;
37 using ::aidl::android::hardware::contexthub::HubInfo;
38 using ::aidl::android::hardware::contexthub::IEndpointCallback;
39 using ::aidl::android::hardware::contexthub::Message;
40 using ::aidl::android::hardware::contexthub::MessageDeliveryStatus;
41 using ::aidl::android::hardware::contexthub::Reason;
42 using ::ndk::ScopedAStatus;
43 using ::ndk::SharedRefBase;
44 using ::ndk::SpAIBinder;
45 using ::testing::_;
46 using ::testing::AllOf;
47 using ::testing::AnyNumber;
48 using ::testing::Ge;
49 using ::testing::IsEmpty;
50 using ::testing::IsNull;
51 using ::testing::Le;
52 using ::testing::NiceMock;
53 using ::testing::Return;
54 using ::testing::UnorderedElementsAreArray;
55
56 class MockEndpointCallback : public IEndpointCallback {
57 public:
58 MOCK_METHOD(ScopedAStatus, onEndpointStarted,
59 (const std::vector<EndpointInfo> &), (override));
60 MOCK_METHOD(ScopedAStatus, onEndpointStopped,
61 (const std::vector<EndpointId> &, Reason), (override));
62 MOCK_METHOD(ScopedAStatus, onMessageReceived, (int32_t, const Message &),
63 (override));
64 MOCK_METHOD(ScopedAStatus, onMessageDeliveryStatusReceived,
65 (int32_t, const MessageDeliveryStatus &), (override));
66 MOCK_METHOD(ScopedAStatus, onEndpointSessionOpenRequest,
67 (int32_t, const EndpointId &, const EndpointId &,
68 const std::optional<std::string> &),
69 (override));
70 MOCK_METHOD(ScopedAStatus, onCloseEndpointSession, (int32_t, Reason),
71 (override));
72 MOCK_METHOD(ScopedAStatus, onEndpointSessionOpenComplete, (int32_t),
73 (override));
74 MOCK_METHOD(SpAIBinder, asBinder, (), (override));
75 MOCK_METHOD(bool, isRemote, (), (override));
76 MOCK_METHOD(ScopedAStatus, getInterfaceVersion, (int32_t *), (override));
77 MOCK_METHOD(ScopedAStatus, getInterfaceHash, (std::string *), (override));
78
MockEndpointCallback()79 MockEndpointCallback() {
80 ON_CALL(*this, onEndpointStarted)
81 .WillByDefault([](const std::vector<EndpointInfo> &) {
82 return ScopedAStatus::ok();
83 });
84 ON_CALL(*this, onEndpointStopped)
85 .WillByDefault([](const std::vector<EndpointId> &, Reason) {
86 return ScopedAStatus::ok();
87 });
88 ON_CALL(*this, onMessageReceived)
89 .WillByDefault(
90 [](int32_t, const Message &) { return ScopedAStatus::ok(); });
91 ON_CALL(*this, onMessageDeliveryStatusReceived)
92 .WillByDefault([](int32_t, const MessageDeliveryStatus &) {
93 return ScopedAStatus::ok();
94 });
95 ON_CALL(*this, onEndpointSessionOpenRequest)
96 .WillByDefault([](int32_t, const EndpointId &, const EndpointId &,
97 const std::optional<std::string> &) {
98 return ScopedAStatus::ok();
99 });
100 ON_CALL(*this, onCloseEndpointSession).WillByDefault([](int32_t, Reason) {
101 return ScopedAStatus::ok();
102 });
103 ON_CALL(*this, onEndpointSessionOpenComplete).WillByDefault([](int32_t) {
104 return ScopedAStatus::ok();
105 });
106 }
107 };
108
109 constexpr int64_t kHub1Id = 0x1, kHub2Id = 0x2;
110 constexpr int64_t kEndpoint1Id = 0x1, kEndpoint2Id = 0x2;
111 const std::string kTestServiceDescriptor = "test_service";
112 const HubInfo kHub1Info{.hubId = kHub1Id};
113 const HubInfo kHub2Info{.hubId = kHub2Id};
114 const Service kTestService{.serviceDescriptor = kTestServiceDescriptor};
115 const EndpointInfo kEndpoint1_1Info{
116 .id = {.id = kEndpoint1Id, .hubId = kHub1Id}};
117 const EndpointInfo kEndpoint1_2Info{
118 .id = {.id = kEndpoint2Id, .hubId = kHub1Id}, .services = {kTestService}};
119 const EndpointInfo kEndpoint2_1Info{
120 .id = {.id = kEndpoint1Id, .hubId = kHub2Id}};
121 const EndpointInfo kEndpoint2_2Info{
122 .id = {.id = kEndpoint2Id, .hubId = kHub2Id}, .services = {kTestService}};
123
124 } // namespace
125
126 class MessageHubManagerTest : public ::testing::Test {
127 public:
128 using HostHub = MessageHubManager::HostHub;
129 using DeathRecipientCookie = HostHub::DeathRecipientCookie;
130 using HostHubDownCb = MessageHubManager::HostHubDownCb;
131
132 static constexpr auto kSessionIdMaxRange = HostHub::kSessionIdMaxRange;
133 static constexpr auto kHostSessionIdBase =
134 MessageHubManager::kHostSessionIdBase;
135
SetUp()136 void SetUp() override {
137 reinit([](std::function<pw::Result<int64_t>()>) { FAIL(); });
138 }
139
TearDown()140 void TearDown() override {
141 mManager->forEachHostHub([](HostHub &hub) { delete hub.mCookie; });
142 }
143
reinit(HostHubDownCb cb)144 void reinit(HostHubDownCb cb) {
145 auto deathRecipient = std::make_unique<NiceMock<MockDeathRecipient>>();
146 mDeathRecipient = deathRecipient.get();
147 ON_CALL(*deathRecipient, linkCallback(_, _))
148 .WillByDefault(Return(pw::OkStatus()));
149 ON_CALL(*deathRecipient, unlinkCallback(_, _))
150 .WillByDefault(Return(pw::OkStatus()));
151 mManager.reset(
152 new MessageHubManager(std::move(deathRecipient), std::move(cb)));
153 }
154
onClientDeath(const std::shared_ptr<HostHub> & hub)155 void onClientDeath(const std::shared_ptr<HostHub> &hub) {
156 MessageHubManager::onClientDeath(hub->mCookie);
157 }
158
setupDefaultHubs()159 void setupDefaultHubs() {
160 mManager->initEmbeddedState();
161 mManager->addEmbeddedHub(kHub2Info);
162 mManager->addEmbeddedEndpoint(kEndpoint2_1Info);
163 mManager->setEmbeddedEndpointReady(kEndpoint2_1Info.id);
164 mManager->addEmbeddedEndpoint(kEndpoint2_2Info);
165 mManager->setEmbeddedEndpointReady(kEndpoint2_2Info.id);
166 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
167 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
168 EXPECT_TRUE(mHostHub->addEndpoint(kEndpoint1_1Info).ok());
169 EXPECT_TRUE(mHostHub->addEndpoint(kEndpoint1_2Info).ok());
170 }
171
setupDefaultHubsAndSession()172 uint16_t setupDefaultHubsAndSession() {
173 setupDefaultHubs();
174 auto range = *mHostHub->reserveSessionIdRange(1);
175 EXPECT_TRUE(mHostHub
176 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
177 range.first, {}, /*hostInitiated=*/true)
178 .ok());
179 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenComplete(range.first));
180 EXPECT_TRUE(mManager->getHostHub(kHub1Id)
181 ->ackSession(range.first,
182 /*hostAcked=*/false)
183 .ok());
184 return range.first;
185 }
186
187 protected:
188 class MockDeathRecipient : public MessageHubManager::DeathRecipient {
189 public:
190 MOCK_METHOD(pw::Status, linkCallback,
191 (const std::shared_ptr<IEndpointCallback> &,
192 DeathRecipientCookie *),
193 (override));
194 MOCK_METHOD(pw::Status, unlinkCallback,
195 (const std::shared_ptr<IEndpointCallback> &,
196 DeathRecipientCookie *),
197 (override));
198 };
199
200 std::unique_ptr<MessageHubManager> mManager;
201 NiceMock<MockDeathRecipient> *mDeathRecipient;
202
203 std::shared_ptr<HostHub> mHostHub;
204 std::shared_ptr<MockEndpointCallback> mHostHubCb;
205 };
206
207 namespace {
208
209 MATCHER_P(MatchSp, sp, "Matches an IEndpointCallback") {
210 return arg.get() == sp.get();
211 }
212
TEST_F(MessageHubManagerTest,CreateAndUnregisterHostHub)213 TEST_F(MessageHubManagerTest, CreateAndUnregisterHostHub) {
214 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
215 DeathRecipientCookie *cookie;
216 EXPECT_CALL(*mDeathRecipient, linkCallback(MatchSp(mHostHubCb), _))
217 .WillOnce([&cookie](const std::shared_ptr<IEndpointCallback> &,
218 DeathRecipientCookie *c) {
219 cookie = c;
220 return pw::OkStatus();
221 });
222 auto statusOrHub = mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
223 ASSERT_TRUE(statusOrHub.ok());
224
225 mHostHub = *statusOrHub;
226 EXPECT_EQ(mHostHub->id(), kHub1Id);
227 EXPECT_EQ(mHostHub, mManager->getHostHub(kHub1Id));
228
229 EXPECT_CALL(*mDeathRecipient, unlinkCallback(MatchSp(mHostHubCb), cookie))
230 .WillOnce(Return(pw::OkStatus()));
231 mHostHub->unregister();
232 EXPECT_EQ(mHostHub->unregister(), pw::Status::Aborted());
233 EXPECT_THAT(mManager->getHostHub(kHub1Id), IsNull());
234 }
235
TEST_F(MessageHubManagerTest,CreateHostHubFails)236 TEST_F(MessageHubManagerTest, CreateHostHubFails) {
237 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
238 EXPECT_CALL(*mDeathRecipient, linkCallback(MatchSp(mHostHubCb), _))
239 .WillOnce(Return(pw::Status::Internal()));
240 EXPECT_FALSE(mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0).ok());
241 }
242
TEST_F(MessageHubManagerTest,OnClientDeath)243 TEST_F(MessageHubManagerTest, OnClientDeath) {
244 bool unlinked = false;
245 reinit([&unlinked](std::function<pw::Result<int64_t>()> fn) {
246 auto statusOrHubId = fn();
247 ASSERT_TRUE(statusOrHubId.ok());
248 EXPECT_EQ(*statusOrHubId, kHub1Id);
249 unlinked = true;
250 });
251
252 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
253 EXPECT_CALL(*mDeathRecipient, linkCallback(MatchSp(mHostHubCb), _))
254 .WillOnce(Return(pw::OkStatus()));
255 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
256 EXPECT_EQ(mHostHub->id(), kHub1Id);
257 EXPECT_EQ(mHostHub, mManager->getHostHub(kHub1Id));
258
259 EXPECT_CALL(*mDeathRecipient, unlinkCallback(_, _)).Times(0);
260 onClientDeath(mHostHub);
261 EXPECT_THAT(mManager->getHostHub(kHub1Id), IsNull());
262 }
263
TEST_F(MessageHubManagerTest,OnClientDeathAfterUnregister)264 TEST_F(MessageHubManagerTest, OnClientDeathAfterUnregister) {
265 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
266 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
267 mHostHub->unregister();
268 onClientDeath(mHostHub);
269 }
270
TEST_F(MessageHubManagerTest,InitAndClearEmbeddedState)271 TEST_F(MessageHubManagerTest, InitAndClearEmbeddedState) {
272 mManager->addEmbeddedHub(kHub1Info);
273 EXPECT_THAT(mManager->getEmbeddedHubs(), IsEmpty());
274
275 mManager->initEmbeddedState();
276 mManager->addEmbeddedHub(kHub1Info);
277 EXPECT_THAT(mManager->getEmbeddedHubs(),
278 UnorderedElementsAreArray({kHub1Info}));
279
280 mManager->clearEmbeddedState();
281 EXPECT_THAT(mManager->getEmbeddedHubs(), IsEmpty());
282 }
283
TEST_F(MessageHubManagerTest,AddAndRemoveEmbeddedHub)284 TEST_F(MessageHubManagerTest, AddAndRemoveEmbeddedHub) {
285 mManager->initEmbeddedState();
286 mManager->addEmbeddedHub(kHub1Info);
287 EXPECT_THAT(mManager->getEmbeddedHubs(),
288 UnorderedElementsAreArray({kHub1Info}));
289
290 mManager->removeEmbeddedHub(kHub1Id);
291 EXPECT_THAT(mManager->getEmbeddedHubs(), IsEmpty());
292 }
293
294 MATCHER_P(MatchEndpointInfo, info, "Matches an EndpointInfo") {
295 if (arg.id.id != info.id.id || arg.id.hubId != info.id.hubId ||
296 arg.services.size() != info.services.size()) {
297 return false;
298 }
299 for (size_t i = 0; i < arg.services.size(); ++i) {
300 if (arg.services[i].serviceDescriptor !=
301 info.services[i].serviceDescriptor) {
302 return false;
303 }
304 }
305 return true;
306 }
307
TEST_F(MessageHubManagerTest,AddAndRemoveEmbeddedEndpoint)308 TEST_F(MessageHubManagerTest, AddAndRemoveEmbeddedEndpoint) {
309 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
310 auto hostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
311 mManager->initEmbeddedState();
312 mManager->addEmbeddedHub(kHub2Info);
313
314 mManager->addEmbeddedEndpoint({.id = kEndpoint2_2Info.id});
315 EXPECT_THAT(mManager->getEmbeddedEndpoints(), IsEmpty());
316
317 mManager->addEmbeddedEndpointService(kEndpoint2_2Info.id,
318 kEndpoint2_2Info.services[0]);
319 EXPECT_THAT(mManager->getEmbeddedEndpoints(), IsEmpty());
320
321 EXPECT_CALL(*mHostHubCb, onEndpointStarted(UnorderedElementsAreArray(
322 {MatchEndpointInfo(kEndpoint2_2Info)})));
323 mManager->setEmbeddedEndpointReady(kEndpoint2_2Info.id);
324 EXPECT_THAT(mManager->getEmbeddedEndpoints(),
325 UnorderedElementsAreArray({MatchEndpointInfo(kEndpoint2_2Info)}));
326
327 EXPECT_CALL(*mHostHubCb, onEndpointStopped(
328 UnorderedElementsAreArray({kEndpoint2_2Info.id}),
329 Reason::ENDPOINT_GONE));
330 mManager->removeEmbeddedEndpoint(kEndpoint2_2Info.id);
331 EXPECT_THAT(mManager->getEmbeddedEndpoints(), IsEmpty());
332 }
333
TEST_F(MessageHubManagerTest,RemovingEmbeddedHubRemovesEndpoints)334 TEST_F(MessageHubManagerTest, RemovingEmbeddedHubRemovesEndpoints) {
335 mManager->initEmbeddedState();
336 mManager->addEmbeddedHub(kHub2Info);
337 mManager->addEmbeddedEndpoint(kEndpoint2_1Info);
338 mManager->setEmbeddedEndpointReady(kEndpoint2_1Info.id);
339 mManager->addEmbeddedEndpoint(kEndpoint2_2Info);
340 mManager->setEmbeddedEndpointReady(kEndpoint2_2Info.id);
341 EXPECT_THAT(mManager->getEmbeddedEndpoints(),
342 UnorderedElementsAreArray({MatchEndpointInfo(kEndpoint2_1Info),
343 MatchEndpointInfo(kEndpoint2_2Info)}));
344
345 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
346 auto hostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
347 EXPECT_CALL(*mHostHubCb,
348 onEndpointStopped(UnorderedElementsAreArray(
349 {kEndpoint2_1Info.id, kEndpoint2_2Info.id}),
350 Reason::HUB_RESET));
351 mManager->removeEmbeddedHub(kHub2Id);
352 EXPECT_THAT(mManager->getEmbeddedEndpoints(), IsEmpty());
353 }
354
TEST_F(MessageHubManagerTest,AddEmbeddedEndpointForUnknownHub)355 TEST_F(MessageHubManagerTest, AddEmbeddedEndpointForUnknownHub) {
356 mManager->initEmbeddedState();
357 mManager->addEmbeddedEndpoint(kEndpoint1_1Info);
358 mManager->setEmbeddedEndpointReady(kEndpoint1_1Info.id);
359 EXPECT_THAT(mManager->getEmbeddedEndpoints(), IsEmpty());
360 }
361
TEST_F(MessageHubManagerTest,AddAndRemoveHostEndpoint)362 TEST_F(MessageHubManagerTest, AddAndRemoveHostEndpoint) {
363 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
364 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
365
366 EXPECT_TRUE(mHostHub->addEndpoint(kEndpoint1_1Info).ok());
367 EXPECT_THAT(mHostHub->getEndpoints(),
368 UnorderedElementsAreArray({kEndpoint1_1Info}));
369
370 EXPECT_TRUE(mHostHub->removeEndpoint(kEndpoint1_1Info.id).ok());
371 EXPECT_THAT(mHostHub->getEndpoints(), IsEmpty());
372 }
373
TEST_F(MessageHubManagerTest,AddDuplicateEndpoint)374 TEST_F(MessageHubManagerTest, AddDuplicateEndpoint) {
375 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
376 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
377 ASSERT_TRUE(mHostHub->addEndpoint(kEndpoint1_1Info).ok());
378 EXPECT_EQ(mHostHub->addEndpoint(kEndpoint1_1Info),
379 pw::Status::AlreadyExists());
380 }
381
TEST_F(MessageHubManagerTest,RemoveNonexistentEndpoint)382 TEST_F(MessageHubManagerTest, RemoveNonexistentEndpoint) {
383 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
384 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
385 EXPECT_EQ(mHostHub->removeEndpoint(kEndpoint1_1Info.id).status(),
386 pw::Status::NotFound());
387 }
388
TEST_F(MessageHubManagerTest,ReserveSessionIdRange)389 TEST_F(MessageHubManagerTest, ReserveSessionIdRange) {
390 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
391 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
392 std::random_device rand;
393 auto range = *mHostHub->reserveSessionIdRange(
394 std::uniform_int_distribution<size_t>(1, kSessionIdMaxRange)(rand));
395 EXPECT_THAT(range.second - range.first + 1,
396 AllOf(Ge(1), Le(kSessionIdMaxRange)));
397 }
398
TEST_F(MessageHubManagerTest,ReserveBadSessionIdRange)399 TEST_F(MessageHubManagerTest, ReserveBadSessionIdRange) {
400 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
401 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
402 EXPECT_EQ(mHostHub->reserveSessionIdRange(0).status(),
403 pw::Status::InvalidArgument());
404 EXPECT_EQ(mHostHub->reserveSessionIdRange(kSessionIdMaxRange + 1).status(),
405 pw::Status::InvalidArgument());
406 }
407
TEST_F(MessageHubManagerTest,ReserveSessionIdRangeFull)408 TEST_F(MessageHubManagerTest, ReserveSessionIdRangeFull) {
409 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
410 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
411 int iterations = (USHRT_MAX - kHostSessionIdBase + 1) / kSessionIdMaxRange;
412 for (int i = 0; i < iterations; ++i)
413 ASSERT_TRUE(mHostHub->reserveSessionIdRange(kSessionIdMaxRange).ok());
414 EXPECT_EQ(mHostHub->reserveSessionIdRange(kSessionIdMaxRange).status(),
415 pw::Status::ResourceExhausted());
416 }
417
TEST_F(MessageHubManagerTest,OpenHostSessionRequest)418 TEST_F(MessageHubManagerTest, OpenHostSessionRequest) {
419 setupDefaultHubs();
420
421 auto range = *mHostHub->reserveSessionIdRange(1);
422 EXPECT_TRUE(mHostHub
423 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
424 range.first, {}, /*hostInitiated=*/true)
425 .ok());
426 EXPECT_FALSE(mHostHub->checkSessionOpen(range.first).ok());
427 }
428
TEST_F(MessageHubManagerTest,OpenHostSessionRequestBadSessionId)429 TEST_F(MessageHubManagerTest, OpenHostSessionRequestBadSessionId) {
430 setupDefaultHubs();
431
432 auto range = *mHostHub->reserveSessionIdRange(1);
433 EXPECT_EQ(mHostHub->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
434 range.first + 1, {}, /*hostInitiated=*/true),
435 pw::Status::OutOfRange());
436 }
437
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionRequest)438 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionRequest) {
439 setupDefaultHubs();
440
441 static constexpr uint16_t kSessionId = 1;
442 std::optional<std::string> serviceDescriptor;
443 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(
444 kSessionId, kEndpoint1_1Info.id,
445 kEndpoint2_1Info.id, serviceDescriptor));
446 EXPECT_TRUE(mHostHub
447 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
448 kSessionId, {}, /*hostInitiated=*/false)
449 .ok());
450 EXPECT_FALSE(mHostHub->checkSessionOpen(kSessionId).ok());
451 }
452
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionRequestBadSessionId)453 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionRequestBadSessionId) {
454 setupDefaultHubs();
455
456 EXPECT_FALSE(mHostHub
457 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
458 kHostSessionIdBase, {},
459 /*hostInitiated=*/false)
460 .ok());
461 EXPECT_EQ(mHostHub->checkSessionOpen(kHostSessionIdBase),
462 pw::Status::NotFound());
463 }
464
TEST_F(MessageHubManagerTest,OpenSessionRequestUnknownHostEndpoint)465 TEST_F(MessageHubManagerTest, OpenSessionRequestUnknownHostEndpoint) {
466 mManager->initEmbeddedState();
467 mManager->addEmbeddedHub(kHub2Info);
468 mManager->addEmbeddedEndpoint(kEndpoint2_1Info);
469 mManager->setEmbeddedEndpointReady(kEndpoint2_1Info.id);
470 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
471 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
472
473 auto range = *mHostHub->reserveSessionIdRange(1);
474 EXPECT_EQ(mHostHub->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
475 range.first, {}, /*hostInitiated=*/true),
476 pw::Status::NotFound());
477 }
478
TEST_F(MessageHubManagerTest,OpenSessionRequestUnknownEmbeddedEndpoint)479 TEST_F(MessageHubManagerTest, OpenSessionRequestUnknownEmbeddedEndpoint) {
480 mManager->initEmbeddedState();
481 mManager->addEmbeddedHub(kHub2Info);
482 mHostHubCb = SharedRefBase::make<MockEndpointCallback>();
483 mHostHub = *mManager->createHostHub(mHostHubCb, kHub1Info, 0, 0);
484 ASSERT_TRUE(mHostHub->addEndpoint(kEndpoint1_1Info).ok());
485
486 auto range = *mHostHub->reserveSessionIdRange(1);
487 EXPECT_EQ(mHostHub->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
488 range.first, {}, /*hostInitiated=*/true),
489 pw::Status::NotFound());
490 }
491
TEST_F(MessageHubManagerTest,OpenHostSessionRequestWithService)492 TEST_F(MessageHubManagerTest, OpenHostSessionRequestWithService) {
493 setupDefaultHubs();
494
495 auto range = *mHostHub->reserveSessionIdRange(1);
496 uint16_t sessionId = range.first;
497 EXPECT_TRUE(mHostHub
498 ->openSession(kEndpoint1_2Info.id, kEndpoint2_2Info.id,
499 sessionId, kTestServiceDescriptor,
500 /*hostInitiated=*/true)
501 .ok());
502 }
503
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionRequestWithService)504 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionRequestWithService) {
505 setupDefaultHubs();
506
507 auto range = *mHostHub->reserveSessionIdRange(1);
508 uint16_t sessionId = range.first;
509 EXPECT_TRUE(mHostHub
510 ->openSession(kEndpoint1_2Info.id, kEndpoint2_2Info.id,
511 sessionId, kTestServiceDescriptor,
512 /*hostInitiated=*/true)
513 .ok());
514 }
515
TEST_F(MessageHubManagerTest,OpenSessionWithServiceHostSideDoesNotSupport)516 TEST_F(MessageHubManagerTest, OpenSessionWithServiceHostSideDoesNotSupport) {
517 setupDefaultHubs();
518
519 EXPECT_FALSE(mHostHub
520 ->openSession(kEndpoint1_1Info.id, kEndpoint2_2Info.id,
521 kHostSessionIdBase, kTestServiceDescriptor,
522 /*hostInitiated=*/true)
523 .ok());
524 }
525
TEST_F(MessageHubManagerTest,OpenSessionWithServiceEmbeddedSideDoesNotSupport)526 TEST_F(MessageHubManagerTest,
527 OpenSessionWithServiceEmbeddedSideDoesNotSupport) {
528 setupDefaultHubs();
529
530 EXPECT_FALSE(mHostHub
531 ->openSession(kEndpoint1_2Info.id, kEndpoint2_1Info.id,
532 kHostSessionIdBase, kTestServiceDescriptor,
533 /*hostInitiated=*/true)
534 .ok());
535 }
536
TEST_F(MessageHubManagerTest,OpenSessionRequestServiceSupportedButNotUsed)537 TEST_F(MessageHubManagerTest, OpenSessionRequestServiceSupportedButNotUsed) {
538 setupDefaultHubs();
539
540 std::optional<std::string> serviceDescriptor;
541 auto range = *mHostHub->reserveSessionIdRange(1);
542 uint16_t sessionId = range.first;
543 EXPECT_TRUE(mHostHub
544 ->openSession(kEndpoint1_2Info.id, kEndpoint2_2Info.id,
545 sessionId, serviceDescriptor,
546 /*hostInitiated=*/true)
547 .ok());
548 }
549
TEST_F(MessageHubManagerTest,OpenHostSessionEmbeddedEndpointAccepts)550 TEST_F(MessageHubManagerTest, OpenHostSessionEmbeddedEndpointAccepts) {
551 auto sessionId = setupDefaultHubsAndSession();
552 EXPECT_TRUE(mHostHub->checkSessionOpen(sessionId).ok());
553 }
554
TEST_F(MessageHubManagerTest,OpenHostSessionEmbeddedEndpointRejects)555 TEST_F(MessageHubManagerTest, OpenHostSessionEmbeddedEndpointRejects) {
556 setupDefaultHubs();
557 auto range = *mHostHub->reserveSessionIdRange(1);
558 ASSERT_TRUE(mHostHub
559 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
560 range.first, {}, /*hostInitiated=*/true)
561 .ok());
562
563 EXPECT_CALL(*mHostHubCb,
564 onCloseEndpointSession(
565 range.first, Reason::OPEN_ENDPOINT_SESSION_REQUEST_REJECTED));
566 EXPECT_TRUE(mManager->getHostHub(kHub1Id)
567 ->closeSession(range.first,
568 Reason::OPEN_ENDPOINT_SESSION_REQUEST_REJECTED)
569 .ok());
570 EXPECT_EQ(mHostHub->checkSessionOpen(range.first), pw::Status::NotFound());
571 }
572
TEST_F(MessageHubManagerTest,OpenHostSessionHostTriesToAck)573 TEST_F(MessageHubManagerTest, OpenHostSessionHostTriesToAck) {
574 setupDefaultHubs();
575 auto range = *mHostHub->reserveSessionIdRange(1);
576 ASSERT_TRUE(mHostHub
577 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
578 range.first, {}, /*hostInitiated=*/true)
579 .ok());
580
581 EXPECT_FALSE(mHostHub->ackSession(range.first, /*hostAcked=*/true).ok());
582 }
583
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionHostEndpointAccepts)584 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionHostEndpointAccepts) {
585 setupDefaultHubs();
586 static constexpr uint16_t kSessionId = 1;
587 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(kSessionId, _, _, _));
588 ASSERT_TRUE(mHostHub
589 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
590 kSessionId, {}, /*hostInitiated=*/false)
591 .ok());
592
593 EXPECT_TRUE(mHostHub->ackSession(kSessionId, /*hostAcked=*/true).ok());
594 EXPECT_FALSE(mHostHub->checkSessionOpen(kSessionId).ok());
595 }
596
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionMessageRouterTriesToAck)597 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionMessageRouterTriesToAck) {
598 setupDefaultHubs();
599 static constexpr uint16_t kSessionId = 1;
600 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(kSessionId, _, _, _));
601 ASSERT_TRUE(mHostHub
602 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
603 kSessionId, {}, /*hostInitiated=*/false)
604 .ok());
605
606 EXPECT_FALSE(mHostHub->ackSession(kSessionId, /*hostAcked=*/false).ok());
607 }
608
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionPrunePendingSession)609 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionPrunePendingSession) {
610 setupDefaultHubs();
611 static constexpr uint16_t kSessionId = 1;
612 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(kSessionId, _, _, _));
613 EXPECT_TRUE(mHostHub
614 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
615 kSessionId, {}, /*hostInitiated=*/false)
616 .ok());
617 EXPECT_TRUE(mHostHub->ackSession(kSessionId, /*hostAcked=*/true).ok());
618
619 EXPECT_CALL(*mHostHubCb, onCloseEndpointSession(kSessionId, _));
620 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(kSessionId, _, _, _));
621 EXPECT_TRUE(mHostHub
622 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
623 kSessionId, {}, /*hostInitiated=*/false)
624 .ok());
625 }
626
TEST_F(MessageHubManagerTest,OpenEmbeddedSessionMessageRouterAcks)627 TEST_F(MessageHubManagerTest, OpenEmbeddedSessionMessageRouterAcks) {
628 setupDefaultHubs();
629 static constexpr uint16_t kSessionId = 1;
630 EXPECT_CALL(*mHostHubCb, onEndpointSessionOpenRequest(kSessionId, _, _, _));
631 ASSERT_TRUE(mHostHub
632 ->openSession(kEndpoint1_1Info.id, kEndpoint2_1Info.id,
633 kSessionId, {}, /*hostInitiated=*/false)
634 .ok());
635 ASSERT_TRUE(mHostHub->ackSession(kSessionId, /*hostAcked=*/true).ok());
636
637 EXPECT_TRUE(mHostHub->ackSession(kSessionId, /*hostAcked=*/false).ok());
638 EXPECT_TRUE(mHostHub->checkSessionOpen(kSessionId).ok());
639 }
640
TEST_F(MessageHubManagerTest,ActiveSessionEmbeddedHubGone)641 TEST_F(MessageHubManagerTest, ActiveSessionEmbeddedHubGone) {
642 auto sessionId = setupDefaultHubsAndSession();
643
644 EXPECT_CALL(*mHostHubCb,
645 onCloseEndpointSession(sessionId, Reason::HUB_RESET));
646 EXPECT_CALL(*mHostHubCb,
647 onEndpointStopped(UnorderedElementsAreArray(
648 {kEndpoint2_1Info.id, kEndpoint2_2Info.id}),
649 Reason::HUB_RESET));
650 mManager->removeEmbeddedHub(kHub2Id);
651 EXPECT_EQ(mHostHub->checkSessionOpen(sessionId), pw::Status::NotFound());
652 }
653
TEST_F(MessageHubManagerTest,ActiveSessionEmbeddedEndpointGone)654 TEST_F(MessageHubManagerTest, ActiveSessionEmbeddedEndpointGone) {
655 auto sessionId = setupDefaultHubsAndSession();
656
657 EXPECT_CALL(*mHostHubCb,
658 onCloseEndpointSession(sessionId, Reason::ENDPOINT_GONE));
659 EXPECT_CALL(*mHostHubCb, onEndpointStopped(
660 UnorderedElementsAreArray({kEndpoint2_1Info.id}),
661 Reason::ENDPOINT_GONE));
662 mManager->removeEmbeddedEndpoint(kEndpoint2_1Info.id);
663 EXPECT_EQ(mHostHub->checkSessionOpen(sessionId), pw::Status::NotFound());
664 }
665
TEST_F(MessageHubManagerTest,ActiveSessionHostEndpointGone)666 TEST_F(MessageHubManagerTest, ActiveSessionHostEndpointGone) {
667 auto sessionId = setupDefaultHubsAndSession();
668
669 EXPECT_THAT(*mHostHub->removeEndpoint(kEndpoint1_1Info.id),
670 UnorderedElementsAreArray({sessionId}));
671 EXPECT_EQ(mHostHub->checkSessionOpen(sessionId), pw::Status::NotFound());
672 }
673
TEST_F(MessageHubManagerTest,HandleMessage)674 TEST_F(MessageHubManagerTest, HandleMessage) {
675 auto sessionId = setupDefaultHubsAndSession();
676
677 Message message{.content = {0xde, 0xad, 0xbe, 0xef}};
678 EXPECT_CALL(*mHostHubCb, onMessageReceived(sessionId, message));
679 EXPECT_TRUE(mHostHub->handleMessage(sessionId, message).ok());
680 }
681
TEST_F(MessageHubManagerTest,HandleMessageForUnknownSession)682 TEST_F(MessageHubManagerTest, HandleMessageForUnknownSession) {
683 setupDefaultHubs();
684
685 Message message{.content = {0xde, 0xad, 0xbe, 0xef}};
686 EXPECT_CALL(*mHostHubCb, onMessageReceived(_, _)).Times(0);
687 EXPECT_FALSE(mHostHub->handleMessage(1, message).ok());
688 }
689
TEST_F(MessageHubManagerTest,HandleMessageDeliveryStatus)690 TEST_F(MessageHubManagerTest, HandleMessageDeliveryStatus) {
691 auto sessionId = setupDefaultHubsAndSession();
692
693 MessageDeliveryStatus status{.errorCode = ErrorCode::TRANSIENT_ERROR};
694 EXPECT_CALL(*mHostHubCb, onMessageDeliveryStatusReceived(sessionId, status));
695 EXPECT_TRUE(mHostHub->handleMessageDeliveryStatus(sessionId, status).ok());
696 }
697
TEST_F(MessageHubManagerTest,HandleMessageDeliveryStatusForUnknownSession)698 TEST_F(MessageHubManagerTest, HandleMessageDeliveryStatusForUnknownSession) {
699 setupDefaultHubs();
700
701 MessageDeliveryStatus status{.errorCode = ErrorCode::TRANSIENT_ERROR};
702 EXPECT_CALL(*mHostHubCb, onMessageDeliveryStatusReceived(_, _)).Times(0);
703 EXPECT_FALSE(mHostHub->handleMessageDeliveryStatus(1, status).ok());
704 }
705
706 } // namespace
707 } // namespace android::hardware::contexthub::common::implementation
708