• 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 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