xref: /aosp_15_r20/system/chre/apps/test/chqts/src/general_test/basic_ble_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2022 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 <general_test/basic_ble_test.h>
18 #include <shared/send_message.h>
19 
20 #include "chre/util/nanoapp/ble.h"
21 #include "chre/util/nanoapp/log.h"
22 #include "chre/util/time.h"
23 #include "chre_api/chre.h"
24 
25 #define LOG_TAG "[GeneralTest][Ble]"
26 /*
27  * Test to check expected functionality of the CHRE BLE APIs.
28  */
29 namespace general_test {
30 
31 using chre::createBleScanFilterForKnownBeacons;
32 using chre::ble_constants::kNumScanFilters;
33 using nanoapp_testing::sendFatalFailureToHost;
34 
35 namespace {
36 const uint32_t gFlushCookie = 0;
37 constexpr uint32_t kGoodReservedValue = 0;
38 constexpr uint8_t kMaxReportAdvertisingSid = 0x0f;
39 }  // namespace
40 
testScanSessionAsync(bool supportsBatching,bool supportsFiltering)41 void testScanSessionAsync(bool supportsBatching, bool supportsFiltering) {
42   uint32_t reportDelayMs = supportsBatching ? 1000 : 0;
43 
44   struct chreBleScanFilter filter;
45   chreBleGenericFilter uuidFilters[kNumScanFilters];
46   if (supportsFiltering) {
47     createBleScanFilterForKnownBeacons(filter, uuidFilters, kNumScanFilters);
48   }
49 
50   if (!chreBleStartScanAsync(CHRE_BLE_SCAN_MODE_FOREGROUND /* mode */,
51                              reportDelayMs,
52                              supportsFiltering ? &filter : nullptr)) {
53     sendFatalFailureToHost("Failed to start a BLE scan in the foreground");
54   }
55 }
56 
BasicBleTest()57 BasicBleTest::BasicBleTest()
58     : Test(CHRE_API_VERSION_1_7),
59       mFlushWasCalled(false),
60       mSupportsBatching(false) {}
61 
setUp(uint32_t messageSize,const void *)62 void BasicBleTest::setUp(uint32_t messageSize, const void * /* message */) {
63   if (messageSize != 0) {
64     sendFatalFailureToHost("Expected 0 byte message, got more bytes:",
65                            &messageSize);
66   }
67 
68   mSupportsBatching =
69       isCapabilitySet(CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING);
70   mSupportsFiltering =
71       isFilterCapabilitySet(CHRE_BLE_FILTER_CAPABILITIES_SERVICE_DATA) &&
72       isFilterCapabilitySet(CHRE_BLE_FILTER_CAPABILITIES_RSSI);
73 
74   if (!isCapabilitySet(CHRE_BLE_CAPABILITIES_SCAN)) {
75     mTestSuccessMarker.markStageAndSuccessOnFinish(BASIC_BLE_TEST_STAGE_SCAN);
76     mTestSuccessMarker.markStageAndSuccessOnFinish(BASIC_BLE_TEST_STAGE_FLUSH);
77     return;
78   }
79 
80   testScanSessionAsync(mSupportsBatching, mSupportsFiltering);
81   if (!mSupportsBatching) {
82     mTestSuccessMarker.markStageAndSuccessOnFinish(BASIC_BLE_TEST_STAGE_FLUSH);
83   }
84 }
85 
handleBleAsyncResult(const chreAsyncResult * result)86 void BasicBleTest::handleBleAsyncResult(const chreAsyncResult *result) {
87   if (result == nullptr) {
88     sendFatalFailureToHost("Received null BLE async result");
89     return;
90   }
91   if (!result->success) {
92     LOGE("Received unsuccessful BLE async result, error code %" PRIu8,
93          result->errorCode);
94     sendFatalFailureToHost("Received unsuccessful BLE async result");
95     return;
96   }
97 
98   switch (result->requestType) {
99     case CHRE_BLE_REQUEST_TYPE_START_SCAN:
100       // Wait one second to allow any advertisement events to propagate
101       // and be verified by handleAdvertisementEvent.
102       if (chreTimerSet(chre::kOneSecondInNanoseconds, nullptr, true) ==
103           CHRE_TIMER_INVALID) {
104         sendFatalFailureToHost(
105             "Failed to start a timer after BLE started scanning");
106       }
107       break;
108     case CHRE_BLE_REQUEST_TYPE_FLUSH:
109       if (result->cookie != &gFlushCookie) {
110         sendFatalFailureToHost("Cookie values do not match");
111       }
112       break;
113     case CHRE_BLE_REQUEST_TYPE_STOP_SCAN:
114       mTestSuccessMarker.markStageAndSuccessOnFinish(BASIC_BLE_TEST_STAGE_SCAN);
115       break;
116     default:
117       sendFatalFailureToHost("Unexpected request type");
118       break;
119   }
120 }
121 
handleAdvertisementEvent(const chreBleAdvertisementEvent * event)122 void BasicBleTest::handleAdvertisementEvent(
123     const chreBleAdvertisementEvent *event) {
124   if (event == nullptr) {
125     sendFatalFailureToHost("Invalid chreBleAdvertisementEvent");
126   } else if (event->reserved != kGoodReservedValue) {
127     sendFatalFailureToHost("chreBleAdvertisementEvent: reserved != 0");
128   } else {
129     for (uint16_t i = 0; i < event->numReports; ++i) {
130       const struct chreBleAdvertisingReport &report = event->reports[i];
131       if (report.advertisingSid != CHRE_BLE_ADI_NONE &&
132           report.advertisingSid > kMaxReportAdvertisingSid) {
133         sendFatalFailureToHost(
134             "chreBleAdvertisingReport: advertisingSid is invalid");
135       } else if (report.reserved != kGoodReservedValue) {
136         sendFatalFailureToHost("chreBleAdvertisingReport: reserved is invalid");
137       }
138     }
139   }
140 }
141 
handleTimerEvent()142 void BasicBleTest::handleTimerEvent() {
143   if (mSupportsBatching) {
144     if (!chreBleFlushAsync(&gFlushCookie)) {
145       sendFatalFailureToHost("Failed to BLE flush");
146     }
147     mFlushWasCalled = true;
148   } else {
149     if (chreBleFlushAsync(&gFlushCookie)) {
150       sendFatalFailureToHost(
151           "chreBleFlushAsync should return false if batching is not supported");
152     }
153 
154     if (!chreBleStopScanAsync()) {
155       sendFatalFailureToHost("Failed to stop a BLE scan session");
156     }
157   }
158 }
159 
handleEvent(uint32_t,uint16_t eventType,const void * eventData)160 void BasicBleTest::handleEvent(uint32_t /* senderInstanceId */,
161                                uint16_t eventType, const void *eventData) {
162   switch (eventType) {
163     case CHRE_EVENT_BLE_ASYNC_RESULT:
164       handleBleAsyncResult(static_cast<const chreAsyncResult *>(eventData));
165       break;
166     case CHRE_EVENT_BLE_FLUSH_COMPLETE:
167       if (!mFlushWasCalled) {
168         sendFatalFailureToHost(
169             "Received CHRE_EVENT_BLE_FLUSH_COMPLETE event when "
170             "chreBleFlushAsync was not called");
171       }
172       if (!chreBleStopScanAsync()) {
173         sendFatalFailureToHost("Failed to stop a BLE scan session");
174       }
175       mTestSuccessMarker.markStageAndSuccessOnFinish(
176           BASIC_BLE_TEST_STAGE_FLUSH);
177       break;
178     case CHRE_EVENT_BLE_ADVERTISEMENT:
179       handleAdvertisementEvent(
180           static_cast<const chreBleAdvertisementEvent *>(eventData));
181       break;
182     case CHRE_EVENT_BLE_BATCH_COMPLETE:
183       // Ignore the event only if we support batching.
184       // Otherwise, it is an unexpected event.
185       if (!mSupportsBatching) {
186         unexpectedEvent(eventType);
187       }
188       break;
189     case CHRE_EVENT_TIMER:
190       handleTimerEvent();
191       break;
192     default:
193       unexpectedEvent(eventType);
194       break;
195   }
196 }
197 
198 }  // namespace general_test
199