1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bluetooth_ble_filter_matcher.h"
17
18 namespace OHOS {
19 namespace Bluetooth {
20 using namespace OHOS::bluetooth;
MatchesScanFilters(const std::vector<bluetooth::BleScanFilterImpl> & bleScanFilters,const BluetoothBleScanResult & result)21 MatchResult BluetoothBleFilterMatcher::MatchesScanFilters(
22 const std::vector<bluetooth::BleScanFilterImpl> &bleScanFilters,
23 const BluetoothBleScanResult &result)
24 {
25 // no filters equals all result pass
26 if (bleScanFilters.empty()) {
27 return MatchResult::MATCH;
28 }
29
30 for (const auto &filter : bleScanFilters) {
31 if (MatchesScanFilter(filter, result) == MatchResult::MATCH) {
32 return MatchResult::MATCH;
33 }
34 }
35 return MatchResult::MISMATCH;
36 }
37
MatchesScanFilter(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)38 MatchResult BluetoothBleFilterMatcher::MatchesScanFilter(
39 const bluetooth::BleScanFilterImpl &filter,
40 const BluetoothBleScanResult &result)
41 {
42 if (MatchesAddress(filter, result) == MatchResult::MISMATCH) {
43 return MatchResult::MISMATCH;
44 }
45
46 if (MatchesName(filter, result) == MatchResult::MISMATCH) {
47 return MatchResult::MISMATCH;
48 }
49
50 if (MatchesServiceUuids(filter, result) == MatchResult::MISMATCH) {
51 return MatchResult::MISMATCH;
52 }
53
54 if (MatchesManufacturerDatas(filter, result) == MatchResult::MISMATCH) {
55 return MatchResult::MISMATCH;
56 }
57
58 if (MatchesServiceDatas(filter, result) == MatchResult::MISMATCH) {
59 return MatchResult::MISMATCH;
60 }
61
62 return MatchResult::MATCH;
63 }
64
MatchesAddress(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)65 MatchResult BluetoothBleFilterMatcher::MatchesAddress(const bluetooth::BleScanFilterImpl &filter,
66 const BluetoothBleScanResult &result)
67 {
68 std::string filterAddress = filter.GetDeviceId();
69 // no fiilter equals all result pass
70 if (filterAddress.empty()) {
71 return MatchResult::MATCH;
72 }
73
74 std::string resultAdderss = result.GetPeripheralDevice().GetAddress();
75 if (resultAdderss.empty()) {
76 return MatchResult::MISMATCH;
77 }
78
79 return filterAddress == resultAdderss ? MatchResult::MATCH : MatchResult::MISMATCH;
80 }
81
MatchesName(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)82 MatchResult BluetoothBleFilterMatcher::MatchesName(const bluetooth::BleScanFilterImpl &filter,
83 const BluetoothBleScanResult &result)
84 {
85 std::string filterName = filter.GetName();
86 // no fiilter equals all result pass
87 if (filterName.empty()) {
88 return MatchResult::MATCH;
89 }
90
91 std::string resultName = result.GetName();
92 if (resultName.empty()) {
93 return MatchResult::MISMATCH;
94 }
95
96 return filterName == resultName ? MatchResult::MATCH : MatchResult::MISMATCH;
97 }
98
MatchesServiceUuids(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)99 MatchResult BluetoothBleFilterMatcher::MatchesServiceUuids(const bluetooth::BleScanFilterImpl &filter,
100 const BluetoothBleScanResult &result)
101 {
102 // no fiilter equals all result pass
103 if (!filter.HasServiceUuid()) {
104 return MatchResult::MATCH;
105 }
106 bluetooth::Uuid filterUuid = filter.GetServiceUuid();
107
108 std::vector<bluetooth::Uuid> resultUuids = result.GetServiceUuids();
109 // if filter needs but result is empty means fail
110 if (resultUuids.empty()) {
111 return MatchResult::MISMATCH;
112 }
113
114 for (auto &uuid : resultUuids) {
115 // mask means filter = result
116 if (!filter.HasServiceUuidMask()) {
117 if (filterUuid.operator == (uuid)) {
118 return MatchResult::MATCH;
119 }
120 }
121
122 // mask means filter&&mask = result&&mask
123 if (filter.HasServiceUuidMask()) {
124 bluetooth::Uuid uuidMask = filter.GetServiceUuidMask();
125 if (MatchesUuidWithMask(filterUuid, uuid, uuidMask)) {
126 return MatchResult::MATCH;
127 }
128 }
129 }
130 return MatchResult::MISMATCH;
131 }
132
MatchesManufacturerDatas(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)133 MatchResult BluetoothBleFilterMatcher::MatchesManufacturerDatas(const bluetooth::BleScanFilterImpl &filter,
134 const BluetoothBleScanResult &result)
135 {
136 uint16_t filterManufacturerId = filter.GetManufacturerId();
137 std::vector<uint8_t> filterData = filter.GetManufactureData();
138 std::vector<uint8_t> fiilterDataMask = filter.GetManufactureDataMask();
139 // no fiilter equals all result pass
140 if (filterData.size() == 0) {
141 return MatchResult::MATCH;
142 }
143 // if filter needs but result is empty means fail
144 if (result.GetManufacturerData().empty()) {
145 return MatchResult::MISMATCH;
146 }
147
148 for (auto &resultManufacturerData : result.GetManufacturerData()) {
149 // if ManufacturerId same then check data
150 if (filterManufacturerId == resultManufacturerData.first) {
151 bool result = MatchesData(filterData, resultManufacturerData.second, fiilterDataMask);
152 return result ? MatchResult::MATCH : MatchResult::MISMATCH;
153 }
154 }
155 return MatchResult::MISMATCH;
156 }
157
MatchesServiceDatas(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)158 MatchResult BluetoothBleFilterMatcher::MatchesServiceDatas(const bluetooth::BleScanFilterImpl &filter,
159 const BluetoothBleScanResult &result)
160 {
161 std::vector<uint8_t> filterData = filter.GetServiceData();
162 std::vector<uint8_t> dataMask = filter.GetServiceDataMask();
163 // no Filter equals all result pass
164 if (filterData.size() == 0) {
165 return MatchResult::MATCH;
166 }
167 // if filter needs but result is empty means fail
168 if (result.GetServiceData().empty()) {
169 return MatchResult::MISMATCH;
170 }
171 for (auto &serviceData : result.GetServiceData()) {
172 std::string resultData = ParseServiceDataUUidToString(serviceData.first, serviceData.second);
173 if (MatchesData(filterData, resultData, dataMask)) {
174 return MatchResult::MATCH;
175 }
176 }
177 return MatchResult::MISMATCH;
178 }
179
MatchesUuidWithMask(bluetooth::Uuid filterUuid,bluetooth::Uuid uuid,bluetooth::Uuid uuidMask)180 bool BluetoothBleFilterMatcher::MatchesUuidWithMask(bluetooth::Uuid filterUuid,
181 bluetooth::Uuid uuid, bluetooth::Uuid uuidMask)
182 {
183 HILOGI("enter");
184 uint8_t uuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
185 uint8_t uuidMask128[bluetooth::Uuid::UUID128_BYTES_TYPE];
186 uint8_t resultUuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
187 if (!filterUuid.ConvertToBytesLE(uuid128)) {
188 HILOGE("Convert filter uuid faild.");
189 return false;
190 }
191 if (!uuidMask.ConvertToBytesLE(uuidMask128)) {
192 HILOGE("Convert uuid mask faild.");
193 return false;
194 }
195 if (!uuid.ConvertToBytesLE(resultUuid128)) {
196 HILOGE("Convert result uuid faild.");
197 return false;
198 }
199 size_t maskLength = sizeof(uuidMask128);
200 if (maskLength <= 0) {
201 return false;
202 }
203
204 for (size_t i = 0; i < maskLength; i++) {
205 if ((uuid128[i] & uuidMask128[i]) != (resultUuid128[i] & uuidMask128[i])) {
206 return false;
207 }
208 }
209
210 return true;
211 }
212
ParseServiceDataUUidToString(bluetooth::Uuid uuid,std::string data)213 std::string BluetoothBleFilterMatcher::ParseServiceDataUUidToString(bluetooth::Uuid uuid, std::string data)
214 {
215 std::string tmpServcieData;
216 int uuidType = uuid.GetUuidType();
217 switch (uuidType) {
218 case bluetooth::Uuid::UUID16_BYTES_TYPE: {
219 uint16_t uuid16 = uuid.ConvertTo16Bits();
220 tmpServcieData = std::string(reinterpret_cast<char *>(&uuid16), BLE_UUID_LEN_16);
221 break;
222 }
223 case bluetooth::Uuid::UUID32_BYTES_TYPE: {
224 uint32_t uuid32 = uuid.ConvertTo32Bits();
225 tmpServcieData = std::string(reinterpret_cast<char *>(&uuid32), BLE_UUID_LEN_32);
226 break;
227 }
228 case bluetooth::Uuid::UUID128_BYTES_TYPE: {
229 uint8_t uuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
230 if (!uuid.ConvertToBytesLE(uuid128)) {
231 HILOGE("Convert filter uuid faild.");
232 }
233 tmpServcieData = std::string(reinterpret_cast<char *>(&uuid128), BLE_UUID_LEN_128);
234 break;
235 }
236 default:
237 break;
238 }
239 return tmpServcieData + data;
240 }
241
MatchesData(std::vector<uint8_t> fData,std::string rData,std::vector<uint8_t> dataMask)242 bool BluetoothBleFilterMatcher::MatchesData(std::vector<uint8_t> fData,
243 std::string rData, std::vector<uint8_t> dataMask)
244 {
245 if (rData.empty()) {
246 return false;
247 }
248
249 size_t length = fData.size();
250 std::vector<uint8_t> vec(rData.begin(), rData.end());
251 if (vec.size() < length) {
252 return false;
253 }
254
255 if (dataMask.empty() || dataMask.size() != length) {
256 for (size_t i = 0; i < length; i++) {
257 if (fData[i] != vec[i]) {
258 return false;
259 }
260 }
261 return true;
262 }
263 for (size_t i = 0; i < length; i++) {
264 if ((fData[i] & dataMask[i]) != (vec[i] & dataMask[i])) {
265 return false;
266 }
267 }
268 return true;
269 }
270 } // namespace Bluetooth
271 } // namespace OHOS