blob: 7eb4262e2f002d89748494994cb0aebfbd661aa8 [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 {
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) {
bool attributesChanged = false;
// Only merge parameters of enabled requests.
if (request.mEnabled) {
// Replace disabled request parameters.
if (!mEnabled) {
mEnabled = true;
mMode = request.mMode;
mReportDelayMs = request.mReportDelayMs;
mRssiThreshold = request.mRssiThreshold;
mFilters.clear();
if (!mFilters.resize(request.mFilters.size())) {
FATAL_ERROR("Unable to reserve filter count");
}
for (size_t i = 0; i < request.mFilters.size(); i++) {
mFilters[i] = request.mFilters[i];
}
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;
if (!otherFilters.empty()) {
attributesChanged = true;
size_t originalFilterSize = mFilters.size();
if (!mFilters.resize(originalFilterSize + otherFilters.size())) {
FATAL_ERROR("Unable to reserve filter count");
}
for (size_t i = 0; i < otherFilters.size(); i++) {
mFilters[originalFilterSize + i] = otherFilters[i];
}
}
}
}
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 (mFilters[i].len != otherFilters[i].len ||
mFilters[i].type != otherFilters[i].type ||
mFilters[i].data != otherFilters[i].data ||
mFilters[i].dataMask != otherFilters[i].dataMask) {
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=%" PRIu32 " 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,
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