xref: /aosp_15_r20/system/chre/test/simulation/ble_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
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   class App : public TestNanoapp {
47    public:
48     App()
49         : TestNanoapp(
50               TestNanoappInfo{.perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
51 
52     void handleEvent(uint32_t, uint16_t eventType,
53                      const void *eventData) override {
54       switch (eventType) {
55         case CHRE_EVENT_TEST_EVENT: {
56           auto event = static_cast<const TestEvent *>(eventData);
57           switch (event->type) {
58             case GET_CAPABILITIES: {
59               TestEventQueueSingleton::get()->pushEvent(
60                   GET_CAPABILITIES, chreBleGetCapabilities());
61               break;
62             }
63 
64             case GET_FILTER_CAPABILITIES: {
65               TestEventQueueSingleton::get()->pushEvent(
66                   GET_FILTER_CAPABILITIES, chreBleGetFilterCapabilities());
67               break;
68             }
69           }
70         }
71       }
72     }
73   };
74 
75   uint64_t appId = loadNanoapp(MakeUnique<App>());
76 
77   uint32_t capabilities;
78   sendEventToNanoapp(appId, GET_CAPABILITIES);
79   waitForEvent(GET_CAPABILITIES, &capabilities);
80   ASSERT_EQ(capabilities, CHRE_BLE_CAPABILITIES_SCAN |
81                               CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING |
82                               CHRE_BLE_CAPABILITIES_SCAN_FILTER_BEST_EFFORT);
83 
84   sendEventToNanoapp(appId, GET_FILTER_CAPABILITIES);
85   waitForEvent(GET_FILTER_CAPABILITIES, &capabilities);
86   ASSERT_EQ(capabilities, CHRE_BLE_FILTER_CAPABILITIES_RSSI |
87                               CHRE_BLE_FILTER_CAPABILITIES_SERVICE_DATA);
88 }
89 
90 class BleTestNanoapp : public TestNanoapp {
91  public:
BleTestNanoapp()92   BleTestNanoapp()
93       : TestNanoapp(
94             TestNanoappInfo{.perms = NanoappPermissions::CHRE_PERMS_BLE}) {}
95 
start()96   bool start() override {
97     chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
98                                    true /* enable */);
99     return true;
100   }
101 
end()102   void end() override {
103     chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
104                                    false /* enable */);
105   }
106 };
107 
108 /**
109  * This test validates the case in which a nanoapp starts a scan, receives
110  * at least one advertisement event, and stops a scan.
111  */
TEST_F(TestBase,BleSimpleScanTest)112 TEST_F(TestBase, BleSimpleScanTest) {
113   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
114   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
115   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
116   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
117 
118   class App : public BleTestNanoapp {
119    public:
120     void handleEvent(uint32_t, uint16_t eventType,
121                      const void *eventData) override {
122       switch (eventType) {
123         case CHRE_EVENT_BLE_ASYNC_RESULT: {
124           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
125           if (event->errorCode == CHRE_ERROR_NONE) {
126             uint16_t type =
127                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
128                     ? SCAN_STARTED
129                     : SCAN_STOPPED;
130             TestEventQueueSingleton::get()->pushEvent(type);
131           }
132           break;
133         }
134 
135         case CHRE_EVENT_BLE_ADVERTISEMENT: {
136           TestEventQueueSingleton::get()->pushEvent(
137               CHRE_EVENT_BLE_ADVERTISEMENT);
138           break;
139         }
140 
141         case CHRE_EVENT_TEST_EVENT: {
142           auto event = static_cast<const TestEvent *>(eventData);
143           switch (event->type) {
144             case START_SCAN: {
145               const bool success = chreBleStartScanAsync(
146                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr);
147               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
148               break;
149             }
150 
151             case STOP_SCAN: {
152               const bool success = chreBleStopScanAsync();
153               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
154               break;
155             }
156           }
157           break;
158         }
159       }
160     }
161   };
162 
163   uint64_t appId = loadNanoapp(MakeUnique<App>());
164 
165   bool success;
166   sendEventToNanoapp(appId, START_SCAN);
167   waitForEvent(START_SCAN, &success);
168   EXPECT_TRUE(success);
169   waitForEvent(SCAN_STARTED);
170   ASSERT_TRUE(chrePalIsBleEnabled());
171   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
172 
173   sendEventToNanoapp(appId, STOP_SCAN);
174   waitForEvent(STOP_SCAN, &success);
175   EXPECT_TRUE(success);
176   waitForEvent(SCAN_STOPPED);
177   ASSERT_FALSE(chrePalIsBleEnabled());
178 }
179 
TEST_F(TestBase,BleStopScanOnUnload)180 TEST_F(TestBase, BleStopScanOnUnload) {
181   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
182   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
183 
184   class App : public BleTestNanoapp {
185    public:
186     void handleEvent(uint32_t, uint16_t eventType,
187                      const void *eventData) override {
188       switch (eventType) {
189         case CHRE_EVENT_BLE_ASYNC_RESULT: {
190           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
191           if (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN &&
192               event->errorCode == CHRE_ERROR_NONE) {
193             TestEventQueueSingleton::get()->pushEvent(SCAN_STARTED);
194           }
195           break;
196         }
197 
198         case CHRE_EVENT_TEST_EVENT: {
199           auto event = static_cast<const TestEvent *>(eventData);
200           switch (event->type) {
201             case START_SCAN: {
202               const bool success = chreBleStartScanAsync(
203                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr);
204               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
205               break;
206             }
207           }
208           break;
209         }
210       }
211     }
212   };
213 
214   uint64_t appId = loadNanoapp(MakeUnique<App>());
215 
216   bool success;
217   sendEventToNanoapp(appId, START_SCAN);
218   waitForEvent(START_SCAN, &success);
219   EXPECT_TRUE(success);
220   waitForEvent(SCAN_STARTED);
221   ASSERT_TRUE(chrePalIsBleEnabled());
222 
223   unloadNanoapp(appId);
224   ASSERT_FALSE(chrePalIsBleEnabled());
225 }
226 
227 /**
228  * This test validates that a nanoapp can start a scan twice and the platform
229  * will be enabled.
230  */
TEST_F(TestBase,BleStartTwiceScanTest)231 TEST_F(TestBase, BleStartTwiceScanTest) {
232   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
233   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
234   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
235   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
236 
237   class App : public BleTestNanoapp {
238    public:
239     void handleEvent(uint32_t, uint16_t eventType, const void *eventData) {
240       switch (eventType) {
241         case CHRE_EVENT_BLE_ASYNC_RESULT: {
242           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
243           if (event->errorCode == CHRE_ERROR_NONE) {
244             uint16_t type =
245                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
246                     ? SCAN_STARTED
247                     : SCAN_STOPPED;
248             TestEventQueueSingleton::get()->pushEvent(type);
249           }
250           break;
251         }
252 
253         case CHRE_EVENT_BLE_ADVERTISEMENT: {
254           TestEventQueueSingleton::get()->pushEvent(
255               CHRE_EVENT_BLE_ADVERTISEMENT);
256           break;
257         }
258 
259         case CHRE_EVENT_TEST_EVENT: {
260           auto event = static_cast<const TestEvent *>(eventData);
261           switch (event->type) {
262             case START_SCAN: {
263               const bool success = chreBleStartScanAsync(
264                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr);
265               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
266               break;
267             }
268 
269             case STOP_SCAN: {
270               const bool success = chreBleStopScanAsync();
271               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
272               break;
273             }
274           }
275         }
276       }
277     }
278   };
279 
280   uint64_t appId = loadNanoapp(MakeUnique<App>());
281   bool success;
282 
283   sendEventToNanoapp(appId, START_SCAN);
284   waitForEvent(START_SCAN, &success);
285   EXPECT_TRUE(success);
286   waitForEvent(SCAN_STARTED);
287 
288   sendEventToNanoapp(appId, START_SCAN);
289   waitForEvent(START_SCAN, &success);
290   EXPECT_TRUE(success);
291   waitForEvent(SCAN_STARTED);
292   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
293 
294   sendEventToNanoapp(appId, STOP_SCAN);
295   waitForEvent(STOP_SCAN, &success);
296   EXPECT_TRUE(success);
297   waitForEvent(SCAN_STOPPED);
298 }
299 
300 /**
301  * This test validates that a nanoapp can request to stop a scan twice without
302  * any ongoing scan existing. It asserts that the nanoapp did not receive any
303  * advertisment events because a scan was never started.
304  */
TEST_F(TestBase,BleStopTwiceScanTest)305 TEST_F(TestBase, BleStopTwiceScanTest) {
306   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
307   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
308   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
309 
310   class App : public BleTestNanoapp {
311    public:
312     void handleEvent(uint32_t, uint16_t eventType,
313                      const void *eventData) override {
314       switch (eventType) {
315         case CHRE_EVENT_BLE_ASYNC_RESULT: {
316           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
317           if (event->errorCode == CHRE_ERROR_NONE) {
318             uint16_t type =
319                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
320                     ? SCAN_STARTED
321                     : SCAN_STOPPED;
322             TestEventQueueSingleton::get()->pushEvent(type);
323           }
324           break;
325         }
326 
327         case CHRE_EVENT_BLE_ADVERTISEMENT: {
328           FATAL_ERROR("No advertisement expected");
329           break;
330         }
331 
332         case CHRE_EVENT_TEST_EVENT: {
333           auto event = static_cast<const TestEvent *>(eventData);
334           switch (event->type) {
335             case STOP_SCAN: {
336               const bool success = chreBleStopScanAsync();
337               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
338               break;
339             }
340           }
341         }
342       }
343     }
344   };
345 
346   uint64_t appId = loadNanoapp(MakeUnique<App>());
347 
348   bool success;
349   sendEventToNanoapp(appId, STOP_SCAN);
350   waitForEvent(STOP_SCAN, &success);
351   EXPECT_TRUE(success);
352   waitForEvent(SCAN_STOPPED);
353 
354   sendEventToNanoapp(appId, STOP_SCAN);
355   waitForEvent(STOP_SCAN, &success);
356   EXPECT_TRUE(success);
357 
358   waitForEvent(SCAN_STOPPED);
359   unloadNanoapp(appId);
360 }
361 
362 /**
363  * This test verifies the following BLE settings behavior:
364  * 1) Nanoapp makes BLE scan request
365  * 2) Toggle BLE setting -> disabled
366  * 3) Toggle BLE setting -> enabled.
367  * 4) Verify things resume.
368  */
TEST_F(TestBase,BleSettingChangeTest)369 TEST_F(TestBase, BleSettingChangeTest) {
370   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
371   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
372   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
373 
374   class App : public BleTestNanoapp {
375    public:
376     void handleEvent(uint32_t, uint16_t eventType,
377                      const void *eventData) override {
378       switch (eventType) {
379         case CHRE_EVENT_BLE_ASYNC_RESULT: {
380           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
381           if (event->errorCode == CHRE_ERROR_NONE) {
382             uint16_t type =
383                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
384                     ? SCAN_STARTED
385                     : SCAN_STOPPED;
386             TestEventQueueSingleton::get()->pushEvent(type);
387           }
388           break;
389         }
390 
391         case CHRE_EVENT_BLE_ADVERTISEMENT: {
392           TestEventQueueSingleton::get()->pushEvent(
393               CHRE_EVENT_BLE_ADVERTISEMENT);
394           break;
395         }
396 
397         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
398           auto *event =
399               static_cast<const chreUserSettingChangedEvent *>(eventData);
400           bool enabled =
401               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
402           TestEventQueueSingleton::get()->pushEvent(
403               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
404           break;
405         }
406 
407         case CHRE_EVENT_TEST_EVENT: {
408           auto event = static_cast<const TestEvent *>(eventData);
409           switch (event->type) {
410             case START_SCAN: {
411               const bool success = chreBleStartScanAsync(
412                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr);
413               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
414               break;
415             }
416           }
417         }
418       }
419     }
420   };
421 
422   uint64_t appId = loadNanoapp(MakeUnique<App>());
423 
424   bool success;
425   sendEventToNanoapp(appId, START_SCAN);
426   waitForEvent(START_SCAN, &success);
427   EXPECT_TRUE(success);
428 
429   waitForEvent(SCAN_STARTED);
430   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
431 
432   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
433       Setting::BLE_AVAILABLE, false /* enabled */);
434   bool enabled;
435   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
436   EXPECT_FALSE(enabled);
437   EXPECT_FALSE(
438       EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
439           Setting::BLE_AVAILABLE));
440   std::this_thread::sleep_for(std::chrono::milliseconds(100));
441   EXPECT_FALSE(chrePalIsBleEnabled());
442 
443   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
444       Setting::BLE_AVAILABLE, true /* enabled */);
445   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
446   EXPECT_TRUE(enabled);
447   EXPECT_TRUE(
448       EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
449           Setting::BLE_AVAILABLE));
450   waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
451   EXPECT_TRUE(chrePalIsBleEnabled());
452 }
453 
454 /**
455  * Test that a nanoapp receives a function disabled error if it attempts to
456  * start a scan when the BLE setting is disabled.
457  */
TEST_F(TestBase,BleSettingDisabledStartScanTest)458 TEST_F(TestBase, BleSettingDisabledStartScanTest) {
459   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
460 
461   class App : public BleTestNanoapp {
462    public:
463     void handleEvent(uint32_t, uint16_t eventType,
464                      const void *eventData) override {
465       switch (eventType) {
466         case CHRE_EVENT_BLE_ASYNC_RESULT: {
467           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
468           if (event->errorCode == CHRE_ERROR_FUNCTION_DISABLED) {
469             TestEventQueueSingleton::get()->pushEvent(
470                 CHRE_EVENT_BLE_ASYNC_RESULT);
471           }
472           break;
473         }
474 
475         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
476           auto *event =
477               static_cast<const chreUserSettingChangedEvent *>(eventData);
478           bool enabled =
479               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
480           TestEventQueueSingleton::get()->pushEvent(
481               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
482           break;
483         }
484 
485         case CHRE_EVENT_TEST_EVENT: {
486           auto event = static_cast<const TestEvent *>(eventData);
487           switch (event->type) {
488             case START_SCAN: {
489               const bool success = chreBleStartScanAsync(
490                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr);
491               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
492               break;
493             }
494           }
495         }
496       }
497     }
498   };
499 
500   uint64_t appId = loadNanoapp(MakeUnique<App>());
501 
502   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
503       Setting::BLE_AVAILABLE, false /* enable */);
504 
505   bool enabled;
506   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
507   EXPECT_FALSE(enabled);
508 
509   bool success;
510   sendEventToNanoapp(appId, START_SCAN);
511   waitForEvent(START_SCAN, &success);
512   EXPECT_TRUE(success);
513   waitForEvent(CHRE_EVENT_BLE_ASYNC_RESULT);
514 }
515 
516 /**
517  * Test that a nanoapp receives a success response when it attempts to stop a
518  * BLE scan while the BLE setting is disabled.
519  */
TEST_F(TestBase,BleSettingDisabledStopScanTest)520 TEST_F(TestBase, BleSettingDisabledStopScanTest) {
521   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
522   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
523   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
524 
525   class App : public BleTestNanoapp {
526    public:
527     void handleEvent(uint32_t, uint16_t eventType,
528                      const void *eventData) override {
529       switch (eventType) {
530         case CHRE_EVENT_BLE_ASYNC_RESULT: {
531           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
532           if (event->errorCode == CHRE_ERROR_NONE) {
533             uint16_t type =
534                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
535                     ? SCAN_STARTED
536                     : SCAN_STOPPED;
537             TestEventQueueSingleton::get()->pushEvent(type);
538           }
539           break;
540         }
541 
542         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
543           auto *event =
544               static_cast<const chreUserSettingChangedEvent *>(eventData);
545           bool enabled =
546               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
547           TestEventQueueSingleton::get()->pushEvent(
548               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
549           break;
550         }
551 
552         case CHRE_EVENT_TEST_EVENT: {
553           auto event = static_cast<const TestEvent *>(eventData);
554           switch (event->type) {
555             case STOP_SCAN: {
556               const bool success = chreBleStopScanAsync();
557               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
558               break;
559             }
560           }
561         }
562       }
563     }
564   };
565 
566   uint64_t appId = loadNanoapp(MakeUnique<App>());
567 
568   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
569       Setting::BLE_AVAILABLE, false /* enable */);
570 
571   bool enabled;
572   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
573   EXPECT_FALSE(enabled);
574 
575   bool success;
576   sendEventToNanoapp(appId, STOP_SCAN);
577   waitForEvent(STOP_SCAN, &success);
578   EXPECT_TRUE(success);
579   waitForEvent(SCAN_STOPPED);
580 }
581 
582 /**
583  * Test that a nanoapp can read RSSI successfully.
584  */
TEST_F(TestBase,BleReadRssi)585 TEST_F(TestBase, BleReadRssi) {
586   constexpr uint16_t kConnectionHandle = 6;
587   constexpr uint32_t kCookie = 123;
588 
589   CREATE_CHRE_TEST_EVENT(RSSI_REQUEST, 1);
590   CREATE_CHRE_TEST_EVENT(RSSI_REQUEST_SENT, 2);
591 
592   class App : public BleTestNanoapp {
593     void handleEvent(uint32_t, uint16_t eventType, const void *eventData) {
594       switch (eventType) {
595         case CHRE_EVENT_BLE_RSSI_READ: {
596           auto *event =
597               static_cast<const struct chreBleReadRssiEvent *>(eventData);
598           if (event->result.errorCode == CHRE_ERROR_NONE) {
599             TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_BLE_RSSI_READ);
600           }
601           break;
602         }
603         case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
604           auto *event =
605               static_cast<const chreUserSettingChangedEvent *>(eventData);
606           bool enabled =
607               (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
608           TestEventQueueSingleton::get()->pushEvent(
609               CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
610           break;
611         }
612         case CHRE_EVENT_TEST_EVENT: {
613           auto event = static_cast<const TestEvent *>(eventData);
614           switch (event->type) {
615             case RSSI_REQUEST: {
616               const bool success =
617                   chreBleReadRssiAsync(kConnectionHandle, (void *)kCookie);
618               TestEventQueueSingleton::get()->pushEvent(RSSI_REQUEST_SENT,
619                                                         success);
620               break;
621             }
622           }
623         }
624       }
625     }
626   };
627 
628   uint64_t appId = loadNanoapp(MakeUnique<App>());
629 
630   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
631       Setting::BLE_AVAILABLE, true /* enabled */);
632   bool enabled;
633   waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
634   EXPECT_TRUE(enabled);
635 
636   bool success;
637   sendEventToNanoapp(appId, RSSI_REQUEST);
638   waitForEvent(RSSI_REQUEST_SENT, &success);
639   EXPECT_TRUE(success);
640   waitForEvent(CHRE_EVENT_BLE_RSSI_READ);
641 }
642 
643 /**
644  * This test validates that a nanoapp can start call start scan twice before
645  * receiving an async response. It should invalidate its original request by
646  * calling start scan a second time.
647  */
TEST_F(TestBase,BleStartScanTwiceBeforeAsyncResponseTest)648 TEST_F(TestBase, BleStartScanTwiceBeforeAsyncResponseTest) {
649   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
650   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
651   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
652   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
653 
654   struct testData {
655     void *cookie;
656   };
657 
658   class App : public BleTestNanoapp {
659     void handleEvent(uint32_t, uint16_t eventType, const void *eventData) {
660       switch (eventType) {
661         case CHRE_EVENT_BLE_ASYNC_RESULT: {
662           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
663           uint16_t type =
664               (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
665                   ? SCAN_STARTED
666                   : SCAN_STOPPED;
667           TestEventQueueSingleton::get()->pushEvent(type, *event);
668           break;
669         }
670         case CHRE_EVENT_TEST_EVENT: {
671           auto event = static_cast<const TestEvent *>(eventData);
672           switch (event->type) {
673             case START_SCAN: {
674               auto data = static_cast<testData *>(event->data);
675               const bool success = chreBleStartScanAsyncV1_9(
676                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 0, nullptr, data->cookie);
677               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
678               break;
679             }
680 
681             case STOP_SCAN: {
682               auto data = static_cast<testData *>(event->data);
683               const bool success = chreBleStopScanAsyncV1_9(data->cookie);
684               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
685               break;
686             }
687           }
688         }
689       }
690     }
691   };
692 
693   uint64_t appId = loadNanoapp(MakeUnique<App>());
694   bool success;
695 
696   delayBleScanStart(true /* delay */);
697 
698   testData data;
699   uint32_t cookieOne = 1;
700   data.cookie = &cookieOne;
701   sendEventToNanoapp(appId, START_SCAN, data);
702   waitForEvent(START_SCAN, &success);
703   EXPECT_TRUE(success);
704 
705   uint32_t cookieTwo = 2;
706   data.cookie = &cookieTwo;
707   sendEventToNanoapp(appId, START_SCAN, data);
708   waitForEvent(START_SCAN, &success);
709   EXPECT_TRUE(success);
710 
711   chreAsyncResult result;
712   waitForEvent(SCAN_STARTED, &result);
713   EXPECT_EQ(result.errorCode, CHRE_ERROR_OBSOLETE_REQUEST);
714   EXPECT_EQ(result.cookie, &cookieOne);
715 
716   // Respond to the first scan request. CHRE will then attempt the next scan
717   // request at which point the PAL should no longer delay the response.
718   delayBleScanStart(false /* delay */);
719   EXPECT_TRUE(startBleScan());
720 
721   waitForEvent(SCAN_STARTED, &result);
722   EXPECT_EQ(result.errorCode, CHRE_ERROR_NONE);
723   EXPECT_EQ(result.cookie, &cookieTwo);
724 
725   sendEventToNanoapp(appId, STOP_SCAN, data);
726   waitForEvent(STOP_SCAN, &success);
727   EXPECT_TRUE(success);
728   waitForEvent(SCAN_STOPPED);
729 }
730 
731 /**
732  * This test validates that a nanoapp can call flush only when an existing scan
733  * is enabled for the nanoapp. This test validates that batching will hold the
734  * data and flush will send the batched data and then a flush complete event.
735  */
TEST_F(TestBase,BleFlush)736 TEST_F(TestBase, BleFlush) {
737   CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
738   CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
739   CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
740   CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
741   CREATE_CHRE_TEST_EVENT(CALL_FLUSH, 4);
742   CREATE_CHRE_TEST_EVENT(SAW_BLE_AD_AND_FLUSH_COMPLETE, 5);
743 
744   class App : public BleTestNanoapp {
745    public:
746     void handleEvent(uint32_t, uint16_t eventType,
747                      const void *eventData) override {
748       switch (eventType) {
749         case CHRE_EVENT_BLE_ASYNC_RESULT: {
750           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
751           if (event->errorCode == CHRE_ERROR_NONE) {
752             uint16_t type =
753                 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
754                     ? SCAN_STARTED
755                     : SCAN_STOPPED;
756             TestEventQueueSingleton::get()->pushEvent(type);
757           }
758           break;
759         }
760 
761         case CHRE_EVENT_BLE_ADVERTISEMENT: {
762           mSawBleAdvertisementEvent = true;
763           break;
764         }
765 
766         case CHRE_EVENT_BLE_FLUSH_COMPLETE: {
767           auto *event = static_cast<const struct chreAsyncResult *>(eventData);
768           mSawFlushCompleteEvent = event->success && event->cookie == &mCookie;
769           break;
770         }
771 
772         case CHRE_EVENT_TEST_EVENT: {
773           auto event = static_cast<const TestEvent *>(eventData);
774           switch (event->type) {
775             case START_SCAN: {
776               const bool success = chreBleStartScanAsync(
777                   CHRE_BLE_SCAN_MODE_AGGRESSIVE, 60000, nullptr);
778               TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
779               break;
780             }
781 
782             case STOP_SCAN: {
783               const bool success = chreBleStopScanAsync();
784               TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
785               break;
786             }
787 
788             case CALL_FLUSH: {
789               const bool success = chreBleFlushAsync(&mCookie);
790               TestEventQueueSingleton::get()->pushEvent(CALL_FLUSH, success);
791               break;
792             }
793           }
794           break;
795         }
796       }
797 
798       if (mSawBleAdvertisementEvent && mSawFlushCompleteEvent) {
799         TestEventQueueSingleton::get()->pushEvent(
800             SAW_BLE_AD_AND_FLUSH_COMPLETE);
801         mSawBleAdvertisementEvent = false;
802         mSawFlushCompleteEvent = false;
803       }
804     }
805 
806    private:
807     uint32_t mCookie;
808     bool mSawBleAdvertisementEvent = false;
809     bool mSawFlushCompleteEvent = false;
810   };
811 
812   uint64_t appId = loadNanoapp(MakeUnique<App>());
813 
814   // Flushing before a scan should fail.
815   bool success;
816   sendEventToNanoapp(appId, CALL_FLUSH);
817   waitForEvent(CALL_FLUSH, &success);
818   ASSERT_FALSE(success);
819 
820   // Start a scan with batching.
821   sendEventToNanoapp(appId, START_SCAN);
822   waitForEvent(START_SCAN, &success);
823   ASSERT_TRUE(success);
824   waitForEvent(SCAN_STARTED);
825   ASSERT_TRUE(chrePalIsBleEnabled());
826 
827   // Call flush again multiple times and get the complete event.
828   // We should only receive data when flush is called as the batch
829   // delay is extremely large.
830   constexpr uint32_t kNumFlushCalls = 3;
831   for (uint32_t i = 0; i < kNumFlushCalls; ++i) {
832     std::this_thread::sleep_for(std::chrono::milliseconds(250));
833 
834     sendEventToNanoapp(appId, CALL_FLUSH);
835     waitForEvent(CALL_FLUSH, &success);
836     ASSERT_TRUE(success);
837 
838     // Wait for some data and a flush complete.
839     // This ensures we receive both advertisement events
840     // and a flush complete event. We are not guaranteed
841     // that the advertisement events will come after
842     // the CALL_FLUSH event or before. If they come
843     // before, then they will be ignored. This
844     // change allows the advertisement events to come
845     // after during the normal expiration of the
846     // batch timer, which is valid (call flush, get
847     // any advertisement events, flush complete event
848     // might get some advertisement events afterwards).
849     waitForEvent(SAW_BLE_AD_AND_FLUSH_COMPLETE);
850   }
851 
852   // Stop a scan.
853   sendEventToNanoapp(appId, STOP_SCAN);
854   waitForEvent(STOP_SCAN, &success);
855   ASSERT_TRUE(success);
856   waitForEvent(SCAN_STOPPED);
857   ASSERT_FALSE(chrePalIsBleEnabled());
858 
859   // Flushing after a scan should fail.
860   sendEventToNanoapp(appId, CALL_FLUSH);
861   waitForEvent(CALL_FLUSH, &success);
862   ASSERT_FALSE(success);
863 }
864 
865 }  // namespace
866 }  // namespace chre
867