• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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