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
__anone6db12310202chre::__anone6db12310111::NanTestNanoapp59 bool (*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 void (*handleEvent)(uint32_t, uint16_t, const void *) =
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 void (*handleEvent)(uint32_t, uint16_t, const void *) =
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 void (*handleEvent)(uint32_t, uint16_t, const void *) =
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 void (*handleEvent)(uint32_t, uint16_t, const void *) =
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 void (*handleEvent)(uint32_t, uint16_t,
310 const void *) = [](uint32_t, uint16_t eventType,
311 const void *eventData) {
312 const uint32_t kSubscribeCookie = 0x10aded;
313
314 switch (eventType) {
315 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
316 auto event =
317 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
318 if (event->result.errorCode == CHRE_ERROR_NONE) {
319 TestEventQueueSingleton::get()->pushEvent(
320 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
321 }
322 break;
323 }
324
325 case CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT: {
326 auto event =
327 static_cast<const chreWifiNanDiscoveryEvent *>(eventData);
328 TestEventQueueSingleton::get()->pushEvent(
329 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event->subscribeId);
330 break;
331 }
332
333 case CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED: {
334 auto event =
335 static_cast<const chreWifiNanSessionTerminatedEvent *>(eventData);
336 TestEventQueueSingleton::get()->pushEvent(
337 CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, event->id);
338 break;
339 }
340
341 case CHRE_EVENT_TEST_EVENT: {
342 auto event = static_cast<const TestEvent *>(eventData);
343 switch (event->type) {
344 case NAN_SUBSCRIBE: {
345 auto config = (chreWifiNanSubscribeConfig *)(event->data);
346 const bool success =
347 chreWifiNanSubscribe(config, &kSubscribeCookie);
348 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE, success);
349 break;
350 }
351 }
352 }
353 }
354 };
355 };
356
357 auto app = loadNanoapp<App>();
358
359 chreWifiNanSubscribeConfig config = {
360 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
361 .service = "SomeServiceName",
362 };
363 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
364 bool success;
365 waitForEvent(NAN_SUBSCRIBE, &success);
366 EXPECT_TRUE(success);
367
368 uint32_t id;
369 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
370
371 PalNanEngineSingleton::get()->sendDiscoveryEvent(id);
372 uint32_t subscribeId;
373 waitForEvent(CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, &subscribeId);
374 EXPECT_EQ(subscribeId, id);
375
376 PalNanEngineSingleton::get()->onServiceTerminated(id);
377 uint32_t terminatedId;
378 waitForEvent(CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, &terminatedId);
379 EXPECT_EQ(terminatedId, id);
380 }
381
382 /**
383 * Test that a service lost event is received upon the Pal NAN engine 'losing'
384 * a discovered service.
385 */
TEST_F(TestBase,WifiNanServiceLostTest)386 TEST_F(TestBase, WifiNanServiceLostTest) {
387 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
388
389 struct Ids {
390 uint32_t subscribe;
391 uint32_t publish;
392 };
393
394 struct App : public NanTestNanoapp {
395 void (*handleEvent)(uint32_t, uint16_t, const void *) =
396 [](uint32_t, uint16_t eventType, const void *eventData) {
397 const uint32_t kSubscribeCookie = 0x10aded;
398
399 switch (eventType) {
400 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
401 auto event =
402 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
403 if (event->result.errorCode == CHRE_ERROR_NONE) {
404 TestEventQueueSingleton::get()->pushEvent(
405 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
406 }
407 break;
408 }
409
410 case CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT: {
411 auto event =
412 static_cast<const chreWifiNanDiscoveryEvent *>(eventData);
413 TestEventQueueSingleton::get()->pushEvent(
414 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event->subscribeId);
415 break;
416 }
417
418 case CHRE_EVENT_WIFI_NAN_SESSION_LOST: {
419 auto event =
420 static_cast<const chreWifiNanSessionLostEvent *>(eventData);
421 Ids ids = {.subscribe = event->id, .publish = event->peerId};
422 TestEventQueueSingleton::get()->pushEvent(
423 CHRE_EVENT_WIFI_NAN_SESSION_LOST, ids);
424 break;
425 }
426
427 case CHRE_EVENT_TEST_EVENT: {
428 auto event = static_cast<const TestEvent *>(eventData);
429 switch (event->type) {
430 case NAN_SUBSCRIBE: {
431 auto config = (chreWifiNanSubscribeConfig *)(event->data);
432 const bool success =
433 chreWifiNanSubscribe(config, &kSubscribeCookie);
434 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
435 success);
436 break;
437 }
438 }
439 }
440 }
441 };
442 };
443
444 auto app = loadNanoapp<App>();
445
446 chreWifiNanSubscribeConfig config = {
447 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
448 .service = "SomeServiceName",
449 };
450 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
451 bool success;
452 waitForEvent(NAN_SUBSCRIBE, &success);
453 EXPECT_TRUE(success);
454
455 uint32_t id;
456 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
457
458 PalNanEngineSingleton::get()->sendDiscoveryEvent(id);
459 uint32_t subscribeId;
460 waitForEvent(CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, &subscribeId);
461 EXPECT_EQ(subscribeId, id);
462
463 PalNanEngineSingleton::get()->onServiceLost(subscribeId, id);
464 Ids ids;
465 waitForEvent(CHRE_EVENT_WIFI_NAN_SESSION_LOST, &ids);
466 EXPECT_EQ(ids.subscribe, id);
467 EXPECT_EQ(ids.publish, id);
468 }
469
470 /**
471 * Test that a ranging event is received upon requesting NAN range
472 * measurements.
473 */
TEST_F(TestBase,WifiNanRangingTest)474 TEST_F(TestBase, WifiNanRangingTest) {
475 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
476 CREATE_CHRE_TEST_EVENT(REQUEST_RANGING, 1);
477
478 struct App : public NanTestNanoapp {
479 void (*handleEvent)(uint32_t, uint16_t, const void *) =
480 [](uint32_t, uint16_t eventType, const void *eventData) {
481 const uint32_t kRangingCookie = 0xfa11;
482 const uint32_t kSubscribeCookie = 0x10aded;
483
484 switch (eventType) {
485 case CHRE_EVENT_WIFI_ASYNC_RESULT: {
486 auto *event = static_cast<const chreAsyncResult *>(eventData);
487 if (event->requestType == CHRE_WIFI_REQUEST_TYPE_RANGING) {
488 TestEventQueueSingleton::get()->pushEvent(
489 CHRE_EVENT_WIFI_ASYNC_RESULT);
490 }
491 break;
492 }
493
494 case CHRE_EVENT_WIFI_RANGING_RESULT: {
495 TestEventQueueSingleton::get()->pushEvent(
496 CHRE_EVENT_WIFI_RANGING_RESULT);
497 break;
498 }
499
500 case CHRE_EVENT_TEST_EVENT: {
501 auto event = static_cast<const TestEvent *>(eventData);
502 switch (event->type) {
503 case NAN_SUBSCRIBE: {
504 auto config = (chreWifiNanSubscribeConfig *)(event->data);
505 const bool success =
506 chreWifiNanSubscribe(config, &kSubscribeCookie);
507 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE,
508 success);
509 break;
510 }
511
512 case REQUEST_RANGING: {
513 uint8_t fakeMacAddress[CHRE_WIFI_BSSID_LEN] = {0x1, 0x2, 0x3,
514 0x4, 0x5, 0x6};
515 struct chreWifiNanRangingParams fakeRangingParams;
516 std::memcpy(fakeRangingParams.macAddress, fakeMacAddress,
517 CHRE_WIFI_BSSID_LEN);
518 const bool success = chreWifiNanRequestRangingAsync(
519 &fakeRangingParams, &kRangingCookie);
520 TestEventQueueSingleton::get()->pushEvent(REQUEST_RANGING,
521 success);
522 break;
523 }
524 }
525 }
526 }
527 };
528 };
529
530 auto app = loadNanoapp<App>();
531 bool success;
532
533 chreWifiNanSubscribeConfig config = {
534 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
535 .service = "SomeServiceName",
536 };
537 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
538 waitForEvent(NAN_SUBSCRIBE, &success);
539 EXPECT_TRUE(success);
540
541 sendEventToNanoapp(app, REQUEST_RANGING, config);
542 waitForEvent(REQUEST_RANGING, &success);
543 EXPECT_TRUE(success);
544 waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);
545 waitForEvent(CHRE_EVENT_WIFI_RANGING_RESULT);
546 }
547
TEST_F(TestBase,WifiNanSubscribeCancelTest)548 TEST_F(TestBase, WifiNanSubscribeCancelTest) {
549 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE, 0);
550 CREATE_CHRE_TEST_EVENT(NAN_SUBSCRIBE_DONE, 1);
551 CREATE_CHRE_TEST_EVENT(NAN_UNSUBSCRIBE, 2);
552 CREATE_CHRE_TEST_EVENT(NAN_UNSUBSCRIBE_DONE, 3);
553
554 struct App : public NanTestNanoapp {
555 void (*handleEvent)(uint32_t, uint16_t, const void *) =
556 [](uint32_t, uint16_t eventType, const void *eventData) {
557 const uint32_t kSubscribeCookie = 0x10aded;
558
559 switch (eventType) {
560 case CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT: {
561 auto event =
562 static_cast<const chreWifiNanIdentifierEvent *>(eventData);
563 if (event->result.errorCode == CHRE_ERROR_NONE) {
564 TestEventQueueSingleton::get()->pushEvent(
565 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event->id);
566 }
567 break;
568 }
569
570 case CHRE_EVENT_TEST_EVENT: {
571 auto event = static_cast<const TestEvent *>(eventData);
572 switch (event->type) {
573 case NAN_SUBSCRIBE: {
574 auto config = (chreWifiNanSubscribeConfig *)(event->data);
575 bool success =
576 chreWifiNanSubscribe(config, &kSubscribeCookie);
577 TestEventQueueSingleton::get()->pushEvent(NAN_SUBSCRIBE_DONE,
578 success);
579 break;
580 }
581 case NAN_UNSUBSCRIBE: {
582 auto *id = static_cast<uint32_t *>(event->data);
583 bool success = chreWifiNanSubscribeCancel(*id);
584 // Note that since we're 'simulating' NAN functionality here,
585 // the async subscribe cancel event will be handled before
586 // the return event below is posted. For a real on-device (or
587 // non-simulated) test, this won't be the case, and care must
588 // be taken to handle the asynchronicity appropriately.
589 TestEventQueueSingleton::get()->pushEvent(
590 NAN_UNSUBSCRIBE_DONE, success);
591 break;
592 }
593 }
594 }
595 }
596 };
597 };
598
599 auto app = loadNanoapp<App>();
600
601 chreWifiNanSubscribeConfig config = {
602 .subscribeType = CHRE_WIFI_NAN_SUBSCRIBE_TYPE_PASSIVE,
603 .service = "SomeServiceName",
604 };
605
606 bool success = false;
607 sendEventToNanoapp(app, NAN_SUBSCRIBE, config);
608 waitForEvent(NAN_SUBSCRIBE_DONE, &success);
609 ASSERT_TRUE(success);
610
611 uint32_t id;
612 waitForEvent(CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, &id);
613
614 auto &wifiRequestManager =
615 EventLoopManagerSingleton::get()->getWifiRequestManager();
616 EXPECT_EQ(wifiRequestManager.getNumNanSubscriptions(), 1);
617
618 success = false;
619 sendEventToNanoapp(app, NAN_UNSUBSCRIBE, id);
620 waitForEvent(NAN_UNSUBSCRIBE_DONE, &success);
621 ASSERT_TRUE(success);
622 EXPECT_EQ(wifiRequestManager.getNumNanSubscriptions(), 0);
623 }
624
625 } // anonymous namespace
626 } // namespace chre
627