1 /*
2 * Copyright (C) 2022 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 <cstdint>
18 #include "chre/common.h"
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/core/settings.h"
21 #include "chre/platform/linux/pal_nan.h"
22 #include "chre/platform/log.h"
23 #include "chre/util/system/napp_permissions.h"
24 #include "chre_api/chre/event.h"
25 #include "chre_api/chre/wifi.h"
26
27 #include "gtest/gtest.h"
28 #include "test_base.h"
29 #include "test_event_queue.h"
30 #include "test_util.h"
31
32 /**
33 * Simulation to test WiFi NAN functionality in CHRE.
34 *
35 * The test works as follows:
36 * - A test nanoapp starts by requesting NAN subscriptions, with random
37 * service specific information. It also requests NAN ranging measurements
38 * if the test desires it. The Linux WiFi PAL has hooks and flags that
39 * instruct it to cover various test cases (fail subscribe, terminate
40 * service, etc.), to enable testing of all NAN events that CHRE is
41 * expected to propagate. These flags should be set before startTestNanoapping
42 * the test nanoapp.
43 *
44 * - The test fails (times out) if any of the events are not sent by CHRE.
45 */
46
47 namespace chre {
48 namespace {
49
50 /**
51 * Common settings for test nanoapps.
52 *
53 * - Grant WiFi permissions,
54 * - Initialize the WiFi state in start.
55 */
56 struct NanTestNanoapp : public TestNanoapp {
57 uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
58
__anonb3af7b0a0202chre::__anonb3af7b0a0111::NanTestNanoapp59 decltype(nanoappStart) *start = []() {
60 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
61 Setting::WIFI_AVAILABLE, true /* enabled */);
62 PalNanEngineSingleton::get()->setFlags(PalNanEngine::Flags::NONE);
63 return true;
64 };
65 };
66
67 /**
68 * Test that an async error is received if NAN operations are attempted when
69 * the WiFi setting is disabled.
70 */
TEST_F(TestBase,WifiNanDisabledViaSettings)71 TEST_F(TestBase, WifiNanDisabledViaSettings) {
72 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
73
74 struct App : public NanTestNanoapp {
75 decltype(nanoappHandleEvent) *handleEvent =
76 [](uint32_t, uint16_t eventType, const void *eventData) {
77 constexpr uint32_t kSubscribeCookie = 0x10aded;
78
79 switch (eventType) {
80 case CHRE_EVENT_WIFI_ASYNC_RESULT: {
81 auto *event = static_cast<const chreAsyncResult *>(eventData);
82 if (event->requestType == CHRE_WIFI_REQUEST_TYPE_NAN_SUBSCRIBE) {
83 ASSERT_EQ(event->errorCode, CHRE_ERROR_FUNCTION_DISABLED);
84 TestEventQueueSingleton::get()->pushEvent(
85 CHRE_EVENT_WIFI_ASYNC_RESULT);
86 }
87 break;
88 }
89
90 case CHRE_EVENT_TEST_EVENT: {
91 auto event = static_cast<const TestEvent *>(eventData);
92 switch (event->type) {
93 case NAN_SUBSCRIBE: {
94 auto config = (chreWifiNanSubscribeConfig *)(event->data);
95 chreWifiNanSubscribe(config, &kSubscribeCookie);
96 break;
97 }
98 }
99 }
100 }
101 };
102 };
103
104 auto app = loadNanoapp<App>();
105
106 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
107 Setting::WIFI_AVAILABLE, false /* enabled */);
108
109 chreWifiNanSubscribeConfig config = {
110 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
111 .service = "SomeServiceName",
112 };
113 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
114 waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);
115 }
116
117 /**
118 * Test that a subscription request succeeds, and an identifier event is
119 * received with a matching cookie. Also test that a discovery event is later
120 * received, marking the completion of the subscription process.
121 */
TEST_F(TestBase,WifiNanSuccessfulSubscribe)122 TEST_F(TestBase, WifiNanSuccessfulSubscribe) {
123 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
124
125 struct App : public NanTestNanoapp {
126 decltype(nanoappHandleEvent) *handleEvent =
127 [](uint32_t, uint16_t eventType, const void *eventData) {
128 const uint32_t kSubscribeCookie = 0x10aded;
129
130 switch (eventType) {
131 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
132 auto event =
133 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
134 if (event->result.errorCode == CHRE_ERROR_NONE) {
135 TestEventQueueSingleton::get()->pushEvent(
136 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
137 }
138 break;
139 }
140
141 case CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT: {
142 auto event =
143 static_cast<const chreWifiNanDiscoveryEvent *>(eventData);
144 TestEventQueueSingleton::get()->pushEvent(
145 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event->subscribeId);
146 break;
147 }
148
149 case CHRE_EVENT_TEST_EVENT: {
150 auto event = static_cast<const TestEvent *>(eventData);
151 switch (event->type) {
152 case NAN_SUBSCRIBE: {
153 auto config = (chreWifiNanSubscribeConfig *)(event->data);
154 const bool success =
155 chreWifiNanSubscribe(config, &kSubscribeCookie);
156 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
157 success);
158 break;
159 }
160 }
161 }
162 }
163 };
164 };
165
166 auto app = loadNanoapp<App>();
167
168 chreWifiNanSubscribeConfig config = {
169 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
170 .service = "SomeServiceName",
171 };
172 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
173 bool success;
174 waitForEvent(NAN_SUBSCRIBE, &success);
175 EXPECT_TRUE(success);
176
177 uint32_t id;
178 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
179 EXPECT_TRUE(PalNanEngineSingleton::get()->isSubscriptionActive(id));
180
181 PalNanEngineSingleton::get()->sendDiscoveryEvent(id);
182 uint32_t subscribeId;
183 waitForEvent(CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, &subscribeId);
184
185 EXPECT_EQ(id, subscribeId);
186 }
187
TEST_F(TestBase,WifiNanUnsSubscribeOnNanoappUnload)188 TEST_F(TestBase, WifiNanUnsSubscribeOnNanoappUnload) {
189 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
190
191 struct App : public NanTestNanoapp {
192 decltype(nanoappHandleEvent) *handleEvent =
193 [](uint32_t, uint16_t eventType, const void *eventData) {
194 const uint32_t kSubscribeCookie = 0x10aded;
195
196 switch (eventType) {
197 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
198 auto event =
199 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
200 if (event->result.errorCode == CHRE_ERROR_NONE) {
201 TestEventQueueSingleton::get()->pushEvent(
202 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
203 }
204 break;
205 }
206
207 case CHRE_EVENT_TEST_EVENT: {
208 auto event = static_cast<const TestEvent *>(eventData);
209 switch (event->type) {
210 case NAN_SUBSCRIBE: {
211 auto config = (chreWifiNanSubscribeConfig *)(event->data);
212 const bool success =
213 chreWifiNanSubscribe(config, &kSubscribeCookie);
214 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
215 success);
216 break;
217 }
218 }
219 }
220 }
221 };
222 };
223
224 auto app = loadNanoapp<App>();
225
226 chreWifiNanSubscribeConfig config = {
227 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
228 .service = "SomeServiceName",
229 };
230 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
231 bool success;
232 waitForEvent(NAN_SUBSCRIBE, &success);
233 EXPECT_TRUE(success);
234
235 uint32_t id;
236 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
237 EXPECT_TRUE(PalNanEngineSingleton::get()->isSubscriptionActive(id));
238
239 unloadNanoapp(app);
240 EXPECT_FALSE(PalNanEngineSingleton::get()->isSubscriptionActive(id));
241 }
242
243 /**
244 * Test that a subscription request fails, and an identifier event is received
245 * with a matching cookie, indicating the reason for the error (Note that the
246 * fake PAL engine always returns the generic CHRE_ERROR as the error code,
247 * but this may vary in unsimulated scenarios).
248 */
TEST_F(TestBase,WifiNanUnuccessfulSubscribeTest)249 TEST_F(TestBase, WifiNanUnuccessfulSubscribeTest) {
250 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
251
252 struct App : public NanTestNanoapp {
253 decltype(nanoappHandleEvent) *handleEvent =
254 [](uint32_t, uint16_t eventType, const void *eventData) {
255 const uint32_t kSubscribeCookie = 0x10aded;
256
257 switch (eventType) {
258 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
259 auto event =
260 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
261 if (event->result.errorCode != CHRE_ERROR_NONE) {
262 TestEventQueueSingleton::get()->pushEvent(
263 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT);
264 }
265 break;
266 }
267
268 case CHRE_EVENT_TEST_EVENT: {
269 auto event = static_cast<const TestEvent *>(eventData);
270 switch (event->type) {
271 case NAN_SUBSCRIBE: {
272 auto config = (chreWifiNanSubscribeConfig *)(event->data);
273 const bool success =
274 chreWifiNanSubscribe(config, &kSubscribeCookie);
275 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
276 success);
277 break;
278 }
279 }
280 }
281 }
282 };
283 };
284
285 auto app = loadNanoapp<App>();
286
287 PalNanEngineSingleton::get()->setFlags(PalNanEngine::Flags::FAIL_SUBSCRIBE);
288
289 chreWifiNanSubscribeConfig config = {
290 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
291 .service = "SomeServiceName",
292 };
293 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
294 bool success;
295 waitForEvent(NAN_SUBSCRIBE, &success);
296 EXPECT_TRUE(success);
297
298 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT);
299 }
300
301 /**
302 * Test that a terminated event is received upon the Pal NAN engine
303 * terminating a discovered service.
304 */
TEST_F(TestBase,WifiNanServiceTerminatedTest)305 TEST_F(TestBase, WifiNanServiceTerminatedTest) {
306 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
307
308 struct App : public NanTestNanoapp {
309 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
310 const void *eventData) {
311 const uint32_t kSubscribeCookie = 0x10aded;
312
313 switch (eventType) {
314 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
315 auto event =
316 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
317 if (event->result.errorCode == CHRE_ERROR_NONE) {
318 TestEventQueueSingleton::get()->pushEvent(
319 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
320 }
321 break;
322 }
323
324 case CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT: {
325 auto event =
326 static_cast<const chreWifiNanDiscoveryEvent *>(eventData);
327 TestEventQueueSingleton::get()->pushEvent(
328 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event->subscribeId);
329 break;
330 }
331
332 case CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED: {
333 auto event =
334 static_cast<const chreWifiNanSessionTerminatedEvent *>(eventData);
335 TestEventQueueSingleton::get()->pushEvent(
336 CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, event->id);
337 break;
338 }
339
340 case CHRE_EVENT_TEST_EVENT: {
341 auto event = static_cast<const TestEvent *>(eventData);
342 switch (event->type) {
343 case NAN_SUBSCRIBE: {
344 auto config = (chreWifiNanSubscribeConfig *)(event->data);
345 const bool success =
346 chreWifiNanSubscribe(config, &kSubscribeCookie);
347 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE, success);
348 break;
349 }
350 }
351 }
352 }
353 };
354 };
355
356 auto app = loadNanoapp<App>();
357
358 chreWifiNanSubscribeConfig config = {
359 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
360 .service = "SomeServiceName",
361 };
362 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
363 bool success;
364 waitForEvent(NAN_SUBSCRIBE, &success);
365 EXPECT_TRUE(success);
366
367 uint32_t id;
368 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
369
370 PalNanEngineSingleton::get()->sendDiscoveryEvent(id);
371 uint32_t subscribeId;
372 waitForEvent(CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, &subscribeId);
373 EXPECT_EQ(subscribeId, id);
374
375 PalNanEngineSingleton::get()->onServiceTerminated(id);
376 uint32_t terminatedId;
377 waitForEvent(CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, &terminatedId);
378 EXPECT_EQ(terminatedId, id);
379 }
380
381 /**
382 * Test that a service lost event is received upon the Pal NAN engine 'losing'
383 * a discovered service.
384 */
TEST_F(TestBase,WifiNanServiceLostTest)385 TEST_F(TestBase, WifiNanServiceLostTest) {
386 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
387
388 struct Ids {
389 uint32_t subscribe;
390 uint32_t publish;
391 };
392
393 struct App : public NanTestNanoapp {
394 decltype(nanoappHandleEvent) *handleEvent =
395 [](uint32_t, uint16_t eventType, const void *eventData) {
396 const uint32_t kSubscribeCookie = 0x10aded;
397
398 switch (eventType) {
399 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
400 auto event =
401 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
402 if (event->result.errorCode == CHRE_ERROR_NONE) {
403 TestEventQueueSingleton::get()->pushEvent(
404 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
405 }
406 break;
407 }
408
409 case CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT: {
410 auto event =
411 static_cast<const chreWifiNanDiscoveryEvent *>(eventData);
412 TestEventQueueSingleton::get()->pushEvent(
413 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event->subscribeId);
414 break;
415 }
416
417 case CHRE_EVENT_WIFI_NAN_SESSION_LOST: {
418 auto event =
419 static_cast<const chreWifiNanSessionLostEvent *>(eventData);
420 Ids ids = {.subscribe = event->id, .publish = event->peerId};
421 TestEventQueueSingleton::get()->pushEvent(
422 CHRE_EVENT_WIFI_NAN_SESSION_LOST, ids);
423 break;
424 }
425
426 case CHRE_EVENT_TEST_EVENT: {
427 auto event = static_cast<const TestEvent *>(eventData);
428 switch (event->type) {
429 case NAN_SUBSCRIBE: {
430 auto config = (chreWifiNanSubscribeConfig *)(event->data);
431 const bool success =
432 chreWifiNanSubscribe(config, &kSubscribeCookie);
433 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
434 success);
435 break;
436 }
437 }
438 }
439 }
440 };
441 };
442
443 auto app = loadNanoapp<App>();
444
445 chreWifiNanSubscribeConfig config = {
446 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
447 .service = "SomeServiceName",
448 };
449 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
450 bool success;
451 waitForEvent(NAN_SUBSCRIBE, &success);
452 EXPECT_TRUE(success);
453
454 uint32_t id;
455 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
456
457 PalNanEngineSingleton::get()->sendDiscoveryEvent(id);
458 uint32_t subscribeId;
459 waitForEvent(CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, &subscribeId);
460 EXPECT_EQ(subscribeId, id);
461
462 PalNanEngineSingleton::get()->onServiceLost(subscribeId, id);
463 Ids ids;
464 waitForEvent(CHRE_EVENT_WIFI_NAN_SESSION_LOST, &ids);
465 EXPECT_EQ(ids.subscribe, id);
466 EXPECT_EQ(ids.publish, id);
467 }
468
469 /**
470 * Test that a ranging event is received upon requesting NAN range
471 * measurements.
472 */
TEST_F(TestBase,WifiNanRangingTest)473 TEST_F(TestBase, WifiNanRangingTest) {
474 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
475 CREATE_CHRE_TEST_EVENT(REQUEST_RANGING, 1);
476
477 struct App : public NanTestNanoapp {
478 decltype(nanoappHandleEvent) *handleEvent =
479 [](uint32_t, uint16_t eventType, const void *eventData) {
480 const uint32_t kRangingCookie = 0xfa11;
481 const uint32_t kSubscribeCookie = 0x10aded;
482
483 switch (eventType) {
484 case CHRE_EVENT_WIFI_ASYNC_RESULT: {
485 auto *event = static_cast<const chreAsyncResult *>(eventData);
486 if (event->requestType == CHRE_WIFI_REQUEST_TYPE_RANGING) {
487 TestEventQueueSingleton::get()->pushEvent(
488 CHRE_EVENT_WIFI_ASYNC_RESULT);
489 }
490 break;
491 }
492
493 case CHRE_EVENT_WIFI_RANGING_RESULT: {
494 TestEventQueueSingleton::get()->pushEvent(
495 CHRE_EVENT_WIFI_RANGING_RESULT);
496 break;
497 }
498
499 case CHRE_EVENT_TEST_EVENT: {
500 auto event = static_cast<const TestEvent *>(eventData);
501 switch (event->type) {
502 case NAN_SUBSCRIBE: {
503 auto config = (chreWifiNanSubscribeConfig *)(event->data);
504 const bool success =
505 chreWifiNanSubscribe(config, &kSubscribeCookie);
506 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
507 success);
508 break;
509 }
510
511 case REQUEST_RANGING: {
512 uint8_t fakeMacAddress[CHRE_WIFI_BSSID_LEN] = {0x1, 0x2, 0x3,
513 0x4, 0x5, 0x6};
514 struct chreWifiNanRangingParams fakeRangingParams;
515 std::memcpy(fakeRangingParams.macAddress, fakeMacAddress,
516 CHRE_WIFI_BSSID_LEN);
517 const bool success = chreWifiNanRequestRangingAsync(
518 &fakeRangingParams, &kRangingCookie);
519 TestEventQueueSingleton::get()->pushEvent(REQUEST_RANGING,
520 success);
521 break;
522 }
523 }
524 }
525 }
526 };
527 };
528
529 auto app = loadNanoapp<App>();
530 bool success;
531
532 chreWifiNanSubscribeConfig config = {
533 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
534 .service = "SomeServiceName",
535 };
536 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
537 waitForEvent(NAN_SUBSCRIBE, &success);
538 EXPECT_TRUE(success);
539
540 sendEventToNanoapp(app, REQUEST_RANGING, config);
541 waitForEvent(REQUEST_RANGING, &success);
542 EXPECT_TRUE(success);
543 waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);
544 waitForEvent(CHRE_EVENT_WIFI_RANGING_RESULT);
545 }
546
TEST_F(TestBase,WifiNanSubscribeCancelTest)547 TEST_F(TestBase, WifiNanSubscribeCancelTest) {
548 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
549 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE_DONE, 1);
550 CREATE_CHRE_TEST_EVENT(NAN_UNSUBSCRIBE, 2);
551 CREATE_CHRE_TEST_EVENT(NAN_UNSUBSCRIBE_DONE, 3);
552
553 struct App : public NanTestNanoapp {
554 decltype(nanoappHandleEvent) *handleEvent =
555 [](uint32_t, uint16_t eventType, const void *eventData) {
556 const uint32_t kSubscribeCookie = 0x10aded;
557
558 switch (eventType) {
559 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
560 auto event =
561 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
562 if (event->result.errorCode == CHRE_ERROR_NONE) {
563 TestEventQueueSingleton::get()->pushEvent(
564 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
565 }
566 break;
567 }
568
569 case CHRE_EVENT_TEST_EVENT: {
570 auto event = static_cast<const TestEvent *>(eventData);
571 switch (event->type) {
572 case NAN_SUBSCRIBE: {
573 auto config = (chreWifiNanSubscribeConfig *)(event->data);
574 bool success =
575 chreWifiNanSubscribe(config, &kSubscribeCookie);
576 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE_DONE,
577 success);
578 break;
579 }
580 case NAN_UNSUBSCRIBE: {
581 auto *id = static_cast<uint32_t *>(event->data);
582 bool success = chreWifiNanSubscribeCancel(*id);
583 // Note that since we're 'simulating' NAN functionality here,
584 // the async subscribe cancel event will be handled before
585 // the return event below is posted. For a real on-device (or
586 // non-simulated) test, this won't be the case, and care must
587 // be taken to handle the asynchronicity appropriately.
588 TestEventQueueSingleton::get()->pushEvent(
589 NAN_UNSUBSCRIBE_DONE, success);
590 break;
591 }
592 }
593 }
594 }
595 };
596 };
597
598 auto app = loadNanoapp<App>();
599
600 chreWifiNanSubscribeConfig config = {
601 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
602 .service = "SomeServiceName",
603 };
604
605 bool success = false;
606 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
607 waitForEvent(NAN_SUBSCRIBE_DONE, &success);
608 ASSERT_TRUE(success);
609
610 uint32_t id;
611 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
612
613 auto &wifiRequestManager =
614 EventLoopManagerSingleton::get()->getWifiRequestManager();
615 EXPECT_EQ(wifiRequestManager.getNumNanSubscriptions(), 1);
616
617 success = false;
618 sendEventToNanoapp(app, NAN_UNSUBSCRIBE, id);
619 waitForEvent(NAN_UNSUBSCRIBE_DONE, &success);
620 ASSERT_TRUE(success);
621 // TODO(b/272351526): consider adding an async result event to catch when the
622 // unsubscribe has finished
623 // EXPECT_EQ(wifiRequestManager.getNumNanSubscriptions(), 0);
624 }
625
626 } // anonymous namespace
627 } // namespace chre
628