167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// 267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// Copyright (C) 2015 Google, Inc. 367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// 467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// Licensed under the Apache License, Version 2.0 (the "License"); 567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// you may not use this file except in compliance with the License. 667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// You may obtain a copy of the License at: 767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// 867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// http://www.apache.org/licenses/LICENSE-2.0 967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// 1067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// Unless required by applicable law or agreed to in writing, software 1167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// distributed under the License is distributed on an "AS IS" BASIS, 1267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// See the License for the specific language governing permissions and 1467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// limitations under the License. 1567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// 1667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 1767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include "service/low_energy_advertiser.h" 1867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 1974ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski#include <base/bind.h> 2067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include <base/logging.h> 2167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 2267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include "service/adapter.h" 2367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include "service/logging_helpers.h" 2467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include "stack/include/bt_types.h" 2567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include "stack/include/hcidefs.h" 2667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 2767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiusing std::lock_guard; 2867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiusing std::mutex; 2967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 3067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskinamespace bluetooth { 3167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 3267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskinamespace { 3367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 3467d5a2523314d9757b2472c3e828dbc1015df4feJakub PawlowskiBLEStatus GetBLEStatus(int status) { 35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (status == BT_STATUS_FAIL) return BLE_STATUS_FAILURE; 3667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 3767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return static_cast<BLEStatus>(status); 3867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 3967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 4067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// The Bluetooth Core Specification defines time interval (e.g. Page Scan 4167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// Interval, Advertising Interval, etc) units as 0.625 milliseconds (or 1 4267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// Baseband slot). The HAL advertising functions expect the interval in this 4367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// unit. This function maps an AdvertiseSettings::Mode value to the 4467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// corresponding time unit. 4567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiint GetAdvertisingIntervalUnit(AdvertiseSettings::Mode mode) { 4667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski int ms; 4767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 4867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski switch (mode) { 49911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case AdvertiseSettings::MODE_BALANCED: 50911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ms = kAdvertisingIntervalMediumMs; 51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 52911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case AdvertiseSettings::MODE_LOW_LATENCY: 53911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ms = kAdvertisingIntervalLowMs; 54911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case AdvertiseSettings::MODE_LOW_POWER: 5667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // Fall through 57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson default: 58911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ms = kAdvertisingIntervalHighMs; 59911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 6067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 6167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 6267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // Convert milliseconds to Bluetooth units. 6367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return (ms * 1000) / 625; 6467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 6567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 66e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowskiint8_t GetAdvertisingTxPower(AdvertiseSettings::TxPowerLevel tx_power) { 67e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski int8_t power; 68e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski 69e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski switch (tx_power) { 70e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski case AdvertiseSettings::TX_POWER_LEVEL_ULTRA_LOW: 71e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski power = -21; 72e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski break; 73e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski case AdvertiseSettings::TX_POWER_LEVEL_LOW: 74e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski power = -15; 75e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski break; 76e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski case AdvertiseSettings::TX_POWER_LEVEL_MEDIUM: 77e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski power = -7; 78e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski break; 79e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski case AdvertiseSettings::TX_POWER_LEVEL_HIGH: 80e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski // Fall through 81e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski default: 82e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski power = 1; 83e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski break; 84e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski } 85e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski 86e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski return power; 87e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski} 88e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski 8967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid GetAdvertiseParams(const AdvertiseSettings& settings, bool has_scan_rsp, 90a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski AdvertiseParameters* out_params) { 9167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski CHECK(out_params); 9267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 9367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski out_params->min_interval = GetAdvertisingIntervalUnit(settings.mode()); 9467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski out_params->max_interval = 9567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski out_params->min_interval + kAdvertisingIntervalDeltaUnit; 9667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 9767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (settings.connectable()) 98e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->advertising_event_properties = 99e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski kAdvertisingEventTypeLegacyConnectable; 10067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski else if (has_scan_rsp) 101e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->advertising_event_properties = 102e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski kAdvertisingEventTypeLegacyScannable; 10367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski else 104e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->advertising_event_properties = 105e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski kAdvertisingEventTypeLegacyNonConnectable; 10667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 107a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski out_params->channel_map = kAdvertisingChannelAll; 108e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->tx_power = GetAdvertisingTxPower(settings.tx_power_level()); 109e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski 110e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski // TODO: expose those new setting through AdvertiseSettings 111e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->primary_advertising_phy = 0x01; 112e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->secondary_advertising_phy = 0x01; 113e0750ca056c8561d4a5b7ea14430049bf1d82fc1Jakub Pawlowski out_params->scan_request_notification_enable = 0; 11467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 11567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 11674ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowskivoid DoNothing(uint8_t status) {} 11774ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski 11867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} // namespace 11967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 12067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// LowEnergyAdvertiser implementation 12167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// ======================================================== 12267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 123911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonLowEnergyAdvertiser::LowEnergyAdvertiser(const UUID& uuid, int advertiser_id) 124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson : app_identifier_(uuid), 12567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski advertiser_id_(advertiser_id), 12667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_started_(false), 12767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_start_callback_(nullptr), 128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson adv_stop_callback_(nullptr) {} 12967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 13067d5a2523314d9757b2472c3e828dbc1015df4feJakub PawlowskiLowEnergyAdvertiser::~LowEnergyAdvertiser() { 13167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // Automatically unregister the advertiser. 13267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski VLOG(1) << "LowEnergyAdvertiser unregistering advertiser: " << advertiser_id_; 13367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 13467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // Stop advertising and ignore the result. 135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface()->Enable( 1365204c62f137de9b6c2834391fd329457d3fdbc84Jakub Pawlowski advertiser_id_, false, base::Bind(&DoNothing), 0, 0, 1375204c62f137de9b6c2834391fd329457d3fdbc84Jakub Pawlowski base::Bind(&DoNothing)); 138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface()->Unregister( 139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson advertiser_id_); 14067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 14167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 14267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiser::StartAdvertising(const AdvertiseSettings& settings, 143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const AdvertiseData& advertise_data, 144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const AdvertiseData& scan_response, 145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const StatusCallback& callback) { 14667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski VLOG(2) << __func__; 14767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski lock_guard<mutex> lock(adv_fields_lock_); 14867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 14967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (IsAdvertisingStarted()) { 15067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(WARNING) << "Already advertising"; 15167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 15267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 15367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 15467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (IsStartingAdvertising()) { 15567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(WARNING) << "StartAdvertising already pending"; 15667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 15767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 15867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 15967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (!advertise_data.IsValid()) { 16067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(ERROR) << "Invalid advertising data"; 16167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 16267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 16367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 16467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (!scan_response.IsValid()) { 16567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(ERROR) << "Invalid scan response data"; 16667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 16767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 16867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 16967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski advertise_settings_ = settings; 17067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 171a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski AdvertiseParameters params; 172a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski GetAdvertiseParams(settings, !scan_response.data().empty(), ¶ms); 17367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 174a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski hal::BluetoothGattInterface::Get() 175a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski ->GetAdvertiserHALInterface() 176a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski ->StartAdvertising( 17767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski advertiser_id_, 178a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski base::Bind(&LowEnergyAdvertiser::EnableCallback, 179a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski base::Unretained(this), true, advertiser_id_), 180a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski params, advertise_data.data(), scan_response.data(), 181a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski settings.timeout().InSeconds(), 182a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski base::Bind(&LowEnergyAdvertiser::EnableCallback, 183a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski base::Unretained(this), false, advertiser_id_)); 184a75087effcc8b4a5869fb1673d43b0b9ff6fb8f1Jakub Pawlowski ; 18567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 18667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_start_callback_.reset(new StatusCallback(callback)); 18767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return true; 18867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 18967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 19067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiser::StopAdvertising(const StatusCallback& callback) { 19167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski VLOG(2) << __func__; 19267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski lock_guard<mutex> lock(adv_fields_lock_); 19367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 19467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (!IsAdvertisingStarted()) { 19567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(ERROR) << "Not advertising"; 19667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 19767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 19867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 19967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (IsStoppingAdvertising()) { 20067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(ERROR) << "StopAdvertising already pending"; 20167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 20267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 20367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface()->Enable( 205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson advertiser_id_, false, 206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson base::Bind(&LowEnergyAdvertiser::EnableCallback, base::Unretained(this), 207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson false, advertiser_id_), 2085204c62f137de9b6c2834391fd329457d3fdbc84Jakub Pawlowski 0, 0, base::Bind(&LowEnergyAdvertiser::EnableCallback, 2095204c62f137de9b6c2834391fd329457d3fdbc84Jakub Pawlowski base::Unretained(this), false, advertiser_id_)); 21067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 21167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // OK to set this at the end since we're still holding |adv_fields_lock_|. 21267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_stop_callback_.reset(new StatusCallback(callback)); 21367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 21467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return true; 21567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 21667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 21767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiser::IsAdvertisingStarted() const { 21867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return adv_started_.load(); 21967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 22067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 22167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiser::IsStartingAdvertising() const { 22267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return !IsAdvertisingStarted() && adv_start_callback_; 22367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 22467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 22567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiser::IsStoppingAdvertising() const { 22667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return IsAdvertisingStarted() && adv_stop_callback_; 22767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 22867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 22967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiconst UUID& LowEnergyAdvertiser::GetAppIdentifier() const { 23067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return app_identifier_; 23167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 23267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonint LowEnergyAdvertiser::GetInstanceId() const { return advertiser_id_; } 23467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid LowEnergyAdvertiser::EnableCallback(bool enable, uint8_t advertiser_id, 236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t status) { 237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (advertiser_id != advertiser_id_) return; 23867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 23967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski lock_guard<mutex> lock(adv_fields_lock_); 24067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 24173679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski VLOG(1) << __func__ << "advertiser_id: " << advertiser_id 242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson << " status: " << status << " enable: " << enable; 24367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 24473679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski if (enable) { 24573679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski CHECK(adv_start_callback_); 24673679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski CHECK(!adv_stop_callback_); 24773679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski 24873679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski // Terminate operation in case of error. 24973679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski if (status != BT_STATUS_SUCCESS) { 25073679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski LOG(ERROR) << "Failed to enable multi-advertising"; 25173679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski InvokeAndClearStartCallback(GetBLEStatus(status)); 25273679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski return; 25373679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski } 25473679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski 25573679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski // All pending tasks are complete. Report success. 25673679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski adv_started_ = true; 25773679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski InvokeAndClearStartCallback(BLE_STATUS_SUCCESS); 25867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 25967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } else { 26073679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski CHECK(!adv_start_callback_); 26173679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski CHECK(adv_stop_callback_); 26273679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski 26373679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski if (status == BT_STATUS_SUCCESS) { 264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson VLOG(1) << "Multi-advertising stopped for advertiser_id: " 265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson << advertiser_id; 26673679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski adv_started_ = false; 26773679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski } else { 26873679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski LOG(ERROR) << "Failed to stop multi-advertising"; 26973679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski } 27067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 27173679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski InvokeAndClearStopCallback(GetBLEStatus(status)); 27273679d01c70fe84921fc4718e99d4b02af8cc5a9Jakub Pawlowski } 27367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 27467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 27567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid LowEnergyAdvertiser::InvokeAndClearStartCallback(BLEStatus status) { 27667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // We allow NULL callbacks. 277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (*adv_start_callback_) (*adv_start_callback_)(status); 27867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 27967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_start_callback_ = nullptr; 28067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 28167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 28267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid LowEnergyAdvertiser::InvokeAndClearStopCallback(BLEStatus status) { 28367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // We allow NULL callbacks. 284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (*adv_stop_callback_) (*adv_stop_callback_)(status); 28567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 28667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski adv_stop_callback_ = nullptr; 28767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 28867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 28967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// LowEnergyAdvertiserFactory implementation 29067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// ======================================================== 29167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 292911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonLowEnergyAdvertiserFactory::LowEnergyAdvertiserFactory() {} 29367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 294911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonLowEnergyAdvertiserFactory::~LowEnergyAdvertiserFactory() {} 29567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 29667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskibool LowEnergyAdvertiserFactory::RegisterInstance( 29774ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski const UUID& app_uuid, const RegisterCallback& callback) { 29874ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski VLOG(1) << __func__; 29967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski lock_guard<mutex> lock(pending_calls_lock_); 30067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 30174ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski if (pending_calls_.find(app_uuid) != pending_calls_.end()) { 30267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski LOG(ERROR) << "Low-Energy advertiser with given UUID already registered - " 30374ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski << "UUID: " << app_uuid.ToString(); 30467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return false; 30567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 30667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 30774ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski BleAdvertiserInterface* hal_iface = 30867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface(); 30967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 31074ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski VLOG(1) << __func__ << " calling register!"; 31174ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski hal_iface->RegisterAdvertiser( 31274ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski base::Bind(&LowEnergyAdvertiserFactory::RegisterAdvertiserCallback, 31374ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski base::Unretained(this), callback, app_uuid)); 31474ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski VLOG(1) << __func__ << " call finished!"; 31567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 31674ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski pending_calls_.insert(app_uuid); 31767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 31867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return true; 31967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 32067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 32167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid LowEnergyAdvertiserFactory::RegisterAdvertiserCallback( 32274ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski const RegisterCallback& callback, const UUID& app_uuid, 32374ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski uint8_t advertiser_id, uint8_t status) { 32474ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski VLOG(1) << __func__; 32567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski lock_guard<mutex> lock(pending_calls_lock_); 32667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 32774ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski auto iter = pending_calls_.find(app_uuid); 32867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (iter == pending_calls_.end()) { 32974ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski VLOG(1) << "Ignoring callback for unknown app_id: " << app_uuid.ToString(); 33067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski return; 33167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 33267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 33367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // No need to construct a advertiser if the call wasn't successful. 33467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski std::unique_ptr<LowEnergyAdvertiser> advertiser; 33567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski BLEStatus result = BLE_STATUS_FAILURE; 33667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski if (status == BT_STATUS_SUCCESS) { 33774ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski advertiser.reset(new LowEnergyAdvertiser(app_uuid, advertiser_id)); 33867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 33967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski result = BLE_STATUS_SUCCESS; 34067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski } 34167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 34267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski // Notify the result via the result callback. 34374ef54b440dc50bb25f587783d80fe5a37070e4aJakub Pawlowski callback(result, app_uuid, std::move(advertiser)); 34467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 34567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski pending_calls_.erase(iter); 34667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} 34767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski 34867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski} // namespace bluetooth 349