Merge "Trigger gd legacy from legacy dumpsys"
diff --git a/system/gd/Android.bp b/system/gd/Android.bp
index b2bff30..60e1030 100644
--- a/system/gd/Android.bp
+++ b/system/gd/Android.bp
@@ -114,11 +114,17 @@
srcs: [
":BluetoothOsSources_linux_generic",
],
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ ],
},
host: {
srcs: [
":BluetoothHalSources_hci_rootcanal",
],
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ ],
},
android: {
srcs: [
@@ -153,6 +159,9 @@
"libchrome",
"libcrypto",
],
+ static_libs: [
+ "libbluetooth-protos",
+ ]
}
cc_library {
@@ -205,6 +214,7 @@
],
static_libs: [
"libbluetooth_gd",
+ "libbluetooth-protos",
],
shared_libs: [
"libchrome",
@@ -279,12 +289,14 @@
"BluetoothGeneratedPackets_h",
],
static_libs: [
+ "libbluetooth-protos",
"libbluetooth_gd",
"libgmock",
],
shared_libs: [
"libchrome",
"libcrypto",
+ "libprotobuf-cpp-full",
],
sanitize: {
address: true,
@@ -320,6 +332,7 @@
":BluetoothHciFuzzHelperSources",
],
static_libs: [
+ "libbluetooth-protos",
"libbluetooth_gd_fuzzing",
"libchrome",
"libgmock",
@@ -331,6 +344,7 @@
],
shared_libs: [
"libcrypto",
+ "libprotobuf-cpp-full",
],
cflags: [
"-DFUZZ_TARGET",
diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc
index 74ac026..ecceb71 100644
--- a/system/gd/hci/hci_layer.cc
+++ b/system/gd/hci/hci_layer.cc
@@ -45,6 +45,8 @@
using hci::ResetCompleteView;
using os::Alarm;
using os::Handler;
+using std::move;
+using std::unique_ptr;
static void fail_if_reset_complete_not_success(CommandCompleteView complete) {
auto reset_complete = ResetCompleteView::Create(complete);
@@ -58,18 +60,33 @@
class CommandQueueEntry {
public:
- CommandQueueEntry(std::unique_ptr<CommandPacketBuilder> command_packet,
+ CommandQueueEntry(unique_ptr<CommandPacketBuilder> command_packet,
ContextualOnceCallback<void(CommandCompleteView)> on_complete_function)
- : command(std::move(command_packet)), waiting_for_status_(false), on_complete(std::move(on_complete_function)) {}
+ : command(move(command_packet)), waiting_for_status_(false), on_complete(move(on_complete_function)) {}
- CommandQueueEntry(std::unique_ptr<CommandPacketBuilder> command_packet,
+ CommandQueueEntry(unique_ptr<CommandPacketBuilder> command_packet,
ContextualOnceCallback<void(CommandStatusView)> on_status_function)
- : command(std::move(command_packet)), waiting_for_status_(true), on_status(std::move(on_status_function)) {}
+ : command(move(command_packet)), waiting_for_status_(true), on_status(move(on_status_function)) {}
- std::unique_ptr<CommandPacketBuilder> command;
+ unique_ptr<CommandPacketBuilder> command;
bool waiting_for_status_;
ContextualOnceCallback<void(CommandStatusView)> on_status;
ContextualOnceCallback<void(CommandCompleteView)> on_complete;
+
+ template <typename TView>
+ ContextualOnceCallback<void(TView)>* GetCallback() {
+ return nullptr;
+ }
+
+ template <>
+ ContextualOnceCallback<void(CommandStatusView)>* GetCallback<CommandStatusView>() {
+ return &on_status;
+ }
+
+ template <>
+ ContextualOnceCallback<void(CommandCompleteView)>* GetCallback<CommandCompleteView>() {
+ return &on_complete;
+ }
};
template <typename T>
@@ -78,37 +95,25 @@
explicit CommandInterfaceImpl(HciLayer& hci) : hci_(hci) {}
~CommandInterfaceImpl() override = default;
- void EnqueueCommand(std::unique_ptr<T> command,
- ContextualOnceCallback<void(CommandCompleteView)> on_complete) override {
- hci_.EnqueueCommand(std::move(command), std::move(on_complete));
+ void EnqueueCommand(unique_ptr<T> command, ContextualOnceCallback<void(CommandCompleteView)> on_complete) override {
+ hci_.EnqueueCommand(move(command), move(on_complete));
}
- void EnqueueCommand(std::unique_ptr<T> command, ContextualOnceCallback<void(CommandStatusView)> on_status) override {
- hci_.EnqueueCommand(std::move(command), std::move(on_status));
+ void EnqueueCommand(unique_ptr<T> command, ContextualOnceCallback<void(CommandStatusView)> on_status) override {
+ hci_.EnqueueCommand(move(command), move(on_status));
}
HciLayer& hci_;
};
struct HciLayer::impl {
- impl(HciLayer& module) : hal_(nullptr), module_(module) {}
+ impl(hal::HciHal* hal, HciLayer& module) : hal_(hal), module_(module) {
+ hci_timeout_alarm_ = new Alarm(module.GetHandler());
+ }
- void Start(hal::HciHal* hal) {
- hal_ = hal;
- hci_timeout_alarm_ = new Alarm(module_.GetHandler());
-
- auto queue_end = acl_queue_.GetDownEnd();
- Handler* handler = module_.GetHandler();
- queue_end->RegisterDequeue(handler, BindOn(this, &impl::on_outbound_acl_ready));
- module_.RegisterEventHandler(EventCode::COMMAND_COMPLETE, handler->BindOn(this, &impl::on_command_complete));
- module_.RegisterEventHandler(EventCode::COMMAND_STATUS, handler->BindOn(this, &impl::on_command_status));
- module_.RegisterEventHandler(EventCode::LE_META_EVENT, handler->BindOn(this, &impl::on_le_meta_event));
- // TODO find the right place
- auto drop_packet = handler->BindOn(this, &impl::drop);
- module_.RegisterEventHandler(EventCode::PAGE_SCAN_REPETITION_MODE_CHANGE, drop_packet);
- module_.RegisterEventHandler(EventCode::MAX_SLOTS_CHANGE, drop_packet);
- module_.RegisterEventHandler(EventCode::VENDOR_SPECIFIC, drop_packet);
-
- module_.EnqueueCommand(ResetBuilder::Create(), handler->BindOnce(&fail_if_reset_complete_not_success));
+ ~impl() {
+ incoming_acl_buffer_.Clear();
+ delete hci_timeout_alarm_;
+ command_queue_.clear();
}
void drop(EventPacketView) {}
@@ -121,54 +126,34 @@
hal_->sendAclData(bytes);
}
- void Stop() {
- acl_queue_.GetDownEnd()->UnregisterDequeue();
- incoming_acl_packet_buffer_.Clear();
- delete hci_timeout_alarm_;
- command_queue_.clear();
- hal_ = nullptr;
- }
-
void on_command_status(EventPacketView event) {
- CommandStatusView status_view = CommandStatusView::Create(event);
- ASSERT(status_view.IsValid());
- command_credits_ = status_view.GetNumHciCommandPackets();
- OpCode op_code = status_view.GetCommandOpCode();
- if (op_code == OpCode::NONE) {
- send_next_command();
- return;
- }
- ASSERT_LOG(!command_queue_.empty(), "Unexpected status event with OpCode 0x%02hx (%s)", op_code,
- OpCodeText(op_code).c_str());
- ASSERT_LOG(waiting_command_ == op_code, "Waiting for 0x%02hx (%s), got 0x%02hx (%s)", waiting_command_,
- OpCodeText(waiting_command_).c_str(), op_code, OpCodeText(op_code).c_str());
- ASSERT_LOG(command_queue_.front().waiting_for_status_,
- "Waiting for command complete 0x%02hx (%s), got command status for 0x%02hx (%s)", waiting_command_,
- OpCodeText(waiting_command_).c_str(), op_code, OpCodeText(op_code).c_str());
- command_queue_.front().on_status.Invoke(std::move(status_view));
- command_queue_.pop_front();
- waiting_command_ = OpCode::NONE;
- hci_timeout_alarm_->Cancel();
- send_next_command();
+ handle_command_response<CommandStatusView>(event, "status");
}
void on_command_complete(EventPacketView event) {
- CommandCompleteView complete_view = CommandCompleteView::Create(event);
- ASSERT(complete_view.IsValid());
- command_credits_ = complete_view.GetNumHciCommandPackets();
- OpCode op_code = complete_view.GetCommandOpCode();
+ handle_command_response<CommandCompleteView>(event, "complete");
+ }
+
+ template <typename TResponse>
+ void handle_command_response(EventPacketView event, std::string logging_id) {
+ TResponse response_view = TResponse::Create(event);
+ ASSERT(response_view.IsValid());
+ command_credits_ = response_view.GetNumHciCommandPackets();
+ OpCode op_code = response_view.GetCommandOpCode();
if (op_code == OpCode::NONE) {
send_next_command();
return;
}
- ASSERT_LOG(command_queue_.size() > 0, "Unexpected command complete with OpCode 0x%02hx (%s)", op_code,
+ bool is_status = logging_id == "status";
+
+ ASSERT_LOG(!command_queue_.empty(), "Unexpected %s event with OpCode 0x%02hx (%s)", logging_id.c_str(), op_code,
OpCodeText(op_code).c_str());
ASSERT_LOG(waiting_command_ == op_code, "Waiting for 0x%02hx (%s), got 0x%02hx (%s)", waiting_command_,
OpCodeText(waiting_command_).c_str(), op_code, OpCodeText(op_code).c_str());
- ASSERT_LOG(!command_queue_.front().waiting_for_status_,
- "Waiting for command status 0x%02hx (%s), got command complete for 0x%02hx (%s)", waiting_command_,
- OpCodeText(waiting_command_).c_str(), op_code, OpCodeText(op_code).c_str());
- command_queue_.front().on_complete.Invoke(std::move(complete_view));
+ ASSERT_LOG(command_queue_.front().waiting_for_status_ == is_status, "0x%02hx (%s) was not expecting %s event",
+ op_code, OpCodeText(op_code).c_str(), logging_id.c_str());
+
+ command_queue_.front().GetCallback<TResponse>()->Invoke(move(response_view));
command_queue_.pop_front();
waiting_command_ = OpCode::NONE;
hci_timeout_alarm_->Cancel();
@@ -185,6 +170,7 @@
}
void on_hci_event(EventPacketView event) {
+ ASSERT(event.IsValid());
EventCode event_code = event.GetEventCode();
if (event_handlers_.find(event_code) == event_handlers_.end()) {
LOG_DEBUG("Dropping unregistered event of type 0x%02hhx (%s)", event_code, EventCodeText(event_code).c_str());
@@ -193,17 +179,9 @@
event_handlers_[event_code].Invoke(event);
}
- void handle_enqueue_command_with_complete(std::unique_ptr<CommandPacketBuilder> command,
- ContextualOnceCallback<void(CommandCompleteView)> on_complete) {
- command_queue_.emplace_back(std::move(command), std::move(on_complete));
-
- send_next_command();
- }
-
- void handle_enqueue_command_with_status(std::unique_ptr<CommandPacketBuilder> command,
- ContextualOnceCallback<void(CommandStatusView)> on_status) {
- command_queue_.emplace_back(std::move(command), std::move(on_status));
-
+ template <typename TResponse>
+ void enqueue_command(unique_ptr<CommandPacketBuilder> command, ContextualOnceCallback<void(TResponse)> on_response) {
+ command_queue_.emplace_back(move(command), move(on_response));
send_next_command();
}
@@ -221,6 +199,7 @@
BitInserter bi(*bytes);
command_queue_.front().command->Serialize(bi);
hal_->sendHciCommand(*bytes);
+
auto cmd_view = CommandPacketView::Create(bytes);
ASSERT(cmd_view.IsValid());
OpCode op_code = cmd_view.GetOpCode();
@@ -229,32 +208,27 @@
hci_timeout_alarm_->Schedule(BindOnce(&on_hci_timeout, op_code), kHciTimeoutMs);
}
- void handle_register_event_handler(EventCode event_code, ContextualCallback<void(EventPacketView)> event_handler) {
- ASSERT_LOG(event_handlers_.count(event_code) == 0, "Can not register a second handler for event_code %02hhx (%s)",
- event_code, EventCodeText(event_code).c_str());
- event_handlers_[event_code] = event_handler;
+ void register_event(EventCode event, ContextualCallback<void(EventPacketView)> handler) {
+ ASSERT_LOG(event_handlers_.count(event) == 0, "Can not register a second handler for %02hhx (%s)", event,
+ EventCodeText(event).c_str());
+ event_handlers_[event] = handler;
}
- void handle_unregister_event_handler(EventCode event_code) {
- event_handlers_.erase(event_handlers_.find(event_code));
+ void unregister_event(EventCode event) {
+ event_handlers_.erase(event_handlers_.find(event));
}
- void handle_register_le_event_handler(SubeventCode subevent_code,
- ContextualCallback<void(LeMetaEventView)> subevent_handler) {
- ASSERT_LOG(subevent_handlers_.count(subevent_code) == 0,
- "Can not register a second handler for subevent_code %02hhx (%s)", subevent_code,
- SubeventCodeText(subevent_code).c_str());
- subevent_handlers_[subevent_code] = subevent_handler;
+ void register_le_event(SubeventCode event, ContextualCallback<void(LeMetaEventView)> handler) {
+ ASSERT_LOG(subevent_handlers_.count(event) == 0, "Can not register a second handler for %02hhx (%s)", event,
+ SubeventCodeText(event).c_str());
+ subevent_handlers_[event] = handler;
}
- void handle_unregister_le_event_handler(SubeventCode subevent_code) {
- subevent_handlers_.erase(subevent_handlers_.find(subevent_code));
+ void unregister_le_event(SubeventCode event) {
+ subevent_handlers_.erase(subevent_handlers_.find(event));
}
- // The HAL
hal::HciHal* hal_;
-
- // A reference to the HciLayer module
HciLayer& module_;
// Interfaces
@@ -276,7 +250,7 @@
// Acl packets
BidiQueue<AclPacketView, AclPacketBuilder> acl_queue_{3 /* TODO: Set queue depth */};
- os::EnqueueBuffer<AclPacketView> incoming_acl_packet_buffer_{acl_queue_.GetDownEnd()};
+ os::EnqueueBuffer<AclPacketView> incoming_acl_buffer_{acl_queue_.GetDownEnd()};
};
// All functions here are running on the HAL thread
@@ -286,15 +260,13 @@
void hciEventReceived(hal::HciPacket event_bytes) override {
auto packet = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(event_bytes));
EventPacketView event = EventPacketView::Create(packet);
- ASSERT(event.IsValid());
- module_.CallOn(module_.impl_, &impl::on_hci_event, std::move(event));
+ module_.CallOn(module_.impl_, &impl::on_hci_event, move(event));
}
void aclDataReceived(hal::HciPacket data_bytes) override {
- auto packet =
- packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(std::move(data_bytes)));
- AclPacketView acl = AclPacketView::Create(packet);
- module_.impl_->incoming_acl_packet_buffer_.Enqueue(std::make_unique<AclPacketView>(acl), module_.GetHandler());
+ auto packet = packet::PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>(move(data_bytes)));
+ auto acl = std::make_unique<AclPacketView>(AclPacketView::Create(packet));
+ module_.impl_->incoming_acl_buffer_.Enqueue(move(acl), module_.GetHandler());
}
void scoDataReceived(hal::HciPacket data_bytes) override {
@@ -304,42 +276,39 @@
HciLayer& module_;
};
-HciLayer::HciLayer() : impl_(new impl(*this)), hal_callbacks_(new hal_callbacks(*this)) {}
+HciLayer::HciLayer() : impl_(nullptr), hal_callbacks_(nullptr) {}
HciLayer::~HciLayer() {
- delete impl_;
- delete hal_callbacks_;
}
-void HciLayer::EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+void HciLayer::EnqueueCommand(unique_ptr<CommandPacketBuilder> command,
common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) {
- CallOn(impl_, &impl::handle_enqueue_command_with_complete, std::move(command), std::move(on_complete));
+ CallOn(impl_, &impl::enqueue_command<CommandCompleteView>, move(command), move(on_complete));
}
-void HciLayer::EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+void HciLayer::EnqueueCommand(unique_ptr<CommandPacketBuilder> command,
common::ContextualOnceCallback<void(CommandStatusView)> on_status) {
- CallOn(impl_, &impl::handle_enqueue_command_with_status, std::move(command), std::move(on_status));
+ CallOn(impl_, &impl::enqueue_command<CommandStatusView>, move(command), move(on_status));
}
common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* HciLayer::GetAclQueueEnd() {
return impl_->acl_queue_.GetUpEnd();
}
-void HciLayer::RegisterEventHandler(EventCode event_code, ContextualCallback<void(EventPacketView)> event_handler) {
- CallOn(impl_, &impl::handle_register_event_handler, event_code, event_handler);
+void HciLayer::RegisterEventHandler(EventCode event, ContextualCallback<void(EventPacketView)> handler) {
+ CallOn(impl_, &impl::register_event, event, handler);
}
-void HciLayer::UnregisterEventHandler(EventCode event_code) {
- CallOn(impl_, &impl::handle_unregister_event_handler, event_code);
+void HciLayer::UnregisterEventHandler(EventCode event) {
+ CallOn(impl_, &impl::unregister_event, event);
}
-void HciLayer::RegisterLeEventHandler(SubeventCode subevent_code,
- ContextualCallback<void(LeMetaEventView)> event_handler) {
- CallOn(impl_, &impl::handle_register_le_event_handler, subevent_code, event_handler);
+void HciLayer::RegisterLeEventHandler(SubeventCode event, ContextualCallback<void(LeMetaEventView)> handler) {
+ CallOn(impl_, &impl::register_le_event, event, handler);
}
-void HciLayer::UnregisterLeEventHandler(SubeventCode subevent_code) {
- CallOn(impl_, &impl::handle_unregister_le_event_handler, subevent_code);
+void HciLayer::UnregisterLeEventHandler(SubeventCode event) {
+ CallOn(impl_, &impl::unregister_le_event, event);
}
AclConnectionInterface* HciLayer::GetAclConnectionInterface(
@@ -396,14 +365,31 @@
void HciLayer::Start() {
auto hal = GetDependency<hal::HciHal>();
- impl_->Start(hal);
+ impl_ = new impl(hal, *this);
+ hal_callbacks_ = new hal_callbacks(*this);
+
+ Handler* handler = GetHandler();
+ impl_->acl_queue_.GetDownEnd()->RegisterDequeue(handler, BindOn(impl_, &impl::on_outbound_acl_ready));
+ RegisterEventHandler(EventCode::COMMAND_COMPLETE, handler->BindOn(impl_, &impl::on_command_complete));
+ RegisterEventHandler(EventCode::COMMAND_STATUS, handler->BindOn(impl_, &impl::on_command_status));
+ RegisterEventHandler(EventCode::LE_META_EVENT, handler->BindOn(impl_, &impl::on_le_meta_event));
+ // TODO find the right place
+ auto drop_packet = handler->BindOn(impl_, &impl::drop);
+ RegisterEventHandler(EventCode::PAGE_SCAN_REPETITION_MODE_CHANGE, drop_packet);
+ RegisterEventHandler(EventCode::MAX_SLOTS_CHANGE, drop_packet);
+ RegisterEventHandler(EventCode::VENDOR_SPECIFIC, drop_packet);
+
+ EnqueueCommand(ResetBuilder::Create(), handler->BindOnce(&fail_if_reset_complete_not_success));
hal->registerIncomingPacketCallback(hal_callbacks_);
}
void HciLayer::Stop() {
auto hal = GetDependency<hal::HciHal>();
hal->unregisterIncomingPacketCallback();
- impl_->Stop();
+ delete hal_callbacks_;
+
+ impl_->acl_queue_.GetDownEnd()->UnregisterDequeue();
+ delete impl_;
}
} // namespace hci
diff --git a/system/gd/module.cc b/system/gd/module.cc
index a9599b9..8ec1bbd 100644
--- a/system/gd/module.cc
+++ b/system/gd/module.cc
@@ -15,6 +15,7 @@
*/
#include "module.h"
+#include "bluetooth/dumpmod.pb.h"
using ::bluetooth::os::Handler;
using ::bluetooth::os::Thread;
@@ -126,6 +127,8 @@
}
void ModuleDumper::DumpState() const {
+ Dumpmod dumpmod;
+
for (auto it = module_registry_.start_order_.rbegin(); it != module_registry_.start_order_.rend(); it++) {
auto instance = module_registry_.started_modules_.find(*it);
ASSERT(instance != module_registry_.started_modules_.end());
@@ -133,7 +136,10 @@
if (message == nullptr) {
continue;
}
- // TODO(cmanton) Process module message into master proto
+ ModuleDumpState dump_state;
+ dump_state.set_name(instance->second->ToString());
+ dump_state.mutable_data()->PackFrom(*message);
+ dumpmod.mutable_module_dump_states()->insert({dump_state.name(), dump_state});
}
}
diff --git a/system/gd/proto/Android.bp b/system/gd/proto/Android.bp
index ef5c78e..ea3620d 100644
--- a/system/gd/proto/Android.bp
+++ b/system/gd/proto/Android.bp
@@ -22,10 +22,15 @@
host_supported: true,
proto: {
export_proto_headers: true,
+ type: "lite",
include_dirs: ["external/protobuf/src"],
},
srcs: [
"bluetooth/dumpmod.proto",
"bluetooth/metrics/bluetooth.proto"
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth.updatable",
+ ],
}
diff --git a/system/gd/security/cert/cert_security.py b/system/gd/security/cert/cert_security.py
new file mode 100644
index 0000000..e862699
--- /dev/null
+++ b/system/gd/security/cert/cert_security.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020 - 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.
+
+import logging
+
+from bluetooth_packets_python3 import hci_packets
+from cert.closable import safeClose
+from cert.event_stream import EventStream
+from cert.py_hci import PyHci
+from cert.py_security import PySecurity
+from datetime import datetime
+from google.protobuf import empty_pb2 as empty_proto
+from hci.facade import facade_pb2 as hci_facade
+from l2cap.classic import facade_pb2 as l2cap_facade
+from security.facade_pb2 import IoCapabilities
+from security.facade_pb2 import AuthenticationRequirements
+from security.facade_pb2 import OobDataPresent
+
+
+class CertSecurity(PySecurity):
+ """
+ Contain all of the certification stack logic for sending and receiving
+ HCI commands following the Classic Pairing flows.
+ """
+ _io_cap_lookup = {
+ IoCapabilities.DISPLAY_ONLY:
+ hci_packets.IoCapability.DISPLAY_ONLY,
+ IoCapabilities.DISPLAY_YES_NO_IO_CAP:
+ hci_packets.IoCapability.DISPLAY_YES_NO,
+ IoCapabilities.KEYBOARD_ONLY:
+ hci_packets.IoCapability.KEYBOARD_ONLY,
+ IoCapabilities.NO_INPUT_NO_OUTPUT:
+ hci_packets.IoCapability.NO_INPUT_NO_OUTPUT,
+ }
+
+ _auth_req_lookup = {
+ AuthenticationRequirements.NO_BONDING:
+ hci_packets.AuthenticationRequirements.NO_BONDING,
+ AuthenticationRequirements.NO_BONDING_MITM_PROTECTION:
+ hci_packets.AuthenticationRequirements.NO_BONDING_MITM_PROTECTION,
+ AuthenticationRequirements.DEDICATED_BONDING:
+ hci_packets.AuthenticationRequirements.DEDICATED_BONDING,
+ AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION:
+ hci_packets.AuthenticationRequirements.
+ DEDICATED_BONDING_MITM_PROTECTION,
+ AuthenticationRequirements.GENERAL_BONDING:
+ hci_packets.AuthenticationRequirements.GENERAL_BONDING,
+ AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION:
+ hci_packets.AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION,
+ }
+
+ _oob_present_lookup = {
+ OobDataPresent.NOT_PRESENT:
+ hci_packets.OobDataPresent.NOT_PRESENT,
+ OobDataPresent.P192_PRESENT:
+ hci_packets.OobDataPresent.P_192_PRESENT,
+ OobDataPresent.P256_PRESENT:
+ hci_packets.OobDataPresent.P_256_PRESENT,
+ OobDataPresent.P192_AND_256_PRESENT:
+ hci_packets.OobDataPresent.P_192_AND_256_PRESENT,
+ }
+
+ _hci_event_stream = None
+ _io_caps = hci_packets.IoCapability.DISPLAY_ONLY
+ _oob_data = hci_packets.OobDataPresent.NOT_PRESENT
+ _auth_reqs = hci_packets.AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION
+
+ _hci = None
+
+ def _enqueue_hci_command(self, command, expect_complete):
+ if (expect_complete):
+ self._hci.send_command_with_complete(command)
+ else:
+ self._hci.send_command_with_status(command)
+
+ def __init__(self, device):
+ """
+ Don't call super b/c the gRPC stream setup will crash test
+ """
+ logging.info("Cert: Init")
+ self._device = device
+ self._device.wait_channel_ready()
+ self._hci = PyHci(device)
+ self._hci.register_for_events(
+ hci_packets.EventCode.LINK_KEY_REQUEST,
+ hci_packets.EventCode.IO_CAPABILITY_REQUEST,
+ hci_packets.EventCode.IO_CAPABILITY_RESPONSE,
+ hci_packets.EventCode.USER_PASSKEY_NOTIFICATION,
+ hci_packets.EventCode.USER_PASSKEY_REQUEST,
+ hci_packets.EventCode.USER_CONFIRMATION_REQUEST,
+ hci_packets.EventCode.REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION,
+ hci_packets.EventCode.LINK_KEY_NOTIFICATION,
+ hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE)
+ self._hci_event_stream = self._hci.get_event_stream()
+
+ def create_bond(self, address, type):
+ """
+ Creates a bond from the cert perspective
+ """
+ logging.info("Cert: Creating bond to '%s' from '%s'" %
+ (str(address), str(self._device.address)))
+ # TODO(optedoblivion): Trigger connection to Send AuthenticationRequested
+
+ def remove_bond(self, address):
+ """
+ We store the link key locally in the test and pretend
+ So to remove_bond we need to Remove the "stored" data
+ """
+ pass
+
+ def set_io_capabilities(self, io_capabilities):
+ """
+ Set the IO Capabilities used for the cert
+ """
+ logging.info(
+ "Cert: setting IO Capabilities data to '%s'" % io_capabilities)
+ self._io_caps = self._io_cap_lookup.get(
+ io_capabilities, hci_packets.IoCapability.DISPLAY_YES_NO)
+
+ def set_authentication_requirements(self, auth_reqs):
+ """
+ Establish authentication requirements for the stack
+ """
+ logging.info("Cert: setting Authentication Requirements data to '%s'" %
+ auth_reqs)
+ self._auth_reqs = self._auth_req_lookup.get(
+ auth_reqs, hci_packets.AuthenticationRequirements.GENERAL_BONDING)
+
+ def set_oob_data(self, data):
+ """
+ Set the Out-of-band data for SSP pairing
+ """
+ logging.info("Cert: setting OOB data present to '%s'" % data)
+ self._oob_data = self._oob_present_lookup.get(
+ data, hci_packets.OobDataPresent.NOT_PRESENT)
+
+ def send_ui_callback(self, address, callback_type, b, uid):
+ """
+ Pretend to answer the pairing dailog as a user
+ """
+ logging.info(
+ "Cert: Send user input callback uid:%d; response: %s" % (uid, b))
+ # TODO(optedoblivion): Make callback and set it to the module
+
+ def enable_secure_simple_pairing(self):
+ """
+ This is called when you want to enable SSP for testing
+ """
+ logging.info("Cert: Sending WRITE_SIMPLE_PAIRING_MODE [True]")
+ self._enqueue_hci_command(
+ hci_packets.WriteSimplePairingModeBuilder(
+ hci_packets.Enable.ENABLED), True)
+ logging.info("Cert: Waiting for controller response")
+ self._hci_event_stream.assert_event_occurs(
+ lambda msg: b'\x0e\x04\x01\x56\x0c' in msg.event)
+
+ def accept_pairing(self, dut_address, reply_boolean):
+ """
+ Here we handle the pairing events at the HCI level
+ """
+ logging.info("Cert: Waiting for LINK_KEY_REQUEST")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.LINK_KEY_REQUEST in event.event
+ )
+ logging.info("Cert: Sending LINK_KEY_REQUEST_NEGATIVE_REPLY")
+ self._enqueue_hci_command(
+ hci_packets.LinkKeyRequestNegativeReplyBuilder(
+ dut_address.decode('utf8')), True)
+ logging.info("Cert: Waiting for IO_CAPABILITY_REQUEST")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.IO_CAPABILITY_REQUEST in event.event
+ )
+ logging.info("Cert: Sending IO_CAPABILITY_REQUEST_REPLY")
+
+ self._enqueue_hci_command(
+ hci_packets.IoCapabilityRequestReplyBuilder(
+ dut_address.decode('utf8'), self._io_caps, self._oob_data,
+ self._auth_reqs), True)
+
+ logging.info("Cert: Waiting for USER_CONFIRMATION_REQUEST")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.USER_CONFIRMATION_REQUEST in event.event
+ )
+ logging.info(
+ "Cert: Sending Simulated User Response '%s'" % reply_boolean)
+ if reply_boolean:
+ logging.info("Cert: Sending USER_CONFIRMATION_REQUEST_REPLY")
+ self._enqueue_hci_command(
+ hci_packets.UserConfirmationRequestReplyBuilder(
+ dut_address.decode('utf8')), True)
+ logging.info("Cert: Waiting for LINK_KEY_NOTIFICATION")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.LINK_KEY_NOTIFICATION in event.event
+ )
+ logging.info("Cert: Waiting for SIMPLE_PAIRING_COMPLETE")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE in event.event
+ )
+ else:
+ logging.info(
+ "Cert: Sending USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY")
+ self._enqueue_hci_command(
+ hci_packets.UserConfirmationRequestNegativeReplyBuilder(
+ dut_address.decode('utf8')), True)
+ logging.info("Cert: Waiting for SIMPLE_PAIRING_COMPLETE")
+ self._hci_event_stream.assert_event_occurs(
+ lambda event: logging.debug(event.event) or hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE in event.event
+ )
+
+ def on_user_input(self, dut_address, reply_boolean, expected_ui_event):
+ """
+ Cert doesn't need the test to respond to the ui event
+ Cert responds in accept pairing
+ """
+ pass
+
+ def wait_for_bond_event(self, expected_bond_event):
+ """
+ A bond event will be triggered once the bond process
+ is complete. For the DUT we need to wait for it,
+ for Cert it isn't needed.
+ """
+ pass
+
+ def close(self):
+ safeClose(self._hci)