blob: 7924349ad8bddae5b5771fcf06ce754eaf89e487 [file] [log] [blame]
/*
* Copyright (C) 2022 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 "chre/core/ble_request.h"
#include <inttypes.h>
#include "chre/platform/fatal_error.h"
#include "chre/util/memory.h"
namespace chre {
namespace {
bool filtersMatch(const chreBleGenericFilter &filter,
const chreBleGenericFilter &otherFilter) {
return filter.len == otherFilter.len && filter.type == otherFilter.type &&
(memcmp(filter.data, otherFilter.data, filter.len) == 0) &&
(memcmp(filter.dataMask, otherFilter.dataMask, filter.len) == 0);
}
} // namespace
BleRequest::BleRequest() : BleRequest(0, false) {}
BleRequest::BleRequest(uint16_t instanceId, bool enable)
: BleRequest(instanceId, enable, CHRE_BLE_SCAN_MODE_BACKGROUND,
0 /* reportDelayMs */, nullptr /* filter */) {}
BleRequest::BleRequest(uint16_t instanceId, bool enable, chreBleScanMode mode,
uint32_t reportDelayMs, const chreBleScanFilter *filter)
: mReportDelayMs(reportDelayMs),
mInstanceId(instanceId),
mMode(mode),
mEnabled(enable),
mRssiThreshold(CHRE_BLE_RSSI_THRESHOLD_NONE),
mStatus(RequestStatus::PENDING_REQ) {
if (filter != nullptr) {
mRssiThreshold = filter->rssiThreshold;
if (filter->scanFilterCount > 0) {
if (!mFilters.resize(filter->scanFilterCount)) {
FATAL_ERROR("Unable to reserve filter count");
}
for (size_t i = 0; i < filter->scanFilterCount; i++) {
mFilters[i] = filter->scanFilters[i];
}
}
}
}
BleRequest::BleRequest(BleRequest &&other) {
*this = std::move(other);
}
BleRequest &BleRequest::operator=(BleRequest &&other) {
mInstanceId = other.mInstanceId;
mMode = other.mMode;
mReportDelayMs = other.mReportDelayMs;
mRssiThreshold = other.mRssiThreshold;
mFilters = std::move(other.mFilters);
mEnabled = other.mEnabled;
mStatus = other.mStatus;
return *this;
}
bool BleRequest::mergeWith(const BleRequest &request) {
// Only merge parameters of enabled requests.
if (!request.mEnabled) {
return false;
}
bool attributesChanged = false;
// Replace disabled request parameters.
if (!mEnabled) {
mEnabled = true;
mMode = request.mMode;
mReportDelayMs = request.mReportDelayMs;
mRssiThreshold = request.mRssiThreshold;
attributesChanged = true;
} else {
if (mMode < request.mMode) {
mMode = request.mMode;
attributesChanged = true;
}
if (mReportDelayMs > request.mReportDelayMs) {
mReportDelayMs = request.mReportDelayMs;
attributesChanged = true;
}
if (mRssiThreshold > request.mRssiThreshold) {
mRssiThreshold = request.mRssiThreshold;
attributesChanged = true;
}
}
const DynamicVector<chreBleGenericFilter> &otherFilters = request.mFilters;
for (const chreBleGenericFilter &otherFilter : otherFilters) {
bool addFilter = true;
for (const chreBleGenericFilter &filter : mFilters) {
if (filtersMatch(filter, otherFilter)) {
addFilter = false;
break;
}
}
if (addFilter) {
attributesChanged = true;
if (!mFilters.push_back(otherFilter)) {
FATAL_ERROR("Unable to merge filters");
}
}
}
return attributesChanged;
}
bool BleRequest::isEquivalentTo(const BleRequest &request) {
const DynamicVector<chreBleGenericFilter> &otherFilters = request.mFilters;
bool isEquivalent = (mEnabled && request.mEnabled && mMode == request.mMode &&
mReportDelayMs == request.mReportDelayMs &&
mRssiThreshold == request.mRssiThreshold &&
mFilters.size() == otherFilters.size());
if (isEquivalent) {
for (size_t i = 0; i < otherFilters.size(); i++) {
if (!filtersMatch(mFilters[i], otherFilters[i])) {
isEquivalent = false;
break;
}
}
}
return isEquivalent;
}
uint16_t BleRequest::getInstanceId() const {
return mInstanceId;
}
chreBleScanMode BleRequest::getMode() const {
return mMode;
}
uint32_t BleRequest::getReportDelayMs() const {
return mReportDelayMs;
}
int8_t BleRequest::getRssiThreshold() const {
return mRssiThreshold;
}
RequestStatus BleRequest::getRequestStatus() const {
return mStatus;
}
void BleRequest::setRequestStatus(RequestStatus status) {
mStatus = status;
}
const DynamicVector<chreBleGenericFilter> &BleRequest::getGenericFilters()
const {
return mFilters;
}
chreBleScanFilter BleRequest::getScanFilter() const {
return chreBleScanFilter{
mRssiThreshold, static_cast<uint8_t>(mFilters.size()), mFilters.data()};
}
bool BleRequest::isEnabled() const {
return mEnabled;
}
void BleRequest::logStateToBuffer(DebugDumpWrapper &debugDump,
bool isPlatformRequest) const {
if (!isPlatformRequest) {
debugDump.print(" instanceId=%" PRIu16 " status=%" PRIu8, mInstanceId,
static_cast<uint8_t>(mStatus));
}
debugDump.print(" %s", mEnabled ? " enable" : " disable\n");
if (mEnabled) {
debugDump.print(
" mode=%" PRIu8 " reportDelayMs=%" PRIu32 " rssiThreshold=%" PRId8,
static_cast<uint8_t>(mMode), mReportDelayMs, mRssiThreshold);
if (isPlatformRequest) {
debugDump.print(" filters=[");
for (const chreBleGenericFilter &filter : mFilters) {
debugDump.print("(type=%" PRIx8, filter.type);
if (filter.len > 0) {
debugDump.print(" data=%s dataMask=%s len=%" PRIu8 "), ",
&filter.data[0], &filter.dataMask[0], filter.len);
} else {
debugDump.print("), ");
}
}
debugDump.print("]\n");
} else {
debugDump.print(" filterCount=%" PRIu8 "\n",
static_cast<uint8_t>(mFilters.size()));
}
}
}
} // namespace chre