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