/* * 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 #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 &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 &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 &BleRequest::getGenericFilters() const { return mFilters; } chreBleScanFilter BleRequest::getScanFilter() const { return chreBleScanFilter{ mRssiThreshold, static_cast(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(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(mFilters.size())); } } } } // namespace chre