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