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