blob: 27111e7cd6fd2c206d4d6b516793439766214d5d [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2016 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.
*
******************************************************************************/
#define LOG_TAG "bt_btif_ble_advertiser"
#include <hardware/bluetooth.h>
#include <hardware/bt_gatt.h>
#include <base/bind.h>
#include <vector>
#include "ble_advertiser.h"
#include "bta_closure_api.h"
#include "btif_common.h"
using base::Bind;
using base::Owned;
using std::vector;
extern bt_status_t do_in_jni_thread(const base::Closure& task);
namespace {
template <typename T>
class OwnedArrayWrapper {
public:
explicit OwnedArrayWrapper(T* o) : ptr_(o) {}
~OwnedArrayWrapper() { delete[] ptr_; }
T* get() const { return ptr_; }
OwnedArrayWrapper(OwnedArrayWrapper&& other) {
ptr_ = other.ptr_;
other.ptr_ = NULL;
}
private:
mutable T* ptr_;
};
template <typename T>
T* Unwrap(const OwnedArrayWrapper<T>& o) {
return o.get();
}
template <typename T>
static inline OwnedArrayWrapper<T> OwnedArray(T* o) {
return OwnedArrayWrapper<T>(o);
}
/* return the actual power in dBm based on the mapping in config file */
int8_t ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
int8_t ble_map_adv_tx_power(int tx_power_index) {
if (0 <= tx_power_index && tx_power_index < BTM_BLE_ADV_TX_POWER_MAX)
return (int8_t)ble_tx_power[tx_power_index];
return 0;
}
void bta_adv_set_data_cback(tBTA_STATUS call_status) {}
class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
~BleAdvertiserInterfaceImpl(){};
void RegisterAdvertiserCb(
base::Callback<void(uint8_t /* adv_id */, uint8_t /* status */)> cb,
uint8_t advertiser_id, uint8_t status) {
LOG(INFO) << __func__ << " status: " << +status << " , adveriser_id: " << +advertiser_id;
do_in_jni_thread(Bind(cb, advertiser_id, status));
}
void RegisterAdvertiser(
base::Callback<void(uint8_t /* advertiser_id */, uint8_t /* status */)>
cb) override {
do_in_bta_thread(
FROM_HERE, Bind(&BleAdvertisingManager::RegisterAdvertiser,
base::Unretained(BleAdvertisingManager::Get()),
Bind(&BleAdvertiserInterfaceImpl::RegisterAdvertiserCb,
base::Unretained(this), cb)));
}
void Unregister(uint8_t advertiser_id) override {
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::Unregister,
base::Unretained(BleAdvertisingManager::Get()), advertiser_id));
}
void SetData(bool set_scan_rsp, vector<uint8_t> data) override {
uint8_t* data_ptr = nullptr;
if (data.size()) {
// base::Owned will free this ptr
data_ptr = new uint8_t[data.size()];
memcpy(data_ptr, data.data(), data.size());
}
if (!set_scan_rsp) {
if (data_ptr) {
do_in_bta_thread(FROM_HERE,
Bind(&BTM_BleWriteAdvData, OwnedArray(data_ptr),
data.size(), bta_adv_set_data_cback));
} else {
do_in_bta_thread(FROM_HERE, Bind(&BTM_BleWriteAdvData, nullptr,
data.size(), bta_adv_set_data_cback));
}
} else {
if (data_ptr) {
do_in_bta_thread(FROM_HERE,
Bind(&BTM_BleWriteScanRsp, OwnedArray(data_ptr),
data.size(), bta_adv_set_data_cback));
} else {
do_in_bta_thread(FROM_HERE, Bind(&BTM_BleWriteScanRsp, nullptr,
data.size(), bta_adv_set_data_cback));
}
}
}
void EnableCb(BleAdvertiserCb cb, uint8_t status) {
LOG(INFO) << __func__ << " status: " << +status;
do_in_jni_thread(Bind(cb, status));
}
void Enable(bool start, BleAdvertiserCb cb) override {
do_in_jni_thread(Bind(&GATT_Listen, start));
cb.Run(BT_STATUS_SUCCESS);
}
void MultiAdvSetParametersCb(BleAdvertiserCb cb, uint8_t status) {
LOG(INFO) << __func__ << " status: " << +status ;
do_in_jni_thread(Bind(cb, status));
}
virtual void MultiAdvSetParameters(int advertiser_id, int min_interval,
int max_interval, int adv_type,
int chnl_map, int tx_power,
BleAdvertiserCb cb) {
tBTM_BLE_ADV_PARAMS* params = new tBTM_BLE_ADV_PARAMS;
params->adv_int_min = min_interval;
params->adv_int_max = max_interval;
params->adv_type = adv_type;
params->channel_map = chnl_map;
params->adv_filter_policy = 0;
params->tx_power = ble_map_adv_tx_power(tx_power);
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::SetParameters,
base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
base::Owned(params),
Bind(&BleAdvertiserInterfaceImpl::MultiAdvSetParametersCb,
base::Unretained(this), cb)));
}
void MultiAdvSetInstDataCb(BleAdvertiserCb cb, uint8_t advertiser_id,
uint8_t status) {
do_in_jni_thread(Bind(cb, status));
}
void MultiAdvSetInstData(int advertiser_id, bool set_scan_rsp,
vector<uint8_t> data, BleAdvertiserCb cb) override {
do_in_bta_thread(
FROM_HERE, Bind(&BleAdvertisingManager::SetData,
base::Unretained(BleAdvertisingManager::Get()),
advertiser_id, set_scan_rsp, std::move(data),
Bind(&BleAdvertiserInterfaceImpl::MultiAdvSetInstDataCb,
base::Unretained(this), cb, advertiser_id)));
}
void MultiAdvEnableTimeoutCb(BleAdvertiserCb cb, uint8_t status) {
do_in_jni_thread(Bind(cb, status));
}
void MultiAdvEnableCb(BleAdvertiserCb cb, uint8_t status) {
do_in_jni_thread(Bind(cb, status));
}
void MultiAdvEnable(uint8_t advertiser_id, bool enable, BleAdvertiserCb cb,
int timeout_s, BleAdvertiserCb timeout_cb) override {
VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id
<< " ,enable: " << enable;
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::Enable,
base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
enable, Bind(&BleAdvertiserInterfaceImpl::MultiAdvEnableCb,
base::Unretained(this), cb),
timeout_s,
Bind(&BleAdvertiserInterfaceImpl::MultiAdvEnableTimeoutCb,
base::Unretained(this), timeout_cb)));
}
};
BleAdvertiserInterface* btLeAdvertiserInstance = nullptr;
} // namespace
BleAdvertiserInterface* get_ble_advertiser_instance() {
if (btLeAdvertiserInstance == nullptr)
btLeAdvertiserInstance = new BleAdvertiserInterfaceImpl();
return btLeAdvertiserInstance;
}