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