blob: ff5f7cccba66b157fbf3cec15cb9a0ea743ae29c [file] [log] [blame]
/*
* Copyright 2020 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.
*/
#define LOG_TAG "bt_shim_advertiser"
#include "le_advertising_manager.h"
#include <hardware/bluetooth.h>
#include <hardware/bt_gatt.h>
#include <vector>
#include "btif/include/btif_common.h"
#include "gd/common/init_flags.h"
#include "gd/hci/acl_manager.h"
#include "gd/hci/controller.h"
#include "gd/hci/le_advertising_manager.h"
#include "gd/packet/packet_view.h"
#include "gd/storage/storage_module.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
#include "stack/include/ble_advertiser.h"
#include "stack/include/btm_api.h"
#include "types/raw_address.h"
#include <base/logging.h>
using bluetooth::hci::Address;
using bluetooth::hci::AddressType;
using bluetooth::hci::ErrorCode;
using bluetooth::hci::GapData;
using bluetooth::hci::OwnAddressType;
using std::vector;
class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
public bluetooth::hci::AdvertisingCallback {
public:
~BleAdvertiserInterfaceImpl() override{};
void Init() {
// Register callback
bluetooth::shim::GetAdvertising()->RegisterAdvertisingCallback(this);
}
// nobody use this function
void RegisterAdvertiser(IdStatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
}
void Unregister(uint8_t advertiser_id) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::shim::GetAdvertising()->RemoveAdvertiser(advertiser_id);
}
void GetOwnAddress(uint8_t advertiser_id, GetAddressCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::shim::GetAdvertising()->GetOwnAddress(advertiser_id);
}
void SetParameters(uint8_t advertiser_id, AdvertiseParameters params,
ParametersCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::hci::ExtendedAdvertisingConfig config{};
parse_parameter(config, params);
bluetooth::shim::GetAdvertising()->SetParameters(advertiser_id, config);
}
void SetData(int advertiser_id, bool set_scan_rsp, vector<uint8_t> data,
StatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
size_t offset = 0;
std::vector<GapData> advertising_data = {};
while (offset < data.size()) {
GapData gap_data;
uint8_t len = data[offset];
auto begin = data.begin() + offset;
auto end = begin + len + 1; // 1 byte for len
auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
data_copy);
GapData::Parse(&gap_data, packet.begin());
advertising_data.push_back(gap_data);
offset += len + 1; // 1 byte for len
}
bluetooth::shim::GetAdvertising()->SetData(advertiser_id, set_scan_rsp,
advertising_data);
}
void Enable(uint8_t advertiser_id, bool enable, StatusCallback cb,
uint16_t duration, uint8_t maxExtAdvEvents,
StatusCallback timeout_cb) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::shim::GetAdvertising()->EnableAdvertiser(
advertiser_id, enable, duration, maxExtAdvEvents);
}
// nobody use this function
void StartAdvertising(uint8_t advertiser_id, StatusCallback cb,
AdvertiseParameters params,
std::vector<uint8_t> advertise_data,
std::vector<uint8_t> scan_response_data, int timeout_s,
MultiAdvCb timeout_cb) override {
LOG(INFO) << __func__ << " in shim layer";
}
void StartAdvertisingSet(int reg_id, IdTxPowerStatusCallback register_cb,
AdvertiseParameters params,
std::vector<uint8_t> advertise_data,
std::vector<uint8_t> scan_response_data,
PeriodicAdvertisingParameters periodic_params,
std::vector<uint8_t> periodic_data,
uint16_t duration, uint8_t maxExtAdvEvents,
IdStatusCallback timeout_cb) {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::hci::ExtendedAdvertisingConfig config{};
parse_parameter(config, params);
bluetooth::hci::PeriodicAdvertisingParameters periodic_parameters;
periodic_parameters.max_interval = periodic_params.max_interval;
periodic_parameters.min_interval = periodic_params.min_interval;
periodic_parameters.properties =
periodic_params.periodic_advertising_properties;
config.periodic_advertising_parameters = periodic_parameters;
size_t offset = 0;
while (offset < advertise_data.size()) {
GapData gap_data;
uint8_t len = advertise_data[offset];
auto begin = advertise_data.begin() + offset;
auto end = begin + len + 1; // 1 byte for len
auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
data_copy);
GapData::Parse(&gap_data, packet.begin());
config.advertisement.push_back(gap_data);
offset += len + 1; // 1 byte for len
}
offset = 0;
while (offset < scan_response_data.size()) {
GapData gap_data;
uint8_t len = scan_response_data[offset];
auto begin = scan_response_data.begin() + offset;
auto end = begin + len + 1; // 1 byte for len
auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
data_copy);
GapData::Parse(&gap_data, packet.begin());
config.scan_response.push_back(gap_data);
offset += len + 1; // 1 byte for len
}
offset = 0;
while (offset < periodic_data.size()) {
GapData gap_data;
uint8_t len = periodic_data[offset];
auto begin = periodic_data.begin() + offset;
auto end = begin + len + 1; // 1 byte for len
auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
data_copy);
GapData::Parse(&gap_data, packet.begin());
config.periodic_data.push_back(gap_data);
offset += len + 1; // 1 byte for len
}
bluetooth::hci::AdvertiserId id =
bluetooth::shim::GetAdvertising()->ExtendedCreateAdvertiser(
reg_id, config, scan_callback, set_terminated_callback, duration,
maxExtAdvEvents, bluetooth::shim::GetGdShimHandler());
LOG(INFO) << "create advertising set, reg_id:" << reg_id
<< ", id:" << (uint16_t)id;
}
void SetPeriodicAdvertisingParameters(
int advertiser_id, PeriodicAdvertisingParameters periodic_params,
StatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::hci::PeriodicAdvertisingParameters parameters;
parameters.max_interval = periodic_params.max_interval;
parameters.min_interval = periodic_params.min_interval;
parameters.properties = periodic_params.periodic_advertising_properties;
bluetooth::shim::GetAdvertising()->SetPeriodicParameters(advertiser_id,
parameters);
}
void SetPeriodicAdvertisingData(int advertiser_id, std::vector<uint8_t> data,
StatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
size_t offset = 0;
std::vector<GapData> advertising_data = {};
while (offset < data.size()) {
GapData gap_data;
uint8_t len = data[offset];
auto begin = data.begin() + offset;
auto end = begin + len + 1; // 1 byte for len
auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
data_copy);
GapData::Parse(&gap_data, packet.begin());
advertising_data.push_back(gap_data);
offset += len + 1; // 1 byte for len
}
bluetooth::shim::GetAdvertising()->SetPeriodicData(advertiser_id,
advertising_data);
}
void SetPeriodicAdvertisingEnable(int advertiser_id, bool enable,
StatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
bluetooth::shim::GetAdvertising()->EnablePeriodicAdvertising(advertiser_id,
enable);
}
void RegisterCallbacks(AdvertisingCallbacks* callbacks) {
advertising_callbacks_ = callbacks;
}
void on_scan(Address address, AddressType address_type) {
LOG(INFO) << __func__ << " in shim layer";
}
void on_set_terminated(ErrorCode error_code, uint8_t, uint8_t) {
LOG(INFO) << __func__ << " in shim layer";
}
const bluetooth::common::Callback<void(Address, AddressType)> scan_callback =
bluetooth::common::Bind(&BleAdvertiserInterfaceImpl::on_scan,
bluetooth::common::Unretained(this));
const bluetooth::common::Callback<void(ErrorCode, uint8_t, uint8_t)>
set_terminated_callback = bluetooth::common::Bind(
&BleAdvertiserInterfaceImpl::on_set_terminated,
bluetooth::common::Unretained(this));
// AdvertisingCallback
void OnAdvertisingSetStarted(int reg_id, uint8_t advertiser_id,
int8_t tx_power,
AdvertisingStatus status) override {
do_in_jni_thread(
FROM_HERE, base::Bind(&AdvertisingCallbacks::OnAdvertisingSetStarted,
base::Unretained(advertising_callbacks_), reg_id,
advertiser_id, tx_power, status));
}
void OnAdvertisingEnabled(uint8_t advertiser_id, bool enable,
uint8_t status) {
do_in_jni_thread(FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnAdvertisingEnabled,
base::Unretained(advertising_callbacks_),
advertiser_id, enable, status));
}
void OnAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
do_in_jni_thread(FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnAdvertisingDataSet,
base::Unretained(advertising_callbacks_),
advertiser_id, status));
}
void OnScanResponseDataSet(uint8_t advertiser_id, uint8_t status) {
do_in_jni_thread(FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnScanResponseDataSet,
base::Unretained(advertising_callbacks_),
advertiser_id, status));
}
void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power,
uint8_t status) {
do_in_jni_thread(
FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnAdvertisingParametersUpdated,
base::Unretained(advertising_callbacks_), advertiser_id,
tx_power, status));
}
void OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id,
uint8_t status) {
do_in_jni_thread(
FROM_HERE,
base::Bind(
&AdvertisingCallbacks::OnPeriodicAdvertisingParametersUpdated,
base::Unretained(advertising_callbacks_), advertiser_id, status));
}
void OnPeriodicAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
do_in_jni_thread(
FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnPeriodicAdvertisingDataSet,
base::Unretained(advertising_callbacks_), advertiser_id,
status));
}
void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable,
uint8_t status) {
do_in_jni_thread(
FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnPeriodicAdvertisingEnabled,
base::Unretained(advertising_callbacks_), advertiser_id,
enable, status));
}
void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type,
bluetooth::hci::Address address) {
RawAddress raw_address = bluetooth::ToRawAddress(address);
do_in_jni_thread(FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnOwnAddressRead,
base::Unretained(advertising_callbacks_),
advertiser_id, address_type, raw_address));
}
AdvertisingCallbacks* advertising_callbacks_;
private:
void parse_parameter(bluetooth::hci::ExtendedAdvertisingConfig& config,
AdvertiseParameters params) {
config.connectable = params.advertising_event_properties & 0x01;
config.scannable = params.advertising_event_properties & 0x02;
config.legacy_pdus = params.advertising_event_properties & 0x10;
config.anonymous = params.advertising_event_properties & 0x20;
config.include_tx_power = params.advertising_event_properties & 0x40;
config.interval_min = params.min_interval;
config.interval_max = params.max_interval;
config.channel_map = params.channel_map;
config.tx_power = params.tx_power;
config.use_le_coded_phy = params.primary_advertising_phy == 0x03;
config.secondary_advertising_phy =
static_cast<bluetooth::hci::SecondaryPhyType>(
params.secondary_advertising_phy);
config.enable_scan_request_notifications =
static_cast<bluetooth::hci::Enable>(
params.scan_request_notification_enable);
// TODO set own_address_type based on address policy
config.own_address_type = OwnAddressType::RANDOM_DEVICE_ADDRESS;
}
};
BleAdvertiserInterfaceImpl* bt_le_advertiser_instance = nullptr;
BleAdvertiserInterface* bluetooth::shim::get_ble_advertiser_instance() {
if (bt_le_advertiser_instance == nullptr) {
bt_le_advertiser_instance = new BleAdvertiserInterfaceImpl();
}
return bt_le_advertiser_instance;
};
void bluetooth::shim::init_advertising_manager() {
bt_le_advertiser_instance->Init();
}