Loading system/stack/btm/ble_advertiser_hci_interface.cc +27 −14 Original line number Diff line number Diff line Loading @@ -206,12 +206,18 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface { command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; if (max_extended_advertising_events) { if (sets.size() != 1) { LOG(ERROR) << "Trying to enable multiple sets in VSC implemenetation!"; command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } SetEnableData& set = sets[0]; if (set.max_extended_advertising_events) { command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } Loading @@ -222,7 +228,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface { uint8_t* pp = param; UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_ENB); UINT8_TO_STREAM(pp, enable); UINT8_TO_STREAM(pp, handle); UINT8_TO_STREAM(pp, set.handle); SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_ENB_LEN, param, command_complete); Loading Loading @@ -403,12 +409,18 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface { HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD, command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; if (max_extended_advertising_events) { if (sets.size() != 1) { LOG(ERROR) << "Trying to enable multiple sets in legacy implemenetation!"; command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } SetEnableData& set = sets[0]; if (set.max_extended_advertising_events) { command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } Loading Loading @@ -563,23 +575,24 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface { LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN, command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; /* cmd_length = header_size + num_of_of_advertiser * size_per_advertiser */ const uint16_t cmd_length = 2 + 1 * 4; const uint16_t cmd_length = 2 + sets.size() * 4; uint8_t param[cmd_length]; memset(param, 0, cmd_length); uint8_t* pp = param; UINT8_TO_STREAM(pp, enable); UINT8_TO_STREAM(pp, 0x01); // just one set UINT8_TO_STREAM(pp, handle); UINT16_TO_STREAM(pp, duration); UINT8_TO_STREAM(pp, max_extended_advertising_events); UINT8_TO_STREAM(pp, sets.size()); for (const SetEnableData& set : sets) { UINT8_TO_STREAM(pp, set.handle); UINT16_TO_STREAM(pp, set.duration); UINT8_TO_STREAM(pp, set.max_extended_advertising_events); } SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_ENABLE, param, cmd_length, command_complete); Loading system/stack/btm/ble_advertiser_hci_interface.h +19 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define BLE_ADVERTISER_HCI_INTERFACE_H #include <base/bind.h> #include <vector> #include "stack/include/bt_types.h" /* This class is an abstraction of HCI commands used for managing Loading Loading @@ -70,9 +71,25 @@ class BleAdvertiserHciInterface { virtual void SetRandomAddress(uint8_t handle, const RawAddress& random_address, status_cb command_complete) = 0; virtual void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, struct SetEnableData { uint8_t handle; uint16_t duration; uint8_t max_extended_advertising_events; }; virtual void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) = 0; void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, status_cb command_complete) { std::vector<SetEnableData> enableData; enableData.emplace_back(SetEnableData{ .handle = handle, .duration = duration, .max_extended_advertising_events = max_extended_advertising_events}); Enable(enable, enableData, command_complete); }; virtual void SetPeriodicAdvertisingParameters(uint8_t handle, uint16_t periodic_adv_int_min, uint16_t periodic_adv_int_max, Loading system/stack/btm/btm_ble_multi_adv.cc +156 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <base/bind.h> #include <base/logging.h> #include <base/strings/string_number_conversions.h> #include <base/time/time.h> #include <string.h> #include <queue> #include <vector> Loading @@ -33,10 +34,13 @@ #include "btm_int_types.h" using base::Bind; using base::TimeDelta; using base::TimeTicks; using RegisterCb = base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>; using IdTxPowerStatusCb = base::Callback<void( uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>; using SetEnableData = BleAdvertiserHciInterface::SetEnableData; extern void btm_gen_resolvable_private_addr( base::Callback<void(uint8_t[8])> cb); Loading @@ -54,7 +58,7 @@ struct AdvertisingInstance { uint8_t advertising_event_properties; alarm_t* adv_raddr_timer; int8_t tx_power; uint16_t duration; uint16_t duration; // 1 unit is 10ms uint8_t maxExtAdvEvents; alarm_t* timeout_timer; uint8_t own_address_type; Loading @@ -62,6 +66,7 @@ struct AdvertisingInstance { MultiAdvCb timeout_cb; bool address_update_required; bool periodic_enabled; uint32_t advertising_interval; // 1 unit is 0.625 ms /* When true, advertising set is enabled, or last scheduled call to "LE Set * Extended Advertising Set Enable" is to enable this advertising set. Any Loading @@ -73,6 +78,7 @@ struct AdvertisingInstance { * command scheduled when in this state will execute when the set is disabled. */ bool enable_status; TimeTicks enable_time; bool IsEnabled() { return enable_status; } Loading Loading @@ -392,7 +398,6 @@ class BleAdvertisingManagerImpl c->maxExtAdvEvents = maxExtAdvEvents; c->timeout_cb = std::move(timeout_cb); // this code is intentionally left formatted this way to highlight the // asynchronous flow // clang-format off Loading Loading @@ -575,27 +580,27 @@ class BleAdvertisingManagerImpl void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb, uint8_t status) { MultiAdvCb myCb; if (enable && p_inst->duration) { p_inst->enable_status = enable; // TODO(jpawlowski): HCI implementation that can't do duration should // emulate it, not EnableWithTimerCb. GetHciInterface()->Enable( enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents, Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb, myCb = Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb, base::Unretained(this), p_inst->inst_id, std::move(cb), p_inst->duration, p_inst->timeout_cb)); p_inst->duration, p_inst->timeout_cb); } else { myCb = std::move(cb); if (p_inst->timeout_timer) { alarm_cancel(p_inst->timeout_timer); alarm_free(p_inst->timeout_timer); p_inst->timeout_timer = nullptr; } } if (enable) p_inst->enable_time = TimeTicks::Now(); p_inst->enable_status = enable; GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents, std::move(cb)); } p_inst->maxExtAdvEvents, std::move(myCb)); } void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params, Loading @@ -613,12 +618,14 @@ class BleAdvertisingManagerImpl return; } // TODO: disable only if was enabled, currently no use scenario needs that, // TODO: disable only if was enabled, currently no use scenario needs // that, // we always set parameters before enabling // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing)); p_inst->advertising_event_properties = p_params->advertising_event_properties; p_inst->tx_power = p_params->tx_power; p_inst->advertising_interval = p_params->adv_int_min; const RawAddress& peer_address = RawAddress::kEmpty; GetHciInterface()->SetParameters( Loading Loading @@ -804,6 +811,63 @@ class BleAdvertisingManagerImpl p_inst->address_update_required = false; } void RecomputeTimeout(AdvertisingInstance* inst, TimeTicks now) { TimeDelta duration = now - inst->enable_time; bool cb_fired = false; if (inst->duration) { int durationDone = (duration.InMilliseconds() / 10); if (durationDone + 1 >= inst->duration) { inst->enable_status = false; inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/); cb_fired = true; } else { inst->duration = inst->duration - durationDone; } } if (inst->maxExtAdvEvents && !cb_fired) { int eventsDone = (duration.InMilliseconds() / (inst->advertising_interval * 5 / 8)); if (eventsDone + 1 >= inst->maxExtAdvEvents) { inst->enable_status = false; inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/); } else { inst->maxExtAdvEvents = inst->maxExtAdvEvents - eventsDone; } } } void Suspend() { std::vector<SetEnableData> sets; for (AdvertisingInstance& inst : adv_inst) { if (!inst.in_use || !inst.enable_status) continue; if (inst.duration || inst.maxExtAdvEvents) RecomputeTimeout(&inst, TimeTicks::Now()); sets.emplace_back(SetEnableData{.handle = inst.inst_id}); } if (!sets.empty()) GetHciInterface()->Enable(false, sets, Bind(DoNothing)); } void Resume() override { std::vector<SetEnableData> sets; for (const AdvertisingInstance& inst : adv_inst) { if (inst.in_use && inst.enable_status) { sets.emplace_back(SetEnableData{ .handle = inst.inst_id, .duration = inst.duration, .max_extended_advertising_events = inst.maxExtAdvEvents}); } } if (!sets.empty()) GetHciInterface()->Enable(true, sets, Bind(DoNothing)); } void OnAdvertisingSetTerminated( uint8_t status, uint8_t advertising_handle, uint16_t connection_handle, uint8_t num_completed_extended_adv_events) override { Loading Loading @@ -835,10 +899,15 @@ class BleAdvertisingManagerImpl if (p_inst->in_use == true) { // TODO(jpawlowski): we don't really allow to do directed advertising // right now. This should probably be removed, check with Andre. if ((p_inst->advertising_event_properties & 0x0C) == 0 /* directed advertising bits not set */) { GetHciInterface()->Enable(true, advertising_handle, 0x00, 0x00, Bind(DoNothing)); if ((p_inst->advertising_event_properties & 0x0C) == 0) { /* directed advertising bits not set */ RecomputeTimeout(p_inst, TimeTicks::Now()); if (p_inst->enable_status) { GetHciInterface()->Enable(true, advertising_handle, p_inst->duration, p_inst->maxExtAdvEvents, Bind(DoNothing)); } } else { /* mark directed adv as disabled if adv has been stopped */ p_inst->in_use = false; Loading Loading @@ -907,3 +976,72 @@ void btm_ble_multi_adv_cleanup(void) { BleAdvertisingManager::CleanUp(); BleAdvertiserHciInterface::CleanUp(); } // TODO(jpawlowski): Find a nicer way to test RecomputeTimeout without exposing // AdvertisingInstance bool timeout_triggered = false; void test_timeout_cb(uint8_t status) { timeout_triggered = true; } // verify that if duration passed, or is about to pass, recomputation will shut // down the advertiser completly void testRecomputeTimeout1() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(111); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.duration = 12 /*120ms*/; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == true); timeout_triggered = false; CHECK(test1.enable_status == false); } // verify that duration and maxExtAdvEvents are properly adjusted when // recomputing. void testRecomputeTimeout2() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(250); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.duration = 50 /*500ms*/; test1.maxExtAdvEvents = 50; test1.advertising_interval = 16 /* 10 ms */; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == false); CHECK(test1.enable_status == true); CHECK(test1.duration == 25); CHECK(test1.maxExtAdvEvents == 25); } // verify that if maxExtAdvEvents were sent, or are close to end, recomputation // wil shut down the advertiser completly void testRecomputeTimeout3() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(495); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.maxExtAdvEvents = 50; test1.advertising_interval = 16 /* 10 ms */; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == true); timeout_triggered = false; CHECK(test1.enable_status == false); } system/stack/btm/btm_ble_privacy.cc +15 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "bt_target.h" #if (BLE_PRIVACY_SPT == TRUE) #include "ble_advertiser.h" #include "bt_types.h" #include "btm_int.h" #include "btu.h" Loading Loading @@ -526,6 +527,13 @@ bool btm_ble_suspend_resolving_list_activity(void) { p_ble_cb->suspended_rl_state |= BTM_BLE_RL_ADV; } // If it's non-VSC implementation, suspend if (BleAdvertisingManager::Get() && (controller_get_interface()->supports_ble_extended_advertising() || BTM_BleMaxMultiAdvInstanceCount() == 0)) { BleAdvertisingManager::Get()->Suspend(); } if (BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { btm_ble_stop_scan(); p_ble_cb->suspended_rl_state |= BTM_BLE_RL_SCAN; Loading Loading @@ -553,6 +561,13 @@ void btm_ble_resume_resolving_list_activity(void) { if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_ADV) btm_ble_start_adv(); // If it's non-VSC implementation, resume if (BleAdvertisingManager::Get() && (controller_get_interface()->supports_ble_extended_advertising() || BTM_BleMaxMultiAdvInstanceCount() == 0)) { BleAdvertisingManager::Get()->Resume(); } if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_SCAN) btm_ble_start_scan(); if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_INIT) btm_ble_resume_bg_conn(); Loading system/stack/include/ble_advertiser.h +10 −3 Original line number Diff line number Diff line Loading @@ -146,6 +146,13 @@ class BleAdvertisingManager { /* This function disable a Multi-ADV instance */ virtual void Unregister(uint8_t inst_id) = 0; /* When resolving list is used, we need to suspend and resume all advertising * instances for the time of operation. Suspend() saves current state, * Resume() resumes the advertising. */ virtual void Suspend() = 0; virtual void Resume() = 0; /* This method is a member of BleAdvertiserHciInterface, and is exposed here * just for tests. It should never be called from upper layers*/ virtual void OnAdvertisingSetTerminated( Loading Loading
system/stack/btm/ble_advertiser_hci_interface.cc +27 −14 Original line number Diff line number Diff line Loading @@ -206,12 +206,18 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface { command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; if (max_extended_advertising_events) { if (sets.size() != 1) { LOG(ERROR) << "Trying to enable multiple sets in VSC implemenetation!"; command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } SetEnableData& set = sets[0]; if (set.max_extended_advertising_events) { command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } Loading @@ -222,7 +228,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface { uint8_t* pp = param; UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_ENB); UINT8_TO_STREAM(pp, enable); UINT8_TO_STREAM(pp, handle); UINT8_TO_STREAM(pp, set.handle); SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_ENB_LEN, param, command_complete); Loading Loading @@ -403,12 +409,18 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface { HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD, command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; if (max_extended_advertising_events) { if (sets.size() != 1) { LOG(ERROR) << "Trying to enable multiple sets in legacy implemenetation!"; command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } SetEnableData& set = sets[0]; if (set.max_extended_advertising_events) { command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); return; } Loading Loading @@ -563,23 +575,24 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface { LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN, command_complete); } void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) override { VLOG(1) << __func__; /* cmd_length = header_size + num_of_of_advertiser * size_per_advertiser */ const uint16_t cmd_length = 2 + 1 * 4; const uint16_t cmd_length = 2 + sets.size() * 4; uint8_t param[cmd_length]; memset(param, 0, cmd_length); uint8_t* pp = param; UINT8_TO_STREAM(pp, enable); UINT8_TO_STREAM(pp, 0x01); // just one set UINT8_TO_STREAM(pp, handle); UINT16_TO_STREAM(pp, duration); UINT8_TO_STREAM(pp, max_extended_advertising_events); UINT8_TO_STREAM(pp, sets.size()); for (const SetEnableData& set : sets) { UINT8_TO_STREAM(pp, set.handle); UINT16_TO_STREAM(pp, set.duration); UINT8_TO_STREAM(pp, set.max_extended_advertising_events); } SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_ENABLE, param, cmd_length, command_complete); Loading
system/stack/btm/ble_advertiser_hci_interface.h +19 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define BLE_ADVERTISER_HCI_INTERFACE_H #include <base/bind.h> #include <vector> #include "stack/include/bt_types.h" /* This class is an abstraction of HCI commands used for managing Loading Loading @@ -70,9 +71,25 @@ class BleAdvertiserHciInterface { virtual void SetRandomAddress(uint8_t handle, const RawAddress& random_address, status_cb command_complete) = 0; virtual void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, struct SetEnableData { uint8_t handle; uint16_t duration; uint8_t max_extended_advertising_events; }; virtual void Enable(uint8_t enable, std::vector<SetEnableData> sets, status_cb command_complete) = 0; void Enable(uint8_t enable, uint8_t handle, uint16_t duration, uint8_t max_extended_advertising_events, status_cb command_complete) { std::vector<SetEnableData> enableData; enableData.emplace_back(SetEnableData{ .handle = handle, .duration = duration, .max_extended_advertising_events = max_extended_advertising_events}); Enable(enable, enableData, command_complete); }; virtual void SetPeriodicAdvertisingParameters(uint8_t handle, uint16_t periodic_adv_int_min, uint16_t periodic_adv_int_max, Loading
system/stack/btm/btm_ble_multi_adv.cc +156 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <base/bind.h> #include <base/logging.h> #include <base/strings/string_number_conversions.h> #include <base/time/time.h> #include <string.h> #include <queue> #include <vector> Loading @@ -33,10 +34,13 @@ #include "btm_int_types.h" using base::Bind; using base::TimeDelta; using base::TimeTicks; using RegisterCb = base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>; using IdTxPowerStatusCb = base::Callback<void( uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>; using SetEnableData = BleAdvertiserHciInterface::SetEnableData; extern void btm_gen_resolvable_private_addr( base::Callback<void(uint8_t[8])> cb); Loading @@ -54,7 +58,7 @@ struct AdvertisingInstance { uint8_t advertising_event_properties; alarm_t* adv_raddr_timer; int8_t tx_power; uint16_t duration; uint16_t duration; // 1 unit is 10ms uint8_t maxExtAdvEvents; alarm_t* timeout_timer; uint8_t own_address_type; Loading @@ -62,6 +66,7 @@ struct AdvertisingInstance { MultiAdvCb timeout_cb; bool address_update_required; bool periodic_enabled; uint32_t advertising_interval; // 1 unit is 0.625 ms /* When true, advertising set is enabled, or last scheduled call to "LE Set * Extended Advertising Set Enable" is to enable this advertising set. Any Loading @@ -73,6 +78,7 @@ struct AdvertisingInstance { * command scheduled when in this state will execute when the set is disabled. */ bool enable_status; TimeTicks enable_time; bool IsEnabled() { return enable_status; } Loading Loading @@ -392,7 +398,6 @@ class BleAdvertisingManagerImpl c->maxExtAdvEvents = maxExtAdvEvents; c->timeout_cb = std::move(timeout_cb); // this code is intentionally left formatted this way to highlight the // asynchronous flow // clang-format off Loading Loading @@ -575,27 +580,27 @@ class BleAdvertisingManagerImpl void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb, uint8_t status) { MultiAdvCb myCb; if (enable && p_inst->duration) { p_inst->enable_status = enable; // TODO(jpawlowski): HCI implementation that can't do duration should // emulate it, not EnableWithTimerCb. GetHciInterface()->Enable( enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents, Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb, myCb = Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb, base::Unretained(this), p_inst->inst_id, std::move(cb), p_inst->duration, p_inst->timeout_cb)); p_inst->duration, p_inst->timeout_cb); } else { myCb = std::move(cb); if (p_inst->timeout_timer) { alarm_cancel(p_inst->timeout_timer); alarm_free(p_inst->timeout_timer); p_inst->timeout_timer = nullptr; } } if (enable) p_inst->enable_time = TimeTicks::Now(); p_inst->enable_status = enable; GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents, std::move(cb)); } p_inst->maxExtAdvEvents, std::move(myCb)); } void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params, Loading @@ -613,12 +618,14 @@ class BleAdvertisingManagerImpl return; } // TODO: disable only if was enabled, currently no use scenario needs that, // TODO: disable only if was enabled, currently no use scenario needs // that, // we always set parameters before enabling // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing)); p_inst->advertising_event_properties = p_params->advertising_event_properties; p_inst->tx_power = p_params->tx_power; p_inst->advertising_interval = p_params->adv_int_min; const RawAddress& peer_address = RawAddress::kEmpty; GetHciInterface()->SetParameters( Loading Loading @@ -804,6 +811,63 @@ class BleAdvertisingManagerImpl p_inst->address_update_required = false; } void RecomputeTimeout(AdvertisingInstance* inst, TimeTicks now) { TimeDelta duration = now - inst->enable_time; bool cb_fired = false; if (inst->duration) { int durationDone = (duration.InMilliseconds() / 10); if (durationDone + 1 >= inst->duration) { inst->enable_status = false; inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/); cb_fired = true; } else { inst->duration = inst->duration - durationDone; } } if (inst->maxExtAdvEvents && !cb_fired) { int eventsDone = (duration.InMilliseconds() / (inst->advertising_interval * 5 / 8)); if (eventsDone + 1 >= inst->maxExtAdvEvents) { inst->enable_status = false; inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/); } else { inst->maxExtAdvEvents = inst->maxExtAdvEvents - eventsDone; } } } void Suspend() { std::vector<SetEnableData> sets; for (AdvertisingInstance& inst : adv_inst) { if (!inst.in_use || !inst.enable_status) continue; if (inst.duration || inst.maxExtAdvEvents) RecomputeTimeout(&inst, TimeTicks::Now()); sets.emplace_back(SetEnableData{.handle = inst.inst_id}); } if (!sets.empty()) GetHciInterface()->Enable(false, sets, Bind(DoNothing)); } void Resume() override { std::vector<SetEnableData> sets; for (const AdvertisingInstance& inst : adv_inst) { if (inst.in_use && inst.enable_status) { sets.emplace_back(SetEnableData{ .handle = inst.inst_id, .duration = inst.duration, .max_extended_advertising_events = inst.maxExtAdvEvents}); } } if (!sets.empty()) GetHciInterface()->Enable(true, sets, Bind(DoNothing)); } void OnAdvertisingSetTerminated( uint8_t status, uint8_t advertising_handle, uint16_t connection_handle, uint8_t num_completed_extended_adv_events) override { Loading Loading @@ -835,10 +899,15 @@ class BleAdvertisingManagerImpl if (p_inst->in_use == true) { // TODO(jpawlowski): we don't really allow to do directed advertising // right now. This should probably be removed, check with Andre. if ((p_inst->advertising_event_properties & 0x0C) == 0 /* directed advertising bits not set */) { GetHciInterface()->Enable(true, advertising_handle, 0x00, 0x00, Bind(DoNothing)); if ((p_inst->advertising_event_properties & 0x0C) == 0) { /* directed advertising bits not set */ RecomputeTimeout(p_inst, TimeTicks::Now()); if (p_inst->enable_status) { GetHciInterface()->Enable(true, advertising_handle, p_inst->duration, p_inst->maxExtAdvEvents, Bind(DoNothing)); } } else { /* mark directed adv as disabled if adv has been stopped */ p_inst->in_use = false; Loading Loading @@ -907,3 +976,72 @@ void btm_ble_multi_adv_cleanup(void) { BleAdvertisingManager::CleanUp(); BleAdvertiserHciInterface::CleanUp(); } // TODO(jpawlowski): Find a nicer way to test RecomputeTimeout without exposing // AdvertisingInstance bool timeout_triggered = false; void test_timeout_cb(uint8_t status) { timeout_triggered = true; } // verify that if duration passed, or is about to pass, recomputation will shut // down the advertiser completly void testRecomputeTimeout1() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(111); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.duration = 12 /*120ms*/; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == true); timeout_triggered = false; CHECK(test1.enable_status == false); } // verify that duration and maxExtAdvEvents are properly adjusted when // recomputing. void testRecomputeTimeout2() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(250); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.duration = 50 /*500ms*/; test1.maxExtAdvEvents = 50; test1.advertising_interval = 16 /* 10 ms */; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == false); CHECK(test1.enable_status == true); CHECK(test1.duration == 25); CHECK(test1.maxExtAdvEvents == 25); } // verify that if maxExtAdvEvents were sent, or are close to end, recomputation // wil shut down the advertiser completly void testRecomputeTimeout3() { auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get(); TimeTicks start = TimeTicks::Now(); TimeTicks end = start + TimeDelta::FromMilliseconds(495); AdvertisingInstance test1(0); test1.enable_status = true; test1.enable_time = start; test1.maxExtAdvEvents = 50; test1.advertising_interval = 16 /* 10 ms */; test1.timeout_cb = Bind(&test_timeout_cb); manager->RecomputeTimeout(&test1, end); CHECK(timeout_triggered == true); timeout_triggered = false; CHECK(test1.enable_status == false); }
system/stack/btm/btm_ble_privacy.cc +15 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "bt_target.h" #if (BLE_PRIVACY_SPT == TRUE) #include "ble_advertiser.h" #include "bt_types.h" #include "btm_int.h" #include "btu.h" Loading Loading @@ -526,6 +527,13 @@ bool btm_ble_suspend_resolving_list_activity(void) { p_ble_cb->suspended_rl_state |= BTM_BLE_RL_ADV; } // If it's non-VSC implementation, suspend if (BleAdvertisingManager::Get() && (controller_get_interface()->supports_ble_extended_advertising() || BTM_BleMaxMultiAdvInstanceCount() == 0)) { BleAdvertisingManager::Get()->Suspend(); } if (BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { btm_ble_stop_scan(); p_ble_cb->suspended_rl_state |= BTM_BLE_RL_SCAN; Loading Loading @@ -553,6 +561,13 @@ void btm_ble_resume_resolving_list_activity(void) { if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_ADV) btm_ble_start_adv(); // If it's non-VSC implementation, resume if (BleAdvertisingManager::Get() && (controller_get_interface()->supports_ble_extended_advertising() || BTM_BleMaxMultiAdvInstanceCount() == 0)) { BleAdvertisingManager::Get()->Resume(); } if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_SCAN) btm_ble_start_scan(); if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_INIT) btm_ble_resume_bg_conn(); Loading
system/stack/include/ble_advertiser.h +10 −3 Original line number Diff line number Diff line Loading @@ -146,6 +146,13 @@ class BleAdvertisingManager { /* This function disable a Multi-ADV instance */ virtual void Unregister(uint8_t inst_id) = 0; /* When resolving list is used, we need to suspend and resume all advertising * instances for the time of operation. Suspend() saves current state, * Resume() resumes the advertising. */ virtual void Suspend() = 0; virtual void Resume() = 0; /* This method is a member of BleAdvertiserHciInterface, and is exposed here * just for tests. It should never be called from upper layers*/ virtual void OnAdvertisingSetTerminated( Loading