• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "chre/common.h"
18 #include "inc/test_util.h"
19 #include "test_base.h"
20 
21 #include <gtest/gtest.h>
22 #include <cstdint>
23 
24 #include "chre/core/event_loop_manager.h"
25 #include "chre/core/settings.h"
26 #include "chre/platform/fatal_error.h"
27 #include "chre/platform/linux/pal_ble.h"
28 #include "chre/util/dynamic_vector.h"
29 #include "chre_api/chre/ble.h"
30 #include "chre_api/chre/user_settings.h"
31 #include "test_util.h"
32 
33 namespace chre {
34 
35 namespace {
36 
37 /**
38  * This test verifies that a nanoapp can query for BLE capabilities and filter
39  * capabilities. Note that a nanoapp does not require BLE permissions to use
40  * these APIs.
41  */
TEST_F(TestBase,BleCapabilitiesTest)42 TEST_F(TestBase, BleCapabilitiesTest) {
43   CREATE_CHRE_TEST_EVENT(GET_CAPABILITIES, 0);
44   CREATE_CHRE_TEST_EVENT(GET_FILTER_CAPABILITIES, 1);
45 
46   struct App : public TestNanoapp {
47     uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
48 
49     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
50                                                    const void *eventData) {
51       switch (eventType) {
52         case CHRE_EVENT_TEST_EVENT: {
53           auto event = static_cast<const TestEvent *>(eventData);
54           switch (event->type) {
55             case GET_CAPABILITIES: {
56               TestEventQueueSingleton::get()->pushEvent(
57                   GET_CAPABILITIES, chreBleGetCapabilities());
58               break;
59             }
60 
61             case GET_FILTER_CAPABILITIES: {
62               TestEventQueueSingleton::get()->pushEvent(
63                   GET_FILTER_CAPABILITIES, chreBleGetFilterCapabilities());
64               break;
65             }
66           }
67         }
68       }
69     };
70   };
71 
72   auto app = loadNanoapp<App>();
73 
74   uint32_t capabilities;
75   sendEventToNanoapp(app, GET_CAPABILITIES);
76   waitForEvent(GET_CAPABILITIES, &capabilities);
77   ASSERT_EQ(capabilities, CHRE_BLE_CAPABILITIES_SCAN |
78                               CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING |
79                               CHRE_BLE_CAPABILITIES_SCAN_FILTER_BEST_EFFORT);
80 
81   sendEventToNanoapp(app, GET_FILTER_CAPABILITIES);
82   waitForEvent(GET_FILTER_CAPABILITIES, &capabilities);
83   ASSERT_EQ(capabilities, CHRE_BLE_FILTER_CAPABILITIES_RSSI |
84                               CHRE_BLE_FILTER_CAPABILITIES_SERVICE_DATA);
85 }
86 
87 struct BleTestNanoapp : public TestNanoapp {
88   uint32_t perms = NanoappPermissions::CHRE_PERMS_BLE;
89 
__anon4ce931120302chre::__anon4ce931120111::BleTestNanoapp90   decltype(nanoappStart) *start = []() {
91     chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
92                                    true /* enable */);
93     return true;
94   };
95 
__anon4ce931120402chre::__anon4ce931120111::BleTestNanoapp96   decltype(nanoappEnd) *end = []() {
97     chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
98                                    false /* enable */);
99   };
100 };
101 
102 /**
103  * This test validates the case in which a nanoapp starts a scan, receives
104  * at least one advertisement event, and stops a scan.
105  */
TEST_F(TestBase,BleSimpleScanTest)106 TEST_F(TestBase, BleSimpleScanTest) {
107   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
108   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
109   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
110   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
111 
112   struct App : public BleTestNanoapp {
113     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
114                                                    const void *eventData) {
115       switch (eventType) {
116         case CHRE_EVENT_BLE_ASYNC_RESULT: {
117           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
118           if (event->errorCode == CHRE_ERROR_NONE) {
119             uint16_t type =
120                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
121                     ? SCAN_STARTED
122                     : SCAN_STOPPED;
123             TestEventQueueSingleton::get()->pushEvent(type);
124           }
125           break;
126         }
127 
128         case CHRE_EVENT_BLE_ADVERTISEMENT: {
129           TestEventQueueSingleton::get()->pushEvent(
130               CHRE_EVENT_BLE_ADVERTISEMENT);
131           break;
132         }
133 
134         case CHRE_EVENT_TEST_EVENT: {
135           auto event = static_cast<const TestEvent *>(eventData);
136           switch (event->type) {
137             case START_SCAN: {
138               const bool success = chreBleStartScanAsync(
139                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
140               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
141               break;
142             }
143 
144             case STOP_SCAN: {
145               const bool success = chreBleStopScanAsync();
146               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
147               break;
148             }
149           }
150           break;
151         }
152       }
153     };
154   };
155 
156   auto app = loadNanoapp<App>();
157 
158   bool success;
159   sendEventToNanoapp(app, START_SCAN);
160   waitForEvent(START_SCAN, &success);
161   EXPECT_TRUE(success);
162   waitForEvent(SCAN_STARTED);
163   ASSERT_TRUE(chrePalIsBleEnabled());
164   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
165 
166   sendEventToNanoapp(app, STOP_SCAN);
167   waitForEvent(STOP_SCAN, &success);
168   EXPECT_TRUE(success);
169   waitForEvent(SCAN_STOPPED);
170   ASSERT_FALSE(chrePalIsBleEnabled());
171 }
172 
TEST_F(TestBase,BleStopScanOnUnload)173 TEST_F(TestBase, BleStopScanOnUnload) {
174   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
175   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
176 
177   struct App : public BleTestNanoapp {
178     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
179                                                    const void *eventData) {
180       switch (eventType) {
181         case CHRE_EVENT_BLE_ASYNC_RESULT: {
182           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
183           if (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN &&
184               event->errorCode == CHRE_ERROR_NONE) {
185             TestEventQueueSingleton::get()->pushEvent(SCAN_STARTED);
186           }
187           break;
188         }
189 
190         case CHRE_EVENT_TEST_EVENT: {
191           auto event = static_cast<const TestEvent *>(eventData);
192           switch (event->type) {
193             case START_SCAN: {
194               const bool success = chreBleStartScanAsync(
195                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
196               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
197               break;
198             }
199           }
200           break;
201         }
202       }
203     };
204   };
205 
206   auto app = loadNanoapp<App>();
207   bool success;
208 
209   sendEventToNanoapp(app, START_SCAN);
210   waitForEvent(START_SCAN, &success);
211   EXPECT_TRUE(success);
212   waitForEvent(SCAN_STARTED);
213   ASSERT_TRUE(chrePalIsBleEnabled());
214 
215   unloadNanoapp(app);
216   ASSERT_FALSE(chrePalIsBleEnabled());
217 }
218 
219 /**
220  * This test validates that a nanoapp can start a scan twice and the platform
221  * will be enabled.
222  */
TEST_F(TestBase,BleStartTwiceScanTest)223 TEST_F(TestBase, BleStartTwiceScanTest) {
224   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
225   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
226   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
227   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
228 
229   struct App : public BleTestNanoapp {
230     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
231                                                    const void *eventData) {
232       switch (eventType) {
233         case CHRE_EVENT_BLE_ASYNC_RESULT: {
234           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
235           if (event->errorCode == CHRE_ERROR_NONE) {
236             uint16_t type =
237                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
238                     ? SCAN_STARTED
239                     : SCAN_STOPPED;
240             TestEventQueueSingleton::get()->pushEvent(type);
241           }
242           break;
243         }
244 
245         case CHRE_EVENT_BLE_ADVERTISEMENT: {
246           TestEventQueueSingleton::get()->pushEvent(
247               CHRE_EVENT_BLE_ADVERTISEMENT);
248           break;
249         }
250 
251         case CHRE_EVENT_TEST_EVENT: {
252           auto event = static_cast<const TestEvent *>(eventData);
253           switch (event->type) {
254             case START_SCAN: {
255               const bool success = chreBleStartScanAsync(
256                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
257               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
258               break;
259             }
260 
261             case STOP_SCAN: {
262               const bool success = chreBleStopScanAsync();
263               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
264               break;
265             }
266           }
267         }
268       }
269     };
270   };
271 
272   auto app = loadNanoapp<App>();
273   bool success;
274 
275   sendEventToNanoapp(app, START_SCAN);
276   waitForEvent(START_SCAN, &success);
277   EXPECT_TRUE(success);
278   waitForEvent(SCAN_STARTED);
279 
280   sendEventToNanoapp(app, START_SCAN);
281   waitForEvent(START_SCAN, &success);
282   EXPECT_TRUE(success);
283   waitForEvent(SCAN_STARTED);
284   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
285 
286   sendEventToNanoapp(app, STOP_SCAN);
287   waitForEvent(STOP_SCAN, &success);
288   EXPECT_TRUE(success);
289   waitForEvent(SCAN_STOPPED);
290 }
291 
292 /**
293  * This test validates that a nanoapp can request to stop a scan twice without
294  * any ongoing scan existing. It asserts that the nanoapp did not receive any
295  * advertisment events because a scan was never started.
296  */
TEST_F(TestBase,BleStopTwiceScanTest)297 TEST_F(TestBase, BleStopTwiceScanTest) {
298   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
299   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
300   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
301 
302   struct App : public BleTestNanoapp {
303     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
304                                                    const void *eventData) {
305       switch (eventType) {
306         case CHRE_EVENT_BLE_ASYNC_RESULT: {
307           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
308           if (event->errorCode == CHRE_ERROR_NONE) {
309             uint16_t type =
310                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
311                     ? SCAN_STARTED
312                     : SCAN_STOPPED;
313             TestEventQueueSingleton::get()->pushEvent(type);
314           }
315           break;
316         }
317 
318         case CHRE_EVENT_BLE_ADVERTISEMENT: {
319           FATAL_ERROR("No advertisement expected");
320           break;
321         }
322 
323         case CHRE_EVENT_TEST_EVENT: {
324           auto event = static_cast<const TestEvent *>(eventData);
325           switch (event->type) {
326             case STOP_SCAN: {
327               const bool success = chreBleStopScanAsync();
328               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
329               break;
330             }
331           }
332         }
333       }
334     };
335   };
336 
337   auto app = loadNanoapp<App>();
338   bool success;
339 
340   sendEventToNanoapp(app, STOP_SCAN);
341   waitForEvent(STOP_SCAN, &success);
342   EXPECT_TRUE(success);
343   waitForEvent(SCAN_STOPPED);
344 
345   sendEventToNanoapp(app, STOP_SCAN);
346   waitForEvent(STOP_SCAN, &success);
347   EXPECT_TRUE(success);
348 
349   waitForEvent(SCAN_STOPPED);
350   unloadNanoapp(app);
351 }
352 
353 /**
354  * This test verifies the following BLE settings behavior:
355  * 1) Nanoapp makes BLE scan request
356  * 2) Toggle BLE setting -> disabled
357  * 3) Toggle BLE setting -> enabled.
358  * 4) Verify things resume.
359  */
TEST_F(TestBase,BleSettingChangeTest)360 TEST_F(TestBase, BleSettingChangeTest) {
361   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
362   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
363   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
364 
365   struct App : public BleTestNanoapp {
366     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
367                                                    const void *eventData) {
368       switch (eventType) {
369         case CHRE_EVENT_BLE_ASYNC_RESULT: {
370           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
371           if (event->errorCode == CHRE_ERROR_NONE) {
372             uint16_t type =
373                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
374                     ? SCAN_STARTED
375                     : SCAN_STOPPED;
376             TestEventQueueSingleton::get()->pushEvent(type);
377           }
378           break;
379         }
380 
381         case CHRE_EVENT_BLE_ADVERTISEMENT: {
382           TestEventQueueSingleton::get()->pushEvent(
383               CHRE_EVENT_BLE_ADVERTISEMENT);
384           break;
385         }
386 
387         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
388           auto *event =
389               static_cast<const chreUserSettingChangedEvent *>(eventData);
390           bool enabled =
391               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
392           TestEventQueueSingleton::get()->pushEvent(
393               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
394           break;
395         }
396 
397         case CHRE_EVENT_TEST_EVENT: {
398           auto event = static_cast<const TestEvent *>(eventData);
399           switch (event->type) {
400             case START_SCAN: {
401               const bool success = chreBleStartScanAsync(
402                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
403               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
404               break;
405             }
406           }
407         }
408       }
409     };
410   };
411 
412   auto app = loadNanoapp<App>();
413   bool success;
414 
415   sendEventToNanoapp(app, START_SCAN);
416   waitForEvent(START_SCAN, &success);
417   EXPECT_TRUE(success);
418 
419   waitForEvent(SCAN_STARTED);
420   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
421 
422   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
423       Setting::BLE_AVAILABLE, false /* enabled */);
424   bool enabled;
425   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
426   EXPECT_FALSE(enabled);
427   EXPECT_FALSE(
428       EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
429           Setting::BLE_AVAILABLE));
430   std::this_thread::sleep_for(std::chrono::milliseconds(100));
431   EXPECT_FALSE(chrePalIsBleEnabled());
432 
433   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
434       Setting::BLE_AVAILABLE, true /* enabled */);
435   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
436   EXPECT_TRUE(enabled);
437   EXPECT_TRUE(
438       EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
439           Setting::BLE_AVAILABLE));
440   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
441   EXPECT_TRUE(chrePalIsBleEnabled());
442 }
443 
444 /**
445  * Test that a nanoapp receives a function disabled error if it attempts to
446  * start a scan when the BLE setting is disabled.
447  */
TEST_F(TestBase,BleSettingDisabledStartScanTest)448 TEST_F(TestBase, BleSettingDisabledStartScanTest) {
449   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
450 
451   struct App : public BleTestNanoapp {
452     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
453                                                    const void *eventData) {
454       switch (eventType) {
455         case CHRE_EVENT_BLE_ASYNC_RESULT: {
456           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
457           if (event->errorCode == CHRE_ERROR_FUNCTION_DISABLED) {
458             TestEventQueueSingleton::get()->pushEvent(
459                 CHRE_EVENT_BLE_ASYNC_RESULT);
460           }
461           break;
462         }
463 
464         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
465           auto *event =
466               static_cast<const chreUserSettingChangedEvent *>(eventData);
467           bool enabled =
468               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
469           TestEventQueueSingleton::get()->pushEvent(
470               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
471           break;
472         }
473 
474         case CHRE_EVENT_TEST_EVENT: {
475           auto event = static_cast<const TestEvent *>(eventData);
476           switch (event->type) {
477             case START_SCAN: {
478               const bool success = chreBleStartScanAsync(
479                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
480               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
481               break;
482             }
483           }
484         }
485       }
486     };
487   };
488 
489   auto app = loadNanoapp<App>();
490 
491   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
492       Setting::BLE_AVAILABLE, false /* enable */);
493 
494   bool enabled;
495   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
496   EXPECT_FALSE(enabled);
497 
498   bool success;
499   sendEventToNanoapp(app, START_SCAN);
500   waitForEvent(START_SCAN, &success);
501   EXPECT_TRUE(success);
502   waitForEvent(CHRE_EVENT_BLE_ASYNC_RESULT);
503 }
504 
505 /**
506  * Test that a nanoapp receives a success response when it attempts to stop a
507  * BLE scan while the BLE setting is disabled.
508  */
TEST_F(TestBase,BleSettingDisabledStopScanTest)509 TEST_F(TestBase, BleSettingDisabledStopScanTest) {
510   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
511   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
512   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
513 
514   struct App : public BleTestNanoapp {
515     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
516                                                    const void *eventData) {
517       switch (eventType) {
518         case CHRE_EVENT_BLE_ASYNC_RESULT: {
519           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
520           if (event->errorCode == CHRE_ERROR_NONE) {
521             uint16_t type =
522                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
523                     ? SCAN_STARTED
524                     : SCAN_STOPPED;
525             TestEventQueueSingleton::get()->pushEvent(type);
526           }
527           break;
528         }
529 
530         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
531           auto *event =
532               static_cast<const chreUserSettingChangedEvent *>(eventData);
533           bool enabled =
534               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
535           TestEventQueueSingleton::get()->pushEvent(
536               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
537           break;
538         }
539 
540         case CHRE_EVENT_TEST_EVENT: {
541           auto event = static_cast<const TestEvent *>(eventData);
542           switch (event->type) {
543             case STOP_SCAN: {
544               const bool success = chreBleStopScanAsync();
545               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
546               break;
547             }
548           }
549         }
550       }
551     };
552   };
553 
554   auto app = loadNanoapp<App>();
555 
556   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
557       Setting::BLE_AVAILABLE, false /* enable */);
558 
559   bool enabled;
560   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
561   EXPECT_FALSE(enabled);
562 
563   bool success;
564   sendEventToNanoapp(app, STOP_SCAN);
565   waitForEvent(STOP_SCAN, &success);
566   EXPECT_TRUE(success);
567   waitForEvent(SCAN_STOPPED);
568 }
569 
570 /**
571  * Test that a nanoapp can read RSSI successfully.
572  */
TEST_F(TestBase,BleReadRssi)573 TEST_F(TestBase, BleReadRssi) {
574   constexpr auto kConnectionHandle = 6;
575   constexpr auto kCookie = 123;
576 
577   CREATE_CHRE_TEST_EVENT(RSSI_REQUEST, 1);
578   CREATE_CHRE_TEST_EVENT(RSSI_REQUEST_SENT, 2);
579 
580   struct App : public BleTestNanoapp {
581     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
582                                                    const void *eventData) {
583       switch (eventType) {
584         case CHRE_EVENT_BLE_RSSI_READ: {
585           auto *event =
586               static_cast<const struct chreBleReadRssiEvent *>(eventData);
587           if (event->result.errorCode == CHRE_ERROR_NONE) {
588             TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_BLE_RSSI_READ);
589           }
590           break;
591         }
592         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
593           auto *event =
594               static_cast<const chreUserSettingChangedEvent *>(eventData);
595           bool enabled =
596               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
597           TestEventQueueSingleton::get()->pushEvent(
598               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
599           break;
600         }
601         case CHRE_EVENT_TEST_EVENT: {
602           auto event = static_cast<const TestEvent *>(eventData);
603           switch (event->type) {
604             case RSSI_REQUEST: {
605               const bool success =
606                   chreBleReadRssiAsync(kConnectionHandle, (void *)kCookie);
607               TestEventQueueSingleton::get()->pushEvent(RSSI_REQUEST_SENT,
608                                                         success);
609               break;
610             }
611           }
612         }
613       }
614     };
615   };
616 
617   auto app = loadNanoapp<App>();
618 
619   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
620       Setting::BLE_AVAILABLE, true /* enabled */);
621   bool enabled;
622   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
623   EXPECT_TRUE(enabled);
624 
625   bool success;
626   sendEventToNanoapp(app, RSSI_REQUEST);
627   waitForEvent(RSSI_REQUEST_SENT, &success);
628   EXPECT_TRUE(success);
629   waitForEvent(CHRE_EVENT_BLE_RSSI_READ);
630 }
631 
632 /**
633  * This test validates that a nanoapp can start call start scan twice before
634  * receiving an async response. It should invalidate its original request by
635  * calling start scan a second time.
636  */
TEST_F(TestBase,BleStartScanTwiceBeforeAsyncResponseTest)637 TEST_F(TestBase, BleStartScanTwiceBeforeAsyncResponseTest) {
638   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
639   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
640   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
641   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
642 
643   struct App : public BleTestNanoapp {
644     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
645                                                    const void *eventData) {
646       switch (eventType) {
647         case CHRE_EVENT_BLE_ASYNC_RESULT: {
648           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
649           uint16_t type =
650               (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
651                   ? SCAN_STARTED
652                   : SCAN_STOPPED;
653           TestEventQueueSingleton::get()->pushEvent(type, event->errorCode);
654           break;
655         }
656         case CHRE_EVENT_TEST_EVENT: {
657           auto event = static_cast<const TestEvent *>(eventData);
658           switch (event->type) {
659             case START_SCAN: {
660               const bool success = chreBleStartScanAsync(
661                   CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
662               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
663               break;
664             }
665 
666             case STOP_SCAN: {
667               const bool success = chreBleStopScanAsync();
668               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
669               break;
670             }
671           }
672         }
673       }
674     };
675   };
676 
677   auto app = loadNanoapp<App>();
678   bool success;
679 
680   delayBleScanStart(true /* delay */);
681 
682   sendEventToNanoapp(app, START_SCAN);
683   waitForEvent(START_SCAN, &success);
684   EXPECT_TRUE(success);
685 
686   sendEventToNanoapp(app, START_SCAN);
687   waitForEvent(START_SCAN, &success);
688   EXPECT_TRUE(success);
689 
690   uint8_t errorCode;
691   waitForEvent(SCAN_STARTED, &errorCode);
692   EXPECT_EQ(errorCode, CHRE_ERROR_OBSOLETE_REQUEST);
693 
694   // Respond to the first scan request. CHRE will then attempt the next scan
695   // request at which point the PAL should no longer delay the response.
696   delayBleScanStart(false /* delay */);
697   EXPECT_TRUE(startBleScan());
698 
699   waitForEvent(SCAN_STARTED, &errorCode);
700   EXPECT_EQ(errorCode, CHRE_ERROR_NONE);
701 
702   sendEventToNanoapp(app, STOP_SCAN);
703   waitForEvent(STOP_SCAN, &success);
704   EXPECT_TRUE(success);
705   waitForEvent(SCAN_STOPPED);
706 }
707 
708 }  // namespace
709 }  // namespace chre
710