blob: 9254217b63dfeb6604df5b0b7015e479feaeff2d [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "location/lbs/contexthub/nanoapps/nearby/filter.h"
#include <chre/util/macros.h>
#include <inttypes.h>
#include <pb_decode.h>
#include <cstdint>
#include <iterator>
#include "chre_api/chre.h"
#include "location/lbs/contexthub/nanoapps/nearby/ble_scan_record.h"
#include "location/lbs/contexthub/nanoapps/nearby/fast_pair_filter.h"
#ifdef ENABLE_PRESENCE
#include "location/lbs/contexthub/nanoapps/nearby/presence_crypto_identity_v1.h"
#include "location/lbs/contexthub/nanoapps/nearby/presence_crypto_v1.h"
#include "location/lbs/contexthub/nanoapps/nearby/presence_filter.h"
#endif
#include "third_party/contexthub/chre/util/include/chre/util/nanoapp/log.h"
#define LOG_TAG "[NEARBY][FILTER]"
namespace nearby {
constexpr nearby_BleFilters kDefaultBleFilters = nearby_BleFilters_init_zero;
bool Filter::Update(const uint8_t *message, uint32_t message_size) {
LOGD("Decode a Filters message with size %" PRIu32, message_size);
ble_filters_ = kDefaultBleFilters;
pb_istream_t stream = pb_istream_from_buffer(message, message_size);
if (!pb_decode(&stream, nearby_BleFilters_fields, &ble_filters_)) {
LOGE("Failed to decode a Filters message.");
return false;
}
// Print filters for debug.
LOGD_SENSITIVE_INFO("BLE filters counter %d", ble_filters_.filter_count);
if (ble_filters_.filter_count > 0) {
LOGD_SENSITIVE_INFO("BLE filter 0 data element count %d",
ble_filters_.filter[0].data_element_count);
if (ble_filters_.filter[0].data_element_count > 0) {
LOGD_SENSITIVE_INFO(
"Data Element 0, key: %" PRIi32
" value[0]: %d,"
" has key: %d, has value: %d, has value length %d,"
" value length %" PRIu32,
ble_filters_.filter[0].data_element[0].key,
ble_filters_.filter[0].data_element[0].value[0],
ble_filters_.filter[0].data_element[0].has_key,
ble_filters_.filter[0].data_element[0].has_value,
ble_filters_.filter[0].data_element[0].has_value_length,
ble_filters_.filter[0].data_element[0].value_length);
}
}
for (int i = 0; i < ble_filters_.filter_count; i++) {
const nearby_BleFilter *filter = &ble_filters_.filter[i];
// Sets the scan interval to satisfy the minimal latency requirement.
if (filter->has_latency_ms && filter->latency_ms < scan_interval_ms_) {
scan_interval_ms_ = filter->latency_ms;
}
}
return true;
}
void Filter::MatchBle(
const chreBleAdvertisingReport &report,
chre::DynamicVector<nearby_BleFilterResult> *filter_results,
chre::DynamicVector<nearby_BleFilterResult> *fp_filter_results) {
#ifndef ENABLE_PRESENCE
UNUSED_VAR(filter_results);
#endif
LOGD("MatchBle");
nearby_BleFilterResult result;
auto record = BleScanRecord::Parse(report.data, report.dataLength);
// Log the service data for debug only.
for (const auto &ble_service_data : record.service_data) {
LOGD_SENSITIVE_INFO("Receive service data with uuid %" PRIX16,
ble_service_data.uuid);
for (int i = 0; i < ble_service_data.length; i++) {
LOGD_SENSITIVE_INFO("%" PRIx8, ble_service_data.data[i]);
}
LOGD_SENSITIVE_INFO("Service data end.");
}
for (int filter_index = 0; filter_index < ble_filters_.filter_count;
filter_index++) {
LOGD("MatchPresence advertisements.");
// TODO(b/193756395): multiple matched results can share the same BLE
// event. Optimize the memory usage by avoiding duplicated BLE events
// across multiple results.
result = nearby_BleFilterResult_init_zero;
result.has_id = true;
result.id = static_cast<uint32_t>(filter_index);
result.has_tx_power = true;
result.tx_power = static_cast<int32_t>(report.txPower);
result.has_rssi = true;
result.rssi = static_cast<int32_t>(report.rssi);
result.has_bluetooth_address = true;
// The buffer size has already been checked.
static_assert(std::size(result.bluetooth_address) == CHRE_BLE_ADDRESS_LEN);
memcpy(result.bluetooth_address, report.address, std::size(report.address));
result.has_timestamp_ns = true;
result.timestamp_ns =
report.timestamp +
static_cast<uint64_t>(chreGetEstimatedHostTimeOffset());
if (MatchFastPair(ble_filters_.filter[filter_index], record, &result)) {
LOGD("Add a matched Fast Pair filter result");
fp_filter_results->push_back(result);
return;
}
#ifdef ENABLE_PRESENCE
if (MatchPresenceV0(ble_filters_.filter[filter_index], record, &result) ||
MatchPresenceV1(ble_filters_.filter[filter_index], record,
PresenceCryptoV1Impl(), PresenceCryptoIdentityV1Impl(),
&result)) {
LOGD("Filter result TX power %" PRId32 ", RSSI %" PRId32, result.tx_power,
result.rssi);
LOGD("Add a matched Presence filter result");
filter_results->push_back(result);
}
#endif
}
}
} // namespace nearby