Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40e57b13 authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Add scan structures

Added the ScanFilter, ScanSettings, ScanResult structures that are
used in the BLE scan API.

Bug: 25744656
Change-Id: Id1bb28e7ebe85fd40013876aa097e1d0f0a4e471
parent 79324061
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ btserviceCommonSrc := \
	common/bluetooth/advertise_data.cpp \
	common/bluetooth/advertise_settings.cpp \
	common/bluetooth/gatt_identifier.cpp \
	common/bluetooth/scan_filter.cpp \
	common/bluetooth/scan_result.cpp \
	common/bluetooth/scan_settings.cpp \
	common/bluetooth/util/address_helper.cpp \
	common/bluetooth/util/atomic_string.cpp \
	common/bluetooth/uuid.cpp
+156 −9
Original line number Diff line number Diff line
@@ -16,10 +16,17 @@

#include "service/common/bluetooth/binder/parcel_helpers.h"

#include "service/common/bluetooth/util/address_helper.h"

using android::Parcel;

using bluetooth::AdvertiseData;
using bluetooth::AdvertiseSettings;
using bluetooth::GattIdentifier;
using bluetooth::ScanFilter;
using bluetooth::ScanResult;
using bluetooth::ScanSettings;
using bluetooth::UUID;

namespace ipc {
namespace binder {
@@ -85,13 +92,13 @@ std::unique_ptr<AdvertiseSettings> CreateAdvertiseSettingsFromParcel(
      new AdvertiseSettings(mode, timeout, tx_power, connectable));
}

void WriteUUIDToParcel(const bluetooth::UUID& uuid, android::Parcel* parcel) {
void WriteUUIDToParcel(const UUID& uuid, android::Parcel* parcel) {
  // The scheme used by android.os.ParcelUuid is to wrote the most significant
  // bits first as one 64-bit integer, followed by the least significant bits in
  // a second 64-bit integer. This is the same as writing the raw-bytes in
  // sequence, but we don't want to assume any host-endianness here. So follow
  // the same scheme and use the same Parcel APIs.
  bluetooth::UUID::UUID128Bit bytes = uuid.GetFullBigEndian();
  UUID::UUID128Bit bytes = uuid.GetFullBigEndian();

  uint64_t most_sig_bits =
      ((((uint64_t) bytes[0]) << 56) |
@@ -117,9 +124,9 @@ void WriteUUIDToParcel(const bluetooth::UUID& uuid, android::Parcel* parcel) {
  parcel->writeUint64(least_sig_bits);
}

std::unique_ptr<bluetooth::UUID> CreateUUIDFromParcel(
std::unique_ptr<UUID> CreateUUIDFromParcel(
    const android::Parcel& parcel) {
  bluetooth::UUID::UUID128Bit bytes;
  UUID::UUID128Bit bytes;

  uint64_t most_sig_bits = parcel.readUint64();
  uint64_t least_sig_bits = parcel.readUint64();
@@ -142,11 +149,11 @@ std::unique_ptr<bluetooth::UUID> CreateUUIDFromParcel(
  bytes[14] = (least_sig_bits >> 8) & 0xFF;
  bytes[15] = least_sig_bits & 0xFF;

  return std::unique_ptr<bluetooth::UUID>(new bluetooth::UUID(bytes));
  return std::unique_ptr<UUID>(new UUID(bytes));
}

void WriteGattIdentifierToParcel(
    const bluetooth::GattIdentifier& gatt_id,
    const GattIdentifier& gatt_id,
    android::Parcel* parcel) {
  parcel->writeCString(gatt_id.device_address().c_str());
  parcel->writeInt32(gatt_id.is_primary());
@@ -160,7 +167,7 @@ void WriteGattIdentifierToParcel(
  parcel->writeInt32(gatt_id.descriptor_instance_id());
}

std::unique_ptr<bluetooth::GattIdentifier> CreateGattIdentifierFromParcel(
std::unique_ptr<GattIdentifier> CreateGattIdentifierFromParcel(
    const android::Parcel& parcel) {
  std::string device_address = parcel.readCString();
  bool is_primary = parcel.readInt32();
@@ -173,12 +180,152 @@ std::unique_ptr<bluetooth::GattIdentifier> CreateGattIdentifierFromParcel(
  int char_id = parcel.readInt32();
  int desc_id = parcel.readInt32();

  return std::unique_ptr<bluetooth::GattIdentifier>(
      new bluetooth::GattIdentifier(
  return std::unique_ptr<GattIdentifier>(
      new GattIdentifier(
          device_address, is_primary,
          *service_uuid, *char_uuid, *desc_uuid,
          service_id, char_id, desc_id));
}

void WriteScanFilterToParcel(
    const ScanFilter& filter,
    android::Parcel* parcel) {
  bool has_name = !filter.device_name().empty();
  parcel->writeInt32(has_name ? 1 : 0);
  if (has_name)
    parcel->writeCString(filter.device_name().c_str());

  bool has_address = !filter.device_address().empty();
  parcel->writeInt32(has_address ? 1 : 0);
  if (has_address)
    parcel->writeCString(filter.device_address().c_str());

  parcel->writeInt32(filter.service_uuid() ? 1 : 0);
  if (filter.service_uuid()) {
    WriteUUIDToParcel(*filter.service_uuid(), parcel);
    parcel->writeInt32(filter.service_uuid_mask() ? 1 : 0);
    if (filter.service_uuid_mask())
      WriteUUIDToParcel(*filter.service_uuid_mask(), parcel);
  }

  // TODO(armansito): Support service and manufacturer data.
}

std::unique_ptr<ScanFilter> CreateScanFilterFromParcel(
    const android::Parcel& parcel) {
  std::string device_name;
  if (parcel.readInt32() == 1)
    device_name = parcel.readCString();

  std::string device_address;
  if (parcel.readInt32() == 1)
    device_address = parcel.readCString();

  std::unique_ptr<UUID> service_uuid, service_uuid_mask;
  if (parcel.readInt32() == 1) {
    service_uuid = CreateUUIDFromParcel(parcel);
    if (parcel.readInt32() == 1)
      service_uuid_mask = CreateUUIDFromParcel(parcel);
  }

  // TODO(armansito): Support service and manufacturer data.

  std::unique_ptr<ScanFilter> filter(new ScanFilter());

  filter->set_device_name(device_name);

  if (!filter->SetDeviceAddress(device_address))
    return nullptr;

  if (!service_uuid)
    return filter;

  if (service_uuid_mask)
    filter->SetServiceUuidWithMask(*service_uuid, *service_uuid_mask);
  else
    filter->SetServiceUuid(*service_uuid);

  return filter;
}

void WriteScanSettingsToParcel(
    const ScanSettings& settings,
    android::Parcel* parcel) {
  parcel->writeInt32(settings.mode());
  parcel->writeInt32(settings.callback_type());
  parcel->writeInt32(settings.result_type());
  parcel->writeInt64(settings.report_delay().InMilliseconds());
  parcel->writeInt32(settings.match_mode());
  parcel->writeInt32(settings.match_count_per_filter());
}

std::unique_ptr<ScanSettings> CreateScanSettingsFromParcel(
    const android::Parcel& parcel) {
  ScanSettings::Mode mode =
      static_cast<ScanSettings::Mode>(parcel.readInt32());
  ScanSettings::CallbackType callback_type =
      static_cast<ScanSettings::CallbackType>(parcel.readInt32());
  ScanSettings::ResultType result_type =
      static_cast<ScanSettings::ResultType>(parcel.readInt32());
  base::TimeDelta report_delay = base::TimeDelta::FromMilliseconds(
      parcel.readInt64());
  ScanSettings::MatchMode match_mode =
      static_cast<ScanSettings::MatchMode>(parcel.readInt32());
  ScanSettings::MatchCount match_count_per_filter =
      static_cast<ScanSettings::MatchCount>(parcel.readInt32());

  return std::unique_ptr<ScanSettings>(new ScanSettings(
      mode, callback_type, result_type, report_delay,
      match_mode, match_count_per_filter));
}

void WriteScanResultToParcel(
    const bluetooth::ScanResult& scan_result,
    android::Parcel* parcel) {
  // The Java framework code conditionally inserts 1 or 0 to indicate if the
  // device adress and the scan record fields are present, based on whether the
  // Java object is null. We do something similar here for consistency, although
  // the native definition of ScanResult requires a valid BD_ADDR.
  if (util::IsAddressValid(scan_result.device_address())) {
    parcel->writeInt32(1);
    parcel->writeCString(scan_result.device_address().c_str());
  } else {
    parcel->writeInt32(0);
  }

  if (!scan_result.scan_record().empty()) {
    parcel->writeInt32(1);
    parcel->writeByteArray(scan_result.scan_record().size(),
                          scan_result.scan_record().data());
  } else {
    parcel->writeInt32(0);
  }

  parcel->writeInt32(scan_result.rssi());
}

std::unique_ptr<bluetooth::ScanResult> CreateScanResultFromParcel(
    const android::Parcel& parcel) {
  std::string device_address;
  if (parcel.readInt32())
    device_address = parcel.readCString();

  std::vector<uint8_t> scan_record;
  if (parcel.readInt32()) {
    int record_len = parcel.readInt32();
    if (record_len != -1) {
      uint8_t bytes[record_len];
      parcel.read(bytes, record_len);

      scan_record = std::vector<uint8_t>(bytes, bytes + record_len);
    }
  }

  int rssi = parcel.readInt32();

  return std::unique_ptr<ScanResult>(new ScanResult(
      device_address, scan_record, rssi));
}

}  // namespace binder
}  // namespace ipc
+33 −0
Original line number Diff line number Diff line
@@ -23,11 +23,17 @@
#include <bluetooth/advertise_data.h>
#include <bluetooth/advertise_settings.h>
#include <bluetooth/gatt_identifier.h>
#include <bluetooth/scan_filter.h>
#include <bluetooth/scan_result.h>
#include <bluetooth/scan_settings.h>
#include <bluetooth/uuid.h>

namespace ipc {
namespace binder {

// Java Parcel meta-data constants.
const int kParcelValList = 11;

// Helpers for converting bluetooth::AdvertiseData to/from Parcel

void WriteAdvertiseDataToParcel(
@@ -62,5 +68,32 @@ void WriteGattIdentifierToParcel(
std::unique_ptr<bluetooth::GattIdentifier> CreateGattIdentifierFromParcel(
    const android::Parcel& parcel);

// Helpers for converting bluetooth::ScanFilter to/from Parcel

void WriteScanFilterToParcel(
    const bluetooth::ScanFilter& filter,
    android::Parcel* parcel);

std::unique_ptr<bluetooth::ScanFilter> CreateScanFilterFromParcel(
    const android::Parcel& parcel);

// Helpers for converting bluetooth::ScanSettings to/from Parcel

void WriteScanSettingsToParcel(
    const bluetooth::ScanSettings& settings,
    android::Parcel* parcel);

std::unique_ptr<bluetooth::ScanSettings> CreateScanSettingsFromParcel(
    const android::Parcel& parcel);

// Helpers for converting bluetooth::ScanResult to/from Parcel

void WriteScanResultToParcel(
    const bluetooth::ScanResult& scan_result,
    android::Parcel* parcel);

std::unique_ptr<bluetooth::ScanResult> CreateScanResultFromParcel(
    const android::Parcel& parcel);

}  // namespace binder
}  // namespace ipc
+98 −0
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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 "service/common/bluetooth/scan_filter.h"

#include "service/common/bluetooth/util/address_helper.h"

namespace bluetooth {

ScanFilter::ScanFilter(const ScanFilter& other) {
  device_name_ = other.device_name_;
  device_address_ = other.device_address_;

  if (other.service_uuid_)
    service_uuid_.reset(new UUID(*other.service_uuid_));

  if (other.service_uuid_mask_)
    service_uuid_mask_.reset(new UUID(*other.service_uuid_mask_));
}

ScanFilter& ScanFilter::operator=(const ScanFilter& other) {
  device_name_ = other.device_name_;
  device_address_ = other.device_address_;

  if (other.service_uuid_)
    service_uuid_.reset(new UUID(*other.service_uuid_));
  else
    service_uuid_ = nullptr;

  if (other.service_uuid_mask_)
    service_uuid_mask_.reset(new UUID(*other.service_uuid_mask_));
  else
    service_uuid_mask_ = nullptr;

  return *this;
}

bool ScanFilter::SetDeviceAddress(const std::string& device_address) {
  if (!util::IsAddressValid(device_address))
    return false;

  device_address_ = device_address;
  return true;
}

void ScanFilter::SetServiceUuid(const UUID& service_uuid) {
  service_uuid_.reset(new UUID(service_uuid));
  service_uuid_mask_.reset();
}

void ScanFilter::SetServiceUuidWithMask(const UUID& service_uuid,
                                        const UUID& mask) {
  service_uuid_.reset(new UUID(service_uuid));
  service_uuid_mask_.reset(new UUID(mask));
}

bool ScanFilter::operator==(const ScanFilter& rhs) const {
  if (device_name_ != rhs.device_name_)
    return false;

  if (device_address_ != rhs.device_address_)
    return false;

  // Both must be either NULL or non-NULL. If only one of them is NULL, then
  // return false.
  if (!!service_uuid_ != !!rhs.service_uuid_)
    return false;

  if (service_uuid_ && rhs.service_uuid_ &&
      *service_uuid_ != *rhs.service_uuid_)
    return false;

  // Both must be either NULL or non-NULL. If only one of them is NULL, then
  // return false.
  if (!!service_uuid_mask_ != !!rhs.service_uuid_mask_)
    return false;

  if (service_uuid_mask_ && rhs.service_uuid_mask_ &&
      *service_uuid_mask_ != *rhs.service_uuid_mask_)
    return false;

  return true;
}

}  // namespace bluetooth
+77 −0
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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.
//

#pragma once

#include <memory>

#include <bluetooth/uuid.h>

namespace bluetooth {

// Used for filtering scan results by allowing clients to restrict scan results
// to only those that are of interest to them.
class ScanFilter {
 public:
  ScanFilter() = default;
  ~ScanFilter() = default;

  // Copy constructor and assignment operator.
  ScanFilter(const ScanFilter& other);
  ScanFilter& operator=(const ScanFilter& other);

  // The device name used while filtering scan results.
  const std::string& device_name() const { return device_name_; }
  void set_device_name(const std::string& name) { device_name_ = name; }

  // The device address used while filtering scan results. Address should be in
  // the XX:XX:XX:XX:XX:XX where X is a hexadecimal digit.
  const std::string& device_address() const { return device_address_; }

  // Sets the device address used for filtering. Returns false if
  // |device_address| is in an illegal format.
  bool SetDeviceAddress(const std::string& device_address);

  // The service UUID and its mask used while filtering scan results. See
  // SetServiceUuidWithMask for what this mask does. The raw pointer returned
  // from these getters belongs to the ScanFilter object. nullptr will be
  // returned if these fields have not been set on this filter.
  UUID* service_uuid() const { return service_uuid_.get(); }
  UUID* service_uuid_mask() const { return service_uuid_mask_.get(); }

  // Sets the service UUID for this filter.
  void SetServiceUuid(const UUID& service_uuid);

  // Sets the service UUID for this filter with a 128-bit mask. The mask allows
  // the caller to partially filter scanned service UUIDs. For any of the
  // 128-bits of a UUID, set the corresponding bit in the mask to 1 to match the
  // advertised value, and 0 to ignore that bit.
  void SetServiceUuidWithMask(const UUID& service_uuid, const UUID& mask);

  // Comparison operator.
  bool operator==(const ScanFilter& rhs) const;

 private:
  std::string device_name_;
  std::string device_address_;

  std::unique_ptr<UUID> service_uuid_;
  std::unique_ptr<UUID> service_uuid_mask_;

  // TODO(armansito): Add service and manufacturer data filter fields.
};

}  // namespace bluetooth
Loading