Loading system/gd/hci/Android.bp +3 −2 Original line number Diff line number Diff line Loading @@ -2,13 +2,14 @@ filegroup { name: "BluetoothHciSources", srcs: [ "acl_manager.cc", "classic_security_manager.cc", "controller.cc", "address.cc", "classic_security_manager.cc", "class_of_device.cc", "controller.cc", "device.cc", "device_database.cc", "hci_layer.cc", "le_advertising_manager.cc", ], } Loading system/gd/hci/hci_packets.pdl +139 −22 Original line number Diff line number Diff line Loading @@ -1802,8 +1802,7 @@ packet ReadExtendedInquiryResponseComplete : CommandComplete (command_op_code = packet WriteExtendedInquiryResponse : CommandPacket (op_code = WRITE_EXTENDED_INQUIRY_RESPONSE) { fec_required : FecRequired, extended_inquiry_response : GapData[], //_payload_, // Zero padding to be 240 octets // Should it be GapData[240] ? _padding_[244], // Zero padding to be 240 octets (GapData[]) + 2 (opcode) + 1 (size) + 1 (FecRequired) } packet WriteExtendedInquiryResponseComplete : CommandComplete (command_op_code = WRITE_EXTENDED_INQUIRY_RESPONSE) { Loading Loading @@ -2197,7 +2196,7 @@ packet LeReadLocalSupportedFeaturesComplete : CommandComplete (command_op_code = le_features : 64, } packet LeSetRandomAddress : CommandPacket (op_code = LE_SET_RANDOM_ADDRESS) { packet LeSetRandomAddress : LeAdvertisingCommand (op_code = LE_SET_RANDOM_ADDRESS) { random_address : Address, } Loading @@ -2220,7 +2219,7 @@ enum AdvertisingEventType : 8 { ADV_DIRECT_IND = 0x01, ADV_SCAN_IND = 0x02, ADV_NONCONN_IND = 0x03, SCAN_RSP = 0x04, ADV_DIRECT_IND_LOW = 0x04, } enum AddressType : 8 { Loading @@ -2231,15 +2230,14 @@ enum AddressType : 8 { } packet LeSetAdvertisingParameters : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_PARAMETERS) { advertising_interval_min : 16, advertising_interval_max : 16, advertising_type : AdvertisingEventType, interval_min : 16, interval_max : 16, type : AdvertisingEventType, own_address_type : AddressType, peer_address_type : PeerAddressType, peer_address : Address, advertising_channel_map : 8, connection_filter_policy : AdvertisingFilterPolicy, scan_filter_policy : AdvertisingFilterPolicy, channel_map : 8, filter_policy : AdvertisingFilterPolicy, _reserved_ : 6, } Loading @@ -2258,7 +2256,7 @@ packet LeReadAdvertisingChannelTxPowerComplete : CommandComplete (command_op_cod packet LeSetAdvertisingData : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _payload_, // Zero padding to 31 bytes of advertising_data _padding_[31], // Zero padding to 31 bytes of advertising_data } packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ADVERTISING_DATA) { Loading @@ -2268,7 +2266,7 @@ packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ packet LeSetScanResponseData : LeAdvertisingCommand (op_code = LE_SET_SCAN_RESPONSE_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _payload_, // Zero padding to 31 bytes of advertising_data _padding_[31], // Zero padding to 31 bytes of advertising_data } packet LeSetScanResponseDataComplete : CommandComplete (command_op_code = LE_SET_SCAN_RESPONSE_DATA) { Loading Loading @@ -2730,16 +2728,85 @@ packet LeGetVendorCapabilitiesComplete098 : LeGetVendorCapabilitiesComplete096 { bluetooth_quality_report_support: 8 } packet LeMultiAdvt : VendorCommand (op_code = LE_MULTI_ADVT) { _payload_, // placeholder (unimplemented) enum SubOcf : 8 { SET_ADVT_PARAM = 0x01, SET_ADVT_DATA = 0x02, SET_ADVT_SCAN_RESP = 0x03, SET_ADVT_RANDOM_ADDR = 0x04, SET_ADVT_ENABLE = 0x05, } packet LeMultiAdvt : LeAdvertisingCommand (op_code = LE_MULTI_ADVT) { sub_cmd : SubOcf, _body_, } packet LeMultiAdvtParamComplete : CommandComplete (command_op_code = LE_MULTI_ADVT) { status : ErrorCode, sub_cmd : SubOcf, } packet LeMultiAdvtParam : LeMultiAdvt (sub_cmd = SET_ADVT_PARAM) { interval_min : 16, interval_max : 16, type : AdvertisingEventType, own_address_type : AddressType, peer_address_type : PeerAddressType, peer_address : Address, channel_map : 8, filter_policy : AdvertisingFilterPolicy, _reserved_ : 6, instance : 8, tx_power : 8, } packet LeMultiAdvtParamSetData : LeMultiAdvt (sub_cmd = SET_ADVT_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _padding_[31], // Zero padding to 31 bytes of advertising_data advertising_instance : 8, } packet LeMultiAdvtParamSetScanResp : LeMultiAdvt (sub_cmd = SET_ADVT_SCAN_RESP) { _size_(advertising_data) : 8, advertising_data : GapData[], _padding_[31], // Zero padding to 31 bytes of advertising_data advertising_instance : 8, } packet LeMultiAdvtParamSetRandomAddr : LeMultiAdvt (sub_cmd = SET_ADVT_RANDOM_ADDR) { random_address : Address, advertising_instance : 8, } packet LeMultiAdvtParamSetEnable : LeMultiAdvt (sub_cmd = SET_ADVT_ENABLE) { advertising_enable : Enable, // Default DISABLED advertising_instance : 8, } packet LeBatchScan : VendorCommand (op_code = LE_BATCH_SCAN) { _payload_, // placeholder (unimplemented) } enum ApcfOpcode : 8 { ENABLE = 0x00, SET_FILTERING_PARAMETERS = 0x01, BROADCASTER_ADDRESS = 0x02, SERVICE_UUID = 0x03, SERVICE_SOLICITATION_UUID = 0x04, LOCAL_NAME = 0x05, MANUFACTURER_DATA = 0x06, SERVICE_DATA = 0x07, } packet LeAdvFilter : VendorCommand (op_code = LE_ADV_FILTER) { _payload_, // placeholder (unimplemented) apcf_opcode : ApcfOpcode, _body_, } packet LeAdvFilterComplete : CommandComplete (command_op_code = LE_ADV_FILTER) { status : ErrorCode, apcf_opcode : ApcfOpcode, } packet LeTrackAdv : VendorCommand (op_code = LE_TRACK_ADV) { Loading Loading @@ -3138,8 +3205,8 @@ struct LeAdvertisingReport { } packet LeAdvertisingReport : LeMetaEvent (subevent_code = ADVERTISING_REPORT) { _count_(le_advertising_reports) : 8, le_advertising_reports : LeAdvertisingReport[], _count_(advertising_reports) : 8, advertising_reports : LeAdvertisingReport[], } packet LeConnectionUpdateComplete : LeMetaEvent (subevent_code = CONNECTION_UPDATE_COMPLETE) { Loading Loading @@ -3214,6 +3281,7 @@ enum DirectAdvertisingAddressType : 8 { RANDOM_DEVICE_ADDRESS = 0x01, PUBLIC_IDENTITY_ADDRESS = 0x02, RANDOM_IDENTITY_ADDRESS = 0x03, CONTROLLER_UNABLE_TO_RESOLVE = 0xFE, NO_ADDRESS = 0xFF, } Loading @@ -3235,16 +3303,59 @@ struct LeDirectedAdvertisingReport { } packet LeDirectedAdvertisingReport : LeMetaEvent (subevent_code = DIRECTED_ADVERTISING_REPORT) { _count_(le_directed_advertising_reports) : 8, le_directed_advertising_reports : LeDirectedAdvertisingReport[], _count_(advertising_reports) : 8, advertising_reports : LeDirectedAdvertisingReport[], } packet LePhyUpdateComplete : LeMetaEvent (subevent_code = PHY_UPDATE_COMPLETE) { _payload_, // placeholder (unimplemented) } enum DataStatus : 2 { COMPLETE = 0x0, CONTINUING = 0x1, TRUNCATED = 0x2, RESERVED = 0x3, } enum PrimaryPhyType : 8 { LE_1M = 0x01, LE_CODED = 0x03, } enum SecondaryPhyType : 8 { NO_PACKETS = 0x00, LE_1M = 0x01, LE_2M = 0x02, LE_CODED = 0x03, } struct LeExtendedAdvertisingReport { connectable : 1, scannable : 1, directed : 1, scan_response : 1, data_status : DataStatus, _reserved_ : 10, address_type : DirectAdvertisingAddressType, address : Address, primary_phy : PrimaryPhyType, secondary_phy : SecondaryPhyType, advertising_sid : 4, // SID subfield in the ADI field _reserved_ : 4, tx_power : 8, rssi : 8, // -127 to +20 (0x7F means not available) periodic_advertising_interval : 16, // 0x006 to 0xFFFF (7.5 ms to 82s) direct_address_type : DirectAdvertisingAddressType, direct_address : Address, _size_(advertising_data) : 8, advertising_data : GapData[], } packet LeExtendedAdvertisingReport : LeMetaEvent (subevent_code = EXTENDED_ADVERTISING_REPORT) { _payload_, // placeholder (unimplemented) _count_(advertising_reports) : 8, advertising_reports : LeExtendedAdvertisingReport[], } packet LePeriodicAdvertisingSyncEstablished : LeMetaEvent (subevent_code = PERIODIC_ADVERTISING_SYNC_ESTABLISHED) { Loading @@ -3263,9 +3374,15 @@ packet LeScanTimeout : LeMetaEvent (subevent_code = SCAN_TIMEOUT) { } packet LeAdvertisingSetTerminated : LeMetaEvent (subevent_code = ADVERTISING_SET_TERMINATED) { _payload_, // placeholder (unimplemented) status : ErrorCode, advertising_handle : 8, connection_handle : 12, _reserved_ : 4, num_completed_extended_advertising_events : 8, } packet LeScanRequestReceived : LeMetaEvent (subevent_code = SCAN_REQUEST_RECEIVED) { _payload_, // placeholder (unimplemented) advertising_handle : 8, scanner_address_type : AddressType, scanner_address : Address, } system/gd/hci/hci_packets_test.cc +15 −2 Original line number Diff line number Diff line Loading @@ -229,13 +229,14 @@ std::vector<uint8_t> pixel_3_xl_write_extended_inquiry_response_no_uuids_just_ei pixel_3_xl_write_extended_inquiry_response_no_uuids.end()}; TEST(HciPacketsTest, testWriteExtendedInquiryResponse) { std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(pixel_3_xl_write_extended_inquiry_response); PacketView<kLittleEndian> packet_bytes_view(packet_bytes); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = WriteExtendedInquiryResponseView::Create(CommandPacketView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); auto gap_data = view.GetExtendedInquiryResponse(); ASSERT_GE(gap_data.size(), 4); ASSERT_EQ(gap_data[0].data_type_, GapDataType::COMPLETE_LOCAL_NAME); ASSERT_EQ(gap_data[0].data_.size(), 10); ASSERT_EQ(gap_data[1].data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS); Loading @@ -244,6 +245,18 @@ TEST(HciPacketsTest, testWriteExtendedInquiryResponse) { ASSERT_EQ(gap_data[2].data_.size(), 0); ASSERT_EQ(gap_data[3].data_type_, GapDataType::COMPLETE_LIST_128_BIT_UUIDS); ASSERT_EQ(gap_data[3].data_.size(), 128); std::vector<GapData> no_padding{gap_data.begin(), gap_data.begin() + 4}; auto builder = WriteExtendedInquiryResponseBuilder::Create(view.GetFecRequired(), no_padding); std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); BitInserter it(*packet_bytes); builder->Serialize(it); EXPECT_EQ(packet_bytes->size(), view_bytes->size()); for (size_t i = 0; i < view_bytes->size(); i++) { ASSERT_EQ(packet_bytes->at(i), view_bytes->at(i)); } } // TODO: Revisit reflection tests for EIR Loading system/gd/hci/le_advertising_interface.h +1 −6 Original line number Diff line number Diff line Loading @@ -37,13 +37,8 @@ class LeAdvertisingInterface { common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) = 0; static constexpr hci::SubeventCode LeAdvertisingEvents[] = { hci::SubeventCode::ADVERTISING_REPORT, hci::SubeventCode::DIRECTED_ADVERTISING_REPORT, hci::SubeventCode::EXTENDED_ADVERTISING_REPORT, hci::SubeventCode::PERIODIC_ADVERTISING_REPORT, hci::SubeventCode::PERIODIC_ADVERTISING_SYNC_ESTABLISHED, hci::SubeventCode::PERIODIC_ADVERTISING_SYNC_LOST, hci::SubeventCode::SCAN_REQUEST_RECEIVED, hci::SubeventCode::ADVERTISING_SET_TERMINATED, }; }; } // namespace hci Loading system/gd/hci/le_advertising_manager.cc 0 → 100644 +262 −0 Original line number Diff line number Diff line /* * Copyright 2019 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. */ #include <memory> #include <mutex> #include "hci/controller.h" #include "hci/hci_layer.h" #include "hci/hci_packets.h" #include "hci/le_advertising_interface.h" #include "hci/le_advertising_manager.h" #include "module.h" #include "os/handler.h" #include "os/log.h" namespace bluetooth { namespace hci { const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); }); struct Advertiser { os::Handler* handler; common::Callback<void(Address, AddressType)> scan_callback; common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback; }; struct LeAdvertisingManager::impl { impl(Module* module, os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) : registered_handler_(nullptr), module_(module), module_handler_(handler), hci_layer_(hci_layer), controller_(controller), le_advertising_interface_(nullptr), num_instances_(0) {} void start() { le_advertising_interface_ = hci_layer_->GetLeAdvertisingInterface( common::Bind(&LeAdvertisingManager::impl::handle_event, common::Unretained(this)), module_handler_); num_instances_ = controller_->GetControllerLeNumberOfSupportedAdverisingSets(); } size_t GetNumberOfAdvertisingInstances() const { return num_instances_; } void handle_event(LeMetaEventView event) { switch (event.GetSubeventCode()) { case hci::SubeventCode::SCAN_REQUEST_RECEIVED: handle_scan_request(LeScanRequestReceivedView::Create(event)); break; case hci::SubeventCode::ADVERTISING_SET_TERMINATED: handle_set_terminated(LeAdvertisingSetTerminatedView::Create(event)); break; default: LOG_INFO("Unknown subevent in scanner %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str()); } } void handle_scan_request(LeScanRequestReceivedView event_view) { if (!event_view.IsValid()) { LOG_INFO("Dropping invalid scan request event"); return; } registered_handler_->Post( common::BindOnce(scan_callback_, event_view.GetScannerAddress(), event_view.GetScannerAddressType())); } void handle_set_terminated(LeAdvertisingSetTerminatedView event_view) { if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } registered_handler_->Post(common::BindOnce(set_terminated_callback_, event_view.GetStatus(), event_view.GetAdvertisingHandle(), event_view.GetNumCompletedExtendedAdvertisingEvents())); } AdvertiserId allocate_advertiser() { AdvertiserId id = 0; { std::unique_lock lock(id_mutex_); while (id < num_instances_ && advertising_sets_.count(id) == 0) { id++; } } if (id == num_instances_) { return kInvalidId; } return id; } void remove_advertiser(AdvertiserId id) { std::unique_lock lock(id_mutex_); if (advertising_sets_.count(id) == 0) { return; } advertising_sets_.erase(id); } void create_advertiser(AdvertiserId id, const AdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { advertising_sets_[id].scan_callback = scan_callback; advertising_sets_[id].set_terminated_callback = set_terminated_callback; advertising_sets_[id].handler = handler; if (!controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) { le_advertising_interface_->EnqueueCommand( hci::LeSetAdvertisingParametersBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetRandomAddressBuilder::Create(config.random_address), common::BindOnce(impl::check_enable_status), module_handler_); if (!config.scan_response.empty()) { le_advertising_interface_->EnqueueCommand(hci::LeSetScanResponseDataBuilder::Create(config.scan_response), common::BindOnce(impl::check_enable_status), module_handler_); } le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement), common::BindOnce(impl::check_enable_status), module_handler_); return; } le_advertising_interface_->EnqueueCommand( hci::LeMultiAdvtParamBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED), common::BindOnce(impl::check_enable_status), module_handler_); } void create_extended_advertiser(AdvertiserId id, const ExtendedAdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { if (!controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) { create_advertiser(id, config, scan_callback, set_terminated_callback, handler); return; } else { LOG_ALWAYS_FATAL("LE_SET_EXTENDED_ADVERTISING_PARAMETERS isn't implemented."); } /* le_advertising_interface_->EnqueueCommand(hci::LeSetExtendedAdvertisingParametersBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_enable_status), module_handler_); */ advertising_sets_[id].scan_callback = scan_callback; advertising_sets_[id].set_terminated_callback = set_terminated_callback; advertising_sets_[id].handler = handler; } void stop_advertising(AdvertiserId advertising_set) { if (advertising_sets_.find(advertising_set) == advertising_sets_.end()) { LOG_INFO("Unknown advertising set %u", advertising_set); return; } le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED), common::BindOnce(impl::check_enable_status), module_handler_); std::unique_lock lock(id_mutex_); advertising_sets_.erase(advertising_set); } common::Callback<void(Address, AddressType)> scan_callback_; common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback_; os::Handler* registered_handler_; Module* module_; os::Handler* module_handler_; hci::HciLayer* hci_layer_; hci::Controller* controller_; hci::LeAdvertisingInterface* le_advertising_interface_; std::map<AdvertiserId, Advertiser> advertising_sets_; std::mutex id_mutex_; size_t num_instances_; static void check_enable_status(CommandCompleteView view) { ASSERT(view.IsValid()); auto status_view = LeSetAdvertisingEnableCompleteView::Create(view); ASSERT(status_view.IsValid()); if (status_view.GetStatus() != ErrorCode::SUCCESS) { LOG_INFO("SetEnable returned status %s", ErrorCodeText(status_view.GetStatus()).c_str()); return; } } }; const AdvertiserId LeAdvertisingManager::kInvalidId = -1; LeAdvertisingManager::LeAdvertisingManager() { pimpl_ = std::make_unique<impl>(this, GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>()); } void LeAdvertisingManager::ListDependencies(ModuleList* list) { list->add<hci::HciLayer>(); list->add<hci::Controller>(); } void LeAdvertisingManager::Start() { pimpl_->start(); } void LeAdvertisingManager::Stop() { pimpl_.reset(); } size_t LeAdvertisingManager::GetNumberOfAdvertisingInstances() const { return pimpl_->GetNumberOfAdvertisingInstances(); } AdvertiserId LeAdvertisingManager::CreateAdvertiser( const AdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { if (config.peer_address == Address::kEmpty) { if (config.address_type == hci::AddressType::PUBLIC_IDENTITY_ADDRESS || config.address_type == hci::AddressType::RANDOM_IDENTITY_ADDRESS) { return kInvalidId; } if (config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND || config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND_LOW) { return kInvalidId; } } AdvertiserId id = pimpl_->allocate_advertiser(); if (id == kInvalidId) { return id; } GetHandler()->Post(common::BindOnce(&impl::create_advertiser, common::Unretained(pimpl_.get()), id, config, scan_callback, set_terminated_callback, handler)); return id; } AdvertiserId LeAdvertisingManager::CreateAdvertiser( const ExtendedAdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { AdvertiserId id = pimpl_->allocate_advertiser(); if (id == kInvalidId) { return id; } // Add error checking here GetHandler()->Post(common::BindOnce(&impl::create_extended_advertiser, common::Unretained(pimpl_.get()), id, config, scan_callback, set_terminated_callback, handler)); return id; } void LeAdvertisingManager::RemoveAdvertiser(AdvertiserId id) { pimpl_->remove_advertiser(id); } } // namespace hci } // namespace bluetooth No newline at end of file Loading
system/gd/hci/Android.bp +3 −2 Original line number Diff line number Diff line Loading @@ -2,13 +2,14 @@ filegroup { name: "BluetoothHciSources", srcs: [ "acl_manager.cc", "classic_security_manager.cc", "controller.cc", "address.cc", "classic_security_manager.cc", "class_of_device.cc", "controller.cc", "device.cc", "device_database.cc", "hci_layer.cc", "le_advertising_manager.cc", ], } Loading
system/gd/hci/hci_packets.pdl +139 −22 Original line number Diff line number Diff line Loading @@ -1802,8 +1802,7 @@ packet ReadExtendedInquiryResponseComplete : CommandComplete (command_op_code = packet WriteExtendedInquiryResponse : CommandPacket (op_code = WRITE_EXTENDED_INQUIRY_RESPONSE) { fec_required : FecRequired, extended_inquiry_response : GapData[], //_payload_, // Zero padding to be 240 octets // Should it be GapData[240] ? _padding_[244], // Zero padding to be 240 octets (GapData[]) + 2 (opcode) + 1 (size) + 1 (FecRequired) } packet WriteExtendedInquiryResponseComplete : CommandComplete (command_op_code = WRITE_EXTENDED_INQUIRY_RESPONSE) { Loading Loading @@ -2197,7 +2196,7 @@ packet LeReadLocalSupportedFeaturesComplete : CommandComplete (command_op_code = le_features : 64, } packet LeSetRandomAddress : CommandPacket (op_code = LE_SET_RANDOM_ADDRESS) { packet LeSetRandomAddress : LeAdvertisingCommand (op_code = LE_SET_RANDOM_ADDRESS) { random_address : Address, } Loading @@ -2220,7 +2219,7 @@ enum AdvertisingEventType : 8 { ADV_DIRECT_IND = 0x01, ADV_SCAN_IND = 0x02, ADV_NONCONN_IND = 0x03, SCAN_RSP = 0x04, ADV_DIRECT_IND_LOW = 0x04, } enum AddressType : 8 { Loading @@ -2231,15 +2230,14 @@ enum AddressType : 8 { } packet LeSetAdvertisingParameters : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_PARAMETERS) { advertising_interval_min : 16, advertising_interval_max : 16, advertising_type : AdvertisingEventType, interval_min : 16, interval_max : 16, type : AdvertisingEventType, own_address_type : AddressType, peer_address_type : PeerAddressType, peer_address : Address, advertising_channel_map : 8, connection_filter_policy : AdvertisingFilterPolicy, scan_filter_policy : AdvertisingFilterPolicy, channel_map : 8, filter_policy : AdvertisingFilterPolicy, _reserved_ : 6, } Loading @@ -2258,7 +2256,7 @@ packet LeReadAdvertisingChannelTxPowerComplete : CommandComplete (command_op_cod packet LeSetAdvertisingData : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _payload_, // Zero padding to 31 bytes of advertising_data _padding_[31], // Zero padding to 31 bytes of advertising_data } packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ADVERTISING_DATA) { Loading @@ -2268,7 +2266,7 @@ packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ packet LeSetScanResponseData : LeAdvertisingCommand (op_code = LE_SET_SCAN_RESPONSE_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _payload_, // Zero padding to 31 bytes of advertising_data _padding_[31], // Zero padding to 31 bytes of advertising_data } packet LeSetScanResponseDataComplete : CommandComplete (command_op_code = LE_SET_SCAN_RESPONSE_DATA) { Loading Loading @@ -2730,16 +2728,85 @@ packet LeGetVendorCapabilitiesComplete098 : LeGetVendorCapabilitiesComplete096 { bluetooth_quality_report_support: 8 } packet LeMultiAdvt : VendorCommand (op_code = LE_MULTI_ADVT) { _payload_, // placeholder (unimplemented) enum SubOcf : 8 { SET_ADVT_PARAM = 0x01, SET_ADVT_DATA = 0x02, SET_ADVT_SCAN_RESP = 0x03, SET_ADVT_RANDOM_ADDR = 0x04, SET_ADVT_ENABLE = 0x05, } packet LeMultiAdvt : LeAdvertisingCommand (op_code = LE_MULTI_ADVT) { sub_cmd : SubOcf, _body_, } packet LeMultiAdvtParamComplete : CommandComplete (command_op_code = LE_MULTI_ADVT) { status : ErrorCode, sub_cmd : SubOcf, } packet LeMultiAdvtParam : LeMultiAdvt (sub_cmd = SET_ADVT_PARAM) { interval_min : 16, interval_max : 16, type : AdvertisingEventType, own_address_type : AddressType, peer_address_type : PeerAddressType, peer_address : Address, channel_map : 8, filter_policy : AdvertisingFilterPolicy, _reserved_ : 6, instance : 8, tx_power : 8, } packet LeMultiAdvtParamSetData : LeMultiAdvt (sub_cmd = SET_ADVT_DATA) { _size_(advertising_data) : 8, advertising_data : GapData[], _padding_[31], // Zero padding to 31 bytes of advertising_data advertising_instance : 8, } packet LeMultiAdvtParamSetScanResp : LeMultiAdvt (sub_cmd = SET_ADVT_SCAN_RESP) { _size_(advertising_data) : 8, advertising_data : GapData[], _padding_[31], // Zero padding to 31 bytes of advertising_data advertising_instance : 8, } packet LeMultiAdvtParamSetRandomAddr : LeMultiAdvt (sub_cmd = SET_ADVT_RANDOM_ADDR) { random_address : Address, advertising_instance : 8, } packet LeMultiAdvtParamSetEnable : LeMultiAdvt (sub_cmd = SET_ADVT_ENABLE) { advertising_enable : Enable, // Default DISABLED advertising_instance : 8, } packet LeBatchScan : VendorCommand (op_code = LE_BATCH_SCAN) { _payload_, // placeholder (unimplemented) } enum ApcfOpcode : 8 { ENABLE = 0x00, SET_FILTERING_PARAMETERS = 0x01, BROADCASTER_ADDRESS = 0x02, SERVICE_UUID = 0x03, SERVICE_SOLICITATION_UUID = 0x04, LOCAL_NAME = 0x05, MANUFACTURER_DATA = 0x06, SERVICE_DATA = 0x07, } packet LeAdvFilter : VendorCommand (op_code = LE_ADV_FILTER) { _payload_, // placeholder (unimplemented) apcf_opcode : ApcfOpcode, _body_, } packet LeAdvFilterComplete : CommandComplete (command_op_code = LE_ADV_FILTER) { status : ErrorCode, apcf_opcode : ApcfOpcode, } packet LeTrackAdv : VendorCommand (op_code = LE_TRACK_ADV) { Loading Loading @@ -3138,8 +3205,8 @@ struct LeAdvertisingReport { } packet LeAdvertisingReport : LeMetaEvent (subevent_code = ADVERTISING_REPORT) { _count_(le_advertising_reports) : 8, le_advertising_reports : LeAdvertisingReport[], _count_(advertising_reports) : 8, advertising_reports : LeAdvertisingReport[], } packet LeConnectionUpdateComplete : LeMetaEvent (subevent_code = CONNECTION_UPDATE_COMPLETE) { Loading Loading @@ -3214,6 +3281,7 @@ enum DirectAdvertisingAddressType : 8 { RANDOM_DEVICE_ADDRESS = 0x01, PUBLIC_IDENTITY_ADDRESS = 0x02, RANDOM_IDENTITY_ADDRESS = 0x03, CONTROLLER_UNABLE_TO_RESOLVE = 0xFE, NO_ADDRESS = 0xFF, } Loading @@ -3235,16 +3303,59 @@ struct LeDirectedAdvertisingReport { } packet LeDirectedAdvertisingReport : LeMetaEvent (subevent_code = DIRECTED_ADVERTISING_REPORT) { _count_(le_directed_advertising_reports) : 8, le_directed_advertising_reports : LeDirectedAdvertisingReport[], _count_(advertising_reports) : 8, advertising_reports : LeDirectedAdvertisingReport[], } packet LePhyUpdateComplete : LeMetaEvent (subevent_code = PHY_UPDATE_COMPLETE) { _payload_, // placeholder (unimplemented) } enum DataStatus : 2 { COMPLETE = 0x0, CONTINUING = 0x1, TRUNCATED = 0x2, RESERVED = 0x3, } enum PrimaryPhyType : 8 { LE_1M = 0x01, LE_CODED = 0x03, } enum SecondaryPhyType : 8 { NO_PACKETS = 0x00, LE_1M = 0x01, LE_2M = 0x02, LE_CODED = 0x03, } struct LeExtendedAdvertisingReport { connectable : 1, scannable : 1, directed : 1, scan_response : 1, data_status : DataStatus, _reserved_ : 10, address_type : DirectAdvertisingAddressType, address : Address, primary_phy : PrimaryPhyType, secondary_phy : SecondaryPhyType, advertising_sid : 4, // SID subfield in the ADI field _reserved_ : 4, tx_power : 8, rssi : 8, // -127 to +20 (0x7F means not available) periodic_advertising_interval : 16, // 0x006 to 0xFFFF (7.5 ms to 82s) direct_address_type : DirectAdvertisingAddressType, direct_address : Address, _size_(advertising_data) : 8, advertising_data : GapData[], } packet LeExtendedAdvertisingReport : LeMetaEvent (subevent_code = EXTENDED_ADVERTISING_REPORT) { _payload_, // placeholder (unimplemented) _count_(advertising_reports) : 8, advertising_reports : LeExtendedAdvertisingReport[], } packet LePeriodicAdvertisingSyncEstablished : LeMetaEvent (subevent_code = PERIODIC_ADVERTISING_SYNC_ESTABLISHED) { Loading @@ -3263,9 +3374,15 @@ packet LeScanTimeout : LeMetaEvent (subevent_code = SCAN_TIMEOUT) { } packet LeAdvertisingSetTerminated : LeMetaEvent (subevent_code = ADVERTISING_SET_TERMINATED) { _payload_, // placeholder (unimplemented) status : ErrorCode, advertising_handle : 8, connection_handle : 12, _reserved_ : 4, num_completed_extended_advertising_events : 8, } packet LeScanRequestReceived : LeMetaEvent (subevent_code = SCAN_REQUEST_RECEIVED) { _payload_, // placeholder (unimplemented) advertising_handle : 8, scanner_address_type : AddressType, scanner_address : Address, }
system/gd/hci/hci_packets_test.cc +15 −2 Original line number Diff line number Diff line Loading @@ -229,13 +229,14 @@ std::vector<uint8_t> pixel_3_xl_write_extended_inquiry_response_no_uuids_just_ei pixel_3_xl_write_extended_inquiry_response_no_uuids.end()}; TEST(HciPacketsTest, testWriteExtendedInquiryResponse) { std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(pixel_3_xl_write_extended_inquiry_response); PacketView<kLittleEndian> packet_bytes_view(packet_bytes); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = WriteExtendedInquiryResponseView::Create(CommandPacketView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); auto gap_data = view.GetExtendedInquiryResponse(); ASSERT_GE(gap_data.size(), 4); ASSERT_EQ(gap_data[0].data_type_, GapDataType::COMPLETE_LOCAL_NAME); ASSERT_EQ(gap_data[0].data_.size(), 10); ASSERT_EQ(gap_data[1].data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS); Loading @@ -244,6 +245,18 @@ TEST(HciPacketsTest, testWriteExtendedInquiryResponse) { ASSERT_EQ(gap_data[2].data_.size(), 0); ASSERT_EQ(gap_data[3].data_type_, GapDataType::COMPLETE_LIST_128_BIT_UUIDS); ASSERT_EQ(gap_data[3].data_.size(), 128); std::vector<GapData> no_padding{gap_data.begin(), gap_data.begin() + 4}; auto builder = WriteExtendedInquiryResponseBuilder::Create(view.GetFecRequired(), no_padding); std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); BitInserter it(*packet_bytes); builder->Serialize(it); EXPECT_EQ(packet_bytes->size(), view_bytes->size()); for (size_t i = 0; i < view_bytes->size(); i++) { ASSERT_EQ(packet_bytes->at(i), view_bytes->at(i)); } } // TODO: Revisit reflection tests for EIR Loading
system/gd/hci/le_advertising_interface.h +1 −6 Original line number Diff line number Diff line Loading @@ -37,13 +37,8 @@ class LeAdvertisingInterface { common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) = 0; static constexpr hci::SubeventCode LeAdvertisingEvents[] = { hci::SubeventCode::ADVERTISING_REPORT, hci::SubeventCode::DIRECTED_ADVERTISING_REPORT, hci::SubeventCode::EXTENDED_ADVERTISING_REPORT, hci::SubeventCode::PERIODIC_ADVERTISING_REPORT, hci::SubeventCode::PERIODIC_ADVERTISING_SYNC_ESTABLISHED, hci::SubeventCode::PERIODIC_ADVERTISING_SYNC_LOST, hci::SubeventCode::SCAN_REQUEST_RECEIVED, hci::SubeventCode::ADVERTISING_SET_TERMINATED, }; }; } // namespace hci Loading
system/gd/hci/le_advertising_manager.cc 0 → 100644 +262 −0 Original line number Diff line number Diff line /* * Copyright 2019 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. */ #include <memory> #include <mutex> #include "hci/controller.h" #include "hci/hci_layer.h" #include "hci/hci_packets.h" #include "hci/le_advertising_interface.h" #include "hci/le_advertising_manager.h" #include "module.h" #include "os/handler.h" #include "os/log.h" namespace bluetooth { namespace hci { const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); }); struct Advertiser { os::Handler* handler; common::Callback<void(Address, AddressType)> scan_callback; common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback; }; struct LeAdvertisingManager::impl { impl(Module* module, os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) : registered_handler_(nullptr), module_(module), module_handler_(handler), hci_layer_(hci_layer), controller_(controller), le_advertising_interface_(nullptr), num_instances_(0) {} void start() { le_advertising_interface_ = hci_layer_->GetLeAdvertisingInterface( common::Bind(&LeAdvertisingManager::impl::handle_event, common::Unretained(this)), module_handler_); num_instances_ = controller_->GetControllerLeNumberOfSupportedAdverisingSets(); } size_t GetNumberOfAdvertisingInstances() const { return num_instances_; } void handle_event(LeMetaEventView event) { switch (event.GetSubeventCode()) { case hci::SubeventCode::SCAN_REQUEST_RECEIVED: handle_scan_request(LeScanRequestReceivedView::Create(event)); break; case hci::SubeventCode::ADVERTISING_SET_TERMINATED: handle_set_terminated(LeAdvertisingSetTerminatedView::Create(event)); break; default: LOG_INFO("Unknown subevent in scanner %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str()); } } void handle_scan_request(LeScanRequestReceivedView event_view) { if (!event_view.IsValid()) { LOG_INFO("Dropping invalid scan request event"); return; } registered_handler_->Post( common::BindOnce(scan_callback_, event_view.GetScannerAddress(), event_view.GetScannerAddressType())); } void handle_set_terminated(LeAdvertisingSetTerminatedView event_view) { if (!event_view.IsValid()) { LOG_INFO("Dropping invalid advertising event"); return; } registered_handler_->Post(common::BindOnce(set_terminated_callback_, event_view.GetStatus(), event_view.GetAdvertisingHandle(), event_view.GetNumCompletedExtendedAdvertisingEvents())); } AdvertiserId allocate_advertiser() { AdvertiserId id = 0; { std::unique_lock lock(id_mutex_); while (id < num_instances_ && advertising_sets_.count(id) == 0) { id++; } } if (id == num_instances_) { return kInvalidId; } return id; } void remove_advertiser(AdvertiserId id) { std::unique_lock lock(id_mutex_); if (advertising_sets_.count(id) == 0) { return; } advertising_sets_.erase(id); } void create_advertiser(AdvertiserId id, const AdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { advertising_sets_[id].scan_callback = scan_callback; advertising_sets_[id].set_terminated_callback = set_terminated_callback; advertising_sets_[id].handler = handler; if (!controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) { le_advertising_interface_->EnqueueCommand( hci::LeSetAdvertisingParametersBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetRandomAddressBuilder::Create(config.random_address), common::BindOnce(impl::check_enable_status), module_handler_); if (!config.scan_response.empty()) { le_advertising_interface_->EnqueueCommand(hci::LeSetScanResponseDataBuilder::Create(config.scan_response), common::BindOnce(impl::check_enable_status), module_handler_); } le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement), common::BindOnce(impl::check_enable_status), module_handler_); return; } le_advertising_interface_->EnqueueCommand( hci::LeMultiAdvtParamBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_enable_status), module_handler_); le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED), common::BindOnce(impl::check_enable_status), module_handler_); } void create_extended_advertiser(AdvertiserId id, const ExtendedAdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { if (!controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) { create_advertiser(id, config, scan_callback, set_terminated_callback, handler); return; } else { LOG_ALWAYS_FATAL("LE_SET_EXTENDED_ADVERTISING_PARAMETERS isn't implemented."); } /* le_advertising_interface_->EnqueueCommand(hci::LeSetExtendedAdvertisingParametersBuilder::Create(config.interval_min, config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_enable_status), module_handler_); */ advertising_sets_[id].scan_callback = scan_callback; advertising_sets_[id].set_terminated_callback = set_terminated_callback; advertising_sets_[id].handler = handler; } void stop_advertising(AdvertiserId advertising_set) { if (advertising_sets_.find(advertising_set) == advertising_sets_.end()) { LOG_INFO("Unknown advertising set %u", advertising_set); return; } le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED), common::BindOnce(impl::check_enable_status), module_handler_); std::unique_lock lock(id_mutex_); advertising_sets_.erase(advertising_set); } common::Callback<void(Address, AddressType)> scan_callback_; common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback_; os::Handler* registered_handler_; Module* module_; os::Handler* module_handler_; hci::HciLayer* hci_layer_; hci::Controller* controller_; hci::LeAdvertisingInterface* le_advertising_interface_; std::map<AdvertiserId, Advertiser> advertising_sets_; std::mutex id_mutex_; size_t num_instances_; static void check_enable_status(CommandCompleteView view) { ASSERT(view.IsValid()); auto status_view = LeSetAdvertisingEnableCompleteView::Create(view); ASSERT(status_view.IsValid()); if (status_view.GetStatus() != ErrorCode::SUCCESS) { LOG_INFO("SetEnable returned status %s", ErrorCodeText(status_view.GetStatus()).c_str()); return; } } }; const AdvertiserId LeAdvertisingManager::kInvalidId = -1; LeAdvertisingManager::LeAdvertisingManager() { pimpl_ = std::make_unique<impl>(this, GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>()); } void LeAdvertisingManager::ListDependencies(ModuleList* list) { list->add<hci::HciLayer>(); list->add<hci::Controller>(); } void LeAdvertisingManager::Start() { pimpl_->start(); } void LeAdvertisingManager::Stop() { pimpl_.reset(); } size_t LeAdvertisingManager::GetNumberOfAdvertisingInstances() const { return pimpl_->GetNumberOfAdvertisingInstances(); } AdvertiserId LeAdvertisingManager::CreateAdvertiser( const AdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { if (config.peer_address == Address::kEmpty) { if (config.address_type == hci::AddressType::PUBLIC_IDENTITY_ADDRESS || config.address_type == hci::AddressType::RANDOM_IDENTITY_ADDRESS) { return kInvalidId; } if (config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND || config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND_LOW) { return kInvalidId; } } AdvertiserId id = pimpl_->allocate_advertiser(); if (id == kInvalidId) { return id; } GetHandler()->Post(common::BindOnce(&impl::create_advertiser, common::Unretained(pimpl_.get()), id, config, scan_callback, set_terminated_callback, handler)); return id; } AdvertiserId LeAdvertisingManager::CreateAdvertiser( const ExtendedAdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback, const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) { AdvertiserId id = pimpl_->allocate_advertiser(); if (id == kInvalidId) { return id; } // Add error checking here GetHandler()->Post(common::BindOnce(&impl::create_extended_advertiser, common::Unretained(pimpl_.get()), id, config, scan_callback, set_terminated_callback, handler)); return id; } void LeAdvertisingManager::RemoveAdvertiser(AdvertiserId id) { pimpl_->remove_advertiser(id); } } // namespace hci } // namespace bluetooth No newline at end of file