Loading system/btif/src/bluetooth.cc +7 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include "common/address_obfuscator.h" #include "common/metrics.h" #include "device/include/interop.h" #include "main/shim/shim.h" #include "osi/include/alarm.h" #include "osi/include/allocation_tracker.h" #include "osi/include/log.h" Loading Loading @@ -138,6 +139,12 @@ static int init(bt_callbacks_t* callbacks, bool start_restricted, LOG_INFO(LOG_TAG, "%s: start restricted = %d ; single user = %d", __func__, start_restricted, is_single_user_mode); if (bluetooth::shim::is_gd_shim_enabled()) { LOG_INFO(LOG_TAG, "%s Enable Gd bluetooth functionality", __func__); } else { LOG_INFO(LOG_TAG, "%s Preserving legacy bluetooth functionality", __func__); } if (interface_ready()) return BT_STATUS_DONE; #ifdef BLUEDROID_DEBUG Loading system/device/include/controller.h +6 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,12 @@ typedef struct controller_t { } controller_t; namespace bluetooth { namespace legacy { const controller_t* controller_get_interface(); } // namespace legacy } // namespace bluetooth const controller_t* controller_get_interface(); const controller_t* controller_get_test_interface( Loading system/device/src/controller.cc +11 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #include "btcore/include/module.h" #include "btcore/include/version.h" #include "hcimsgs.h" #include "main/shim/controller.h" #include "main/shim/shim.h" #include "osi/include/future.h" #include "stack/include/btm_ble_api.h" Loading Loading @@ -582,7 +584,7 @@ static const controller_t interface = { get_local_supported_codecs, get_le_all_initiating_phys}; const controller_t* controller_get_interface() { const controller_t* bluetooth::legacy::controller_get_interface() { static bool loaded = false; if (!loaded) { loaded = true; Loading @@ -595,6 +597,14 @@ const controller_t* controller_get_interface() { return &interface; } const controller_t* controller_get_interface() { if (bluetooth::shim::is_gd_shim_enabled()) { return bluetooth::shim::controller_get_interface(); } else { return bluetooth::legacy::controller_get_interface(); } } const controller_t* controller_get_test_interface( const hci_t* hci_interface, const hci_packet_factory_t* packet_factory_interface, Loading system/gd/shim/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ filegroup { name: "BluetoothShimSources", srcs: [ "controller.cc", "hci_layer.cc", "stack.cc", ], } system/gd/shim/hci_layer.cc 0 → 100644 +233 −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. */ #define LOG_TAG "bt_gd_shim" #include <cstdint> #include <memory> #include <queue> #include <unordered_map> #include <vector> #include "hci/hci_layer.h" #include "hci/hci_packets.h" #include "module.h" #include "os/handler.h" #include "os/log.h" #include "packet/raw_builder.h" #include "shim/hci_layer.h" namespace bluetooth { namespace shim { using TokenQueue = std::queue<const void*>; using OpCodeTokenQueueMap = std::unordered_map<hci::OpCode, TokenQueue>; const ModuleFactory HciLayer::Factory = ModuleFactory([]() { return new HciLayer(); }); struct HciLayer::impl { impl(os::Handler* handler, hci::HciLayer* hci_layer) : handler_(handler), hci_layer_(hci_layer) {} void OnTransmitPacketCommandComplete(hci::CommandCompleteView view) { if (command_complete_callback_ == nullptr) { LOG_WARN("%s Received packet complete with no complete callback registered", __func__); return; } uint16_t command_op_code = static_cast<uint16_t>(view.GetCommandOpCode()); std::vector<const uint8_t> data(view.begin(), view.end()); if (op_code_token_queue_map_.count(view.GetCommandOpCode()) == 0) { LOG_WARN("%s Received unexpected command complete for opcode:0x%04x", __func__, command_op_code); return; } const void* token = op_code_token_queue_map_[view.GetCommandOpCode()].front(); if (token == nullptr) { LOG_WARN("%s Received expected command status but no token for opcode:0x%04x", __func__, command_op_code); return; } op_code_token_queue_map_[view.GetCommandOpCode()].pop(); command_complete_callback_(command_op_code, data, token); } void OnTransmitPacketStatus(hci::CommandStatusView view) { if (command_status_callback_ == nullptr) { LOG_WARN("%s Received packet complete with no status callback registered", __func__); return; } uint16_t command_op_code = static_cast<uint16_t>(view.GetCommandOpCode()); std::vector<const uint8_t> data(view.begin(), view.end()); if (op_code_token_queue_map_.count(view.GetCommandOpCode()) == 0) { LOG_WARN("%s Received unexpected command status for opcode:0x%04x", __func__, command_op_code); return; } const void* token = op_code_token_queue_map_[view.GetCommandOpCode()].front(); if (token == nullptr) { LOG_WARN("%s Received expected command status but no token for opcode:0x%04x", __func__, command_op_code); return; } op_code_token_queue_map_[view.GetCommandOpCode()].pop(); uint8_t status = static_cast<uint8_t>(view.GetStatus()); command_status_callback_(command_op_code, data, token, status); } void TransmitCommand(uint16_t command, const uint8_t* data, size_t len, const void* token) { ASSERT(data != nullptr); ASSERT(token != nullptr); const hci::OpCode op_code = static_cast<const hci::OpCode>(command); auto payload = MakeUniquePacket(data, len); auto packet = hci::CommandPacketBuilder::Create(op_code, std::move(payload)); op_code_token_queue_map_[op_code].push(token); if (IsCommandStatusOpcode(op_code)) { hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnTransmitPacketStatus, common::Unretained(this)), handler_); } else { hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnTransmitPacketCommandComplete, common::Unretained(this)), handler_); } } void RegisterCommandComplete(CommandCompleteCallback callback) { ASSERT(command_complete_callback_ == nullptr); command_complete_callback_ = callback; } void UnregisterCommandComplete() { ASSERT(command_complete_callback_ != nullptr); command_complete_callback_ = nullptr; } void RegisterCommandStatus(CommandStatusCallback callback) { ASSERT(command_status_callback_ == nullptr); command_status_callback_ = callback; } void UnregisterCommandStatus() { ASSERT(command_status_callback_ != nullptr); command_status_callback_ = nullptr; } private: os::Handler* handler_{nullptr}; hci::HciLayer* hci_layer_{nullptr}; CommandCompleteCallback command_complete_callback_; CommandStatusCallback command_status_callback_; OpCodeTokenQueueMap op_code_token_queue_map_; /** * Returns true if expecting command complete, false otherwise */ bool IsCommandStatusOpcode(hci::OpCode op_code) { switch (op_code) { case hci::OpCode::INQUIRY: case hci::OpCode::CREATE_CONNECTION: case hci::OpCode::DISCONNECT: case hci::OpCode::ACCEPT_CONNECTION_REQUEST: case hci::OpCode::REJECT_CONNECTION_REQUEST: case hci::OpCode::CHANGE_CONNECTION_PACKET_TYPE: case hci::OpCode::AUTHENTICATION_REQUESTED: case hci::OpCode::SET_CONNECTION_ENCRYPTION: case hci::OpCode::CHANGE_CONNECTION_LINK_KEY: case hci::OpCode::MASTER_LINK_KEY: case hci::OpCode::REMOTE_NAME_REQUEST: case hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES: case hci::OpCode::READ_REMOTE_EXTENDED_FEATURES: case hci::OpCode::READ_REMOTE_VERSION_INFORMATION: case hci::OpCode::READ_CLOCK_OFFSET: case hci::OpCode::SETUP_SYNCHRONOUS_CONNECTION: case hci::OpCode::ACCEPT_SYNCHRONOUS_CONNECTION: case hci::OpCode::REJECT_SYNCHRONOUS_CONNECTION: case hci::OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION: case hci::OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION: case hci::OpCode::HOLD_MODE: case hci::OpCode::SNIFF_MODE: case hci::OpCode::EXIT_SNIFF_MODE: case hci::OpCode::QOS_SETUP: case hci::OpCode::SWITCH_ROLE: case hci::OpCode::FLOW_SPECIFICATION: case hci::OpCode::REFRESH_ENCRYPTION_KEY: case hci::OpCode::LE_CREATE_CONNECTION: case hci::OpCode::LE_CONNECTION_UPDATE: case hci::OpCode::LE_READ_REMOTE_FEATURES: case hci::OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND: case hci::OpCode::LE_GENERATE_DHKEY_COMMAND: case hci::OpCode::LE_SET_PHY: case hci::OpCode::LE_EXTENDED_CREATE_CONNECTION: case hci::OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC: return true; default: return false; } } std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) { packet::RawBuilder builder; std::vector<uint8_t> bytes(data, data + len); auto payload = std::make_unique<packet::RawBuilder>(); payload->AddOctets(bytes); return payload; } }; void HciLayer::TransmitCommand(uint16_t op_code, const uint8_t* data, size_t len, const void* token) { pimpl_->TransmitCommand(op_code, data, len, std::move(token)); } void HciLayer::RegisterCommandComplete(CommandCompleteCallback callback) { pimpl_->RegisterCommandComplete(callback); } void HciLayer::UnregisterCommandComplete() { pimpl_->UnregisterCommandComplete(); } void HciLayer::RegisterCommandStatus(CommandStatusCallback callback) { pimpl_->RegisterCommandStatus(callback); } void HciLayer::UnregisterCommandStatus() { pimpl_->UnregisterCommandStatus(); } /** * Module methods */ void HciLayer::ListDependencies(ModuleList* list) { list->add<hci::HciLayer>(); } void HciLayer::Start() { LOG_INFO("%s Starting controller shim layer", __func__); pimpl_ = std::make_unique<impl>(GetHandler(), GetDependency<hci::HciLayer>()); } void HciLayer::Stop() { pimpl_.reset(); } } // namespace shim } // namespace bluetooth Loading
system/btif/src/bluetooth.cc +7 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include "common/address_obfuscator.h" #include "common/metrics.h" #include "device/include/interop.h" #include "main/shim/shim.h" #include "osi/include/alarm.h" #include "osi/include/allocation_tracker.h" #include "osi/include/log.h" Loading Loading @@ -138,6 +139,12 @@ static int init(bt_callbacks_t* callbacks, bool start_restricted, LOG_INFO(LOG_TAG, "%s: start restricted = %d ; single user = %d", __func__, start_restricted, is_single_user_mode); if (bluetooth::shim::is_gd_shim_enabled()) { LOG_INFO(LOG_TAG, "%s Enable Gd bluetooth functionality", __func__); } else { LOG_INFO(LOG_TAG, "%s Preserving legacy bluetooth functionality", __func__); } if (interface_ready()) return BT_STATUS_DONE; #ifdef BLUEDROID_DEBUG Loading
system/device/include/controller.h +6 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,12 @@ typedef struct controller_t { } controller_t; namespace bluetooth { namespace legacy { const controller_t* controller_get_interface(); } // namespace legacy } // namespace bluetooth const controller_t* controller_get_interface(); const controller_t* controller_get_test_interface( Loading
system/device/src/controller.cc +11 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #include "btcore/include/module.h" #include "btcore/include/version.h" #include "hcimsgs.h" #include "main/shim/controller.h" #include "main/shim/shim.h" #include "osi/include/future.h" #include "stack/include/btm_ble_api.h" Loading Loading @@ -582,7 +584,7 @@ static const controller_t interface = { get_local_supported_codecs, get_le_all_initiating_phys}; const controller_t* controller_get_interface() { const controller_t* bluetooth::legacy::controller_get_interface() { static bool loaded = false; if (!loaded) { loaded = true; Loading @@ -595,6 +597,14 @@ const controller_t* controller_get_interface() { return &interface; } const controller_t* controller_get_interface() { if (bluetooth::shim::is_gd_shim_enabled()) { return bluetooth::shim::controller_get_interface(); } else { return bluetooth::legacy::controller_get_interface(); } } const controller_t* controller_get_test_interface( const hci_t* hci_interface, const hci_packet_factory_t* packet_factory_interface, Loading
system/gd/shim/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ filegroup { name: "BluetoothShimSources", srcs: [ "controller.cc", "hci_layer.cc", "stack.cc", ], }
system/gd/shim/hci_layer.cc 0 → 100644 +233 −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. */ #define LOG_TAG "bt_gd_shim" #include <cstdint> #include <memory> #include <queue> #include <unordered_map> #include <vector> #include "hci/hci_layer.h" #include "hci/hci_packets.h" #include "module.h" #include "os/handler.h" #include "os/log.h" #include "packet/raw_builder.h" #include "shim/hci_layer.h" namespace bluetooth { namespace shim { using TokenQueue = std::queue<const void*>; using OpCodeTokenQueueMap = std::unordered_map<hci::OpCode, TokenQueue>; const ModuleFactory HciLayer::Factory = ModuleFactory([]() { return new HciLayer(); }); struct HciLayer::impl { impl(os::Handler* handler, hci::HciLayer* hci_layer) : handler_(handler), hci_layer_(hci_layer) {} void OnTransmitPacketCommandComplete(hci::CommandCompleteView view) { if (command_complete_callback_ == nullptr) { LOG_WARN("%s Received packet complete with no complete callback registered", __func__); return; } uint16_t command_op_code = static_cast<uint16_t>(view.GetCommandOpCode()); std::vector<const uint8_t> data(view.begin(), view.end()); if (op_code_token_queue_map_.count(view.GetCommandOpCode()) == 0) { LOG_WARN("%s Received unexpected command complete for opcode:0x%04x", __func__, command_op_code); return; } const void* token = op_code_token_queue_map_[view.GetCommandOpCode()].front(); if (token == nullptr) { LOG_WARN("%s Received expected command status but no token for opcode:0x%04x", __func__, command_op_code); return; } op_code_token_queue_map_[view.GetCommandOpCode()].pop(); command_complete_callback_(command_op_code, data, token); } void OnTransmitPacketStatus(hci::CommandStatusView view) { if (command_status_callback_ == nullptr) { LOG_WARN("%s Received packet complete with no status callback registered", __func__); return; } uint16_t command_op_code = static_cast<uint16_t>(view.GetCommandOpCode()); std::vector<const uint8_t> data(view.begin(), view.end()); if (op_code_token_queue_map_.count(view.GetCommandOpCode()) == 0) { LOG_WARN("%s Received unexpected command status for opcode:0x%04x", __func__, command_op_code); return; } const void* token = op_code_token_queue_map_[view.GetCommandOpCode()].front(); if (token == nullptr) { LOG_WARN("%s Received expected command status but no token for opcode:0x%04x", __func__, command_op_code); return; } op_code_token_queue_map_[view.GetCommandOpCode()].pop(); uint8_t status = static_cast<uint8_t>(view.GetStatus()); command_status_callback_(command_op_code, data, token, status); } void TransmitCommand(uint16_t command, const uint8_t* data, size_t len, const void* token) { ASSERT(data != nullptr); ASSERT(token != nullptr); const hci::OpCode op_code = static_cast<const hci::OpCode>(command); auto payload = MakeUniquePacket(data, len); auto packet = hci::CommandPacketBuilder::Create(op_code, std::move(payload)); op_code_token_queue_map_[op_code].push(token); if (IsCommandStatusOpcode(op_code)) { hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnTransmitPacketStatus, common::Unretained(this)), handler_); } else { hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnTransmitPacketCommandComplete, common::Unretained(this)), handler_); } } void RegisterCommandComplete(CommandCompleteCallback callback) { ASSERT(command_complete_callback_ == nullptr); command_complete_callback_ = callback; } void UnregisterCommandComplete() { ASSERT(command_complete_callback_ != nullptr); command_complete_callback_ = nullptr; } void RegisterCommandStatus(CommandStatusCallback callback) { ASSERT(command_status_callback_ == nullptr); command_status_callback_ = callback; } void UnregisterCommandStatus() { ASSERT(command_status_callback_ != nullptr); command_status_callback_ = nullptr; } private: os::Handler* handler_{nullptr}; hci::HciLayer* hci_layer_{nullptr}; CommandCompleteCallback command_complete_callback_; CommandStatusCallback command_status_callback_; OpCodeTokenQueueMap op_code_token_queue_map_; /** * Returns true if expecting command complete, false otherwise */ bool IsCommandStatusOpcode(hci::OpCode op_code) { switch (op_code) { case hci::OpCode::INQUIRY: case hci::OpCode::CREATE_CONNECTION: case hci::OpCode::DISCONNECT: case hci::OpCode::ACCEPT_CONNECTION_REQUEST: case hci::OpCode::REJECT_CONNECTION_REQUEST: case hci::OpCode::CHANGE_CONNECTION_PACKET_TYPE: case hci::OpCode::AUTHENTICATION_REQUESTED: case hci::OpCode::SET_CONNECTION_ENCRYPTION: case hci::OpCode::CHANGE_CONNECTION_LINK_KEY: case hci::OpCode::MASTER_LINK_KEY: case hci::OpCode::REMOTE_NAME_REQUEST: case hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES: case hci::OpCode::READ_REMOTE_EXTENDED_FEATURES: case hci::OpCode::READ_REMOTE_VERSION_INFORMATION: case hci::OpCode::READ_CLOCK_OFFSET: case hci::OpCode::SETUP_SYNCHRONOUS_CONNECTION: case hci::OpCode::ACCEPT_SYNCHRONOUS_CONNECTION: case hci::OpCode::REJECT_SYNCHRONOUS_CONNECTION: case hci::OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION: case hci::OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION: case hci::OpCode::HOLD_MODE: case hci::OpCode::SNIFF_MODE: case hci::OpCode::EXIT_SNIFF_MODE: case hci::OpCode::QOS_SETUP: case hci::OpCode::SWITCH_ROLE: case hci::OpCode::FLOW_SPECIFICATION: case hci::OpCode::REFRESH_ENCRYPTION_KEY: case hci::OpCode::LE_CREATE_CONNECTION: case hci::OpCode::LE_CONNECTION_UPDATE: case hci::OpCode::LE_READ_REMOTE_FEATURES: case hci::OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND: case hci::OpCode::LE_GENERATE_DHKEY_COMMAND: case hci::OpCode::LE_SET_PHY: case hci::OpCode::LE_EXTENDED_CREATE_CONNECTION: case hci::OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC: return true; default: return false; } } std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) { packet::RawBuilder builder; std::vector<uint8_t> bytes(data, data + len); auto payload = std::make_unique<packet::RawBuilder>(); payload->AddOctets(bytes); return payload; } }; void HciLayer::TransmitCommand(uint16_t op_code, const uint8_t* data, size_t len, const void* token) { pimpl_->TransmitCommand(op_code, data, len, std::move(token)); } void HciLayer::RegisterCommandComplete(CommandCompleteCallback callback) { pimpl_->RegisterCommandComplete(callback); } void HciLayer::UnregisterCommandComplete() { pimpl_->UnregisterCommandComplete(); } void HciLayer::RegisterCommandStatus(CommandStatusCallback callback) { pimpl_->RegisterCommandStatus(callback); } void HciLayer::UnregisterCommandStatus() { pimpl_->UnregisterCommandStatus(); } /** * Module methods */ void HciLayer::ListDependencies(ModuleList* list) { list->add<hci::HciLayer>(); } void HciLayer::Start() { LOG_INFO("%s Starting controller shim layer", __func__); pimpl_ = std::make_unique<impl>(GetHandler(), GetDependency<hci::HciLayer>()); } void HciLayer::Stop() { pimpl_.reset(); } } // namespace shim } // namespace bluetooth