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