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