aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-11-11 21:09:35 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-11-11 21:09:35 +0000
commit7fb2d8a93ad374f3bd859d1dbd1ed3bcbd1d066d (patch)
treec052800eec2c144799e89e3e978069f8529366e9
parent89755b16ff683f94472bb6aff47082720e4f628a (diff)
parent44d82eaeeab4e822c74c5f4721aac1e911b735fa (diff)
downloadbt-android10-mainline-networking-release.tar.gz
Snap for 6001391 from 44d82eaeeab4e822c74c5f4721aac1e911b735fa to qt-aml-networking-releaseandroid-mainline-10.0.0_r6android10-mainline-networking-release
Change-Id: I0d4ec91534b53072b53f99f326a09d8ab5dc291a
-rw-r--r--binder/android/bluetooth/IBluetooth.aidl5
-rw-r--r--binder/android/bluetooth/IBluetoothA2dp.aidl6
-rw-r--r--binder/android/bluetooth/IBluetoothGatt.aidl2
-rw-r--r--binder/android/bluetooth/IBluetoothHeadset.aidl6
-rw-r--r--binder/android/bluetooth/IBluetoothManager.aidl3
-rw-r--r--build/Android.bp27
-rw-r--r--embdrv/sbc/decoder/srce/decoder-sbc.c8
-rw-r--r--gd/cert/gd_base_test.py1
-rw-r--r--gd/hci/Android.bp3
-rw-r--r--gd/hci/acl_manager.cc12
-rw-r--r--gd/hci/acl_manager_test.cc37
-rw-r--r--gd/hci/controller.cc38
-rw-r--r--gd/hci/controller.h38
-rw-r--r--gd/hci/hci_packets.pdl84
-rw-r--r--gd/hci/le_advertising_manager.cc150
-rw-r--r--gd/hci/le_advertising_manager.h2
-rw-r--r--gd/hci/le_advertising_manager_test.cc356
-rw-r--r--gd/hci/le_report.h83
-rw-r--r--gd/hci/le_scanning_interface.h6
-rw-r--r--gd/hci/le_scanning_manager.cc247
-rw-r--r--gd/hci/le_scanning_manager.h60
-rw-r--r--gd/hci/le_scanning_manager_test.cc336
-rw-r--r--gd/l2cap/classic/cert/simple_l2cap_test.py63
-rw-r--r--gd/l2cap/classic/internal/dynamic_channel_impl.cc8
-rw-r--r--gd/l2cap/classic/internal/dynamic_channel_impl.h15
-rw-r--r--gd/l2cap/classic/internal/link.cc6
-rw-r--r--gd/l2cap/classic/internal/signalling_manager.cc32
-rw-r--r--gd/l2cap/internal/scheduler.h3
-rw-r--r--gd/l2cap/internal/scheduler_fifo.cc7
-rw-r--r--gd/l2cap/internal/scheduler_fifo.h8
-rw-r--r--gd/l2cap/internal/scheduler_fifo_test.cc8
-rw-r--r--gd/l2cap/internal/scheduler_mock.h4
-rw-r--r--gd/l2cap/le/internal/link.h2
-rw-r--r--gd/security/Android.bp8
-rw-r--r--gd/security/channel/Android.bp13
-rw-r--r--gd/security/channel/security_manager_channel.cc93
-rw-r--r--gd/security/channel/security_manager_channel.h113
-rw-r--r--gd/security/channel/security_manager_channel_unittest.cc276
-rw-r--r--gd/security/internal/security_manager_impl.cc152
-rw-r--r--gd/security/internal/security_manager_impl.h119
-rw-r--r--gd/security/pairing/classic_pairing_handler.h42
-rw-r--r--gd/security/pairing/pairing_handler.h52
-rw-r--r--gd/security/record/security_record.h60
-rw-r--r--gd/security/security_manager.cc57
-rw-r--r--gd/security/security_manager.h56
-rw-r--r--gd/security/security_module.cc18
-rw-r--r--gd/security/test/fake_hci_layer.h115
-rw-r--r--gd/shim/il2cap.h20
-rw-r--r--gd/shim/l2cap.cc414
-rw-r--r--gd/shim/l2cap.h14
-rw-r--r--gd/shim/stack.cc1
-rw-r--r--main/Android.bp31
-rw-r--r--main/shim/l2c_api.cc22
-rw-r--r--main/shim/l2cap.cc258
-rw-r--r--main/shim/l2cap.h50
-rw-r--r--main/shim/l2cap_test.cc254
-rw-r--r--main/shim/test_stack.cc91
-rw-r--r--main/shim/test_stack.h66
-rw-r--r--profile/avrcp/Android.bp32
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc86
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_error_responsebin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_requestbin0 -> 14 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_responsebin0 -> 8 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_up_requestbin0 -> 14 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_play_pos_notificationbin0 -> 15 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_volume_changed_notificationbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/general_reject_invalid_command_packetbin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_requestbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_company_idbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_unknownbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_company_idbin0 -> 18 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_events_supportedbin0 -> 15 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_fullbin0 -> 47 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_partialbin0 -> 23 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_elements_attributes_response_fullbin0 -> 113 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_error_responsebin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_folder_responsebin0 -> 36 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_media_player_responsebin0 -> 63 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_requestbin0 -> 13 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_no_attrsbin0 -> 13 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_now_playingbin0 -> 13 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_titlebin0 -> 17 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_vfsbin0 -> 17 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_song_responsebin0 -> 53 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributesbin0 -> 43 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes_invalidbin0 -> 43 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_song_responsebin0 -> 59 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_requestbin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_responsebin0 -> 19 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_media_playersbin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_now_playingbin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_vfsbin0 -> 4 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_responsebin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_addressed_player_notificationbin0 -> 15 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_available_players_notificationbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_now_playing_notificationbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_play_status_notificationbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_track_changed_notificationbin0 -> 19 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_uids_notificaitonbin0 -> 13 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_volume_changed_notificationbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_pushedbin0 -> 5 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_releasedbin0 -> 5 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_requestbin0 -> 21 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_responsebin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/register_notification_invalidbin0 -> 14 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/register_play_status_notificationbin0 -> 15 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/register_volume_changed_notificationbin0 -> 15 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/reject_player_app_settings_responsebin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/rejected_volume_changed_notificationbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_requestbin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_responsebin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_id_1_requestbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_requestbin0 -> 12 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_responsebin0 -> 11 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_requestbin0 -> 5 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_responsebin0 -> 13 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_browse_packetbin0 -> 3 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_change_path_requestbin0 -> 3 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_capabilities_requestbin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_element_attributes_requestbin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_folder_items_requestbin0 -> 3 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_item_attributes_requestbin0 -> 3 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_total_number_of_items_requestbin0 -> 3 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_play_item_requestbin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_set_addressed_player_requestbin0 -> 10 bytes
-rw-r--r--profile/avrcp/tests/avrcp_device_fuzz/corpus/short_vendor_packetbin0 -> 10 bytes
-rw-r--r--stack/btm/btm_acl.cc18
-rw-r--r--stack/btm/btm_int.h2
-rw-r--r--stack/btu/btu_hcif.cc10
-rw-r--r--stack/include/hcidefs.h2
-rw-r--r--test/rootcanal/Android.bp6
-rw-r--r--types/class_of_device.h8
-rw-r--r--vendor_libs/test_vendor_lib/Android.bp21
-rw-r--r--vendor_libs/test_vendor_lib/include/link.h50
-rw-r--r--vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc76
-rw-r--r--vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h15
-rw-r--r--vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc597
-rw-r--r--vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h88
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/beacon.cc29
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/beacon.h3
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/car_kit.cc5
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/car_kit.h3
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/device.cc11
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/device.h12
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/device_properties.cc17
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/device_properties.h4
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/keyboard.cc2
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/keyboard.h3
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc31
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h8
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/loopback.cc17
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/loopback.h3
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc30
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h4
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/sniffer.cc2
-rw-r--r--vendor_libs/test_vendor_lib/model/devices/sniffer.h5
-rw-r--r--vendor_libs/test_vendor_lib/model/setup/phy_layer.h16
-rw-r--r--vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc53
-rw-r--r--vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h23
-rw-r--r--vendor_libs/test_vendor_lib/model/setup/test_model.cc6
-rw-r--r--vendor_libs/test_vendor_lib/packets/Android.bp3
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h55
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/command_view.h52
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h50
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h47
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h50
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h48
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h51
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h106
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h72
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h48
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h58
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h50
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h47
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h54
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h60
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h55
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_connect_builder.h71
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_builder.h66
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_view.h59
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/le_connect_view.h63
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc187
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h110
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc52
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h49
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h54
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_reject_builder.h50
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_reject_view.h47
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h50
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h47
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/page_view.h51
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h53
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/response_view.h51
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h52
-rw-r--r--vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl171
-rw-r--r--vendor_libs/test_vendor_lib/packets/packet_view.h4
-rw-r--r--vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc512
-rw-r--r--vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc12
-rw-r--r--vendor_libs/test_vendor_lib/types/address.h8
-rw-r--r--vendor_libs/test_vendor_lib/types/class_of_device.h8
200 files changed, 6872 insertions, 1220 deletions
diff --git a/binder/android/bluetooth/IBluetooth.aidl b/binder/android/bluetooth/IBluetooth.aidl
index 6bda14bfc..fa2b063aa 100644
--- a/binder/android/bluetooth/IBluetooth.aidl
+++ b/binder/android/bluetooth/IBluetooth.aidl
@@ -35,12 +35,14 @@ import android.os.ResultReceiver;
*/
interface IBluetooth
{
+ @UnsupportedAppUsage
boolean isEnabled();
int getState();
boolean enable();
boolean enableNoAutoConnect();
boolean disable();
+ @UnsupportedAppUsage
String getAddress();
ParcelUuid[] getUuids();
boolean setName(in String name);
@@ -79,10 +81,12 @@ interface IBluetooth
String getRemoteName(in BluetoothDevice device);
int getRemoteType(in BluetoothDevice device);
+ @UnsupportedAppUsage
String getRemoteAlias(in BluetoothDevice device);
boolean setRemoteAlias(in BluetoothDevice device, in String name);
int getRemoteClass(in BluetoothDevice device);
ParcelUuid[] getRemoteUuids(in BluetoothDevice device);
+ @UnsupportedAppUsage
boolean fetchRemoteUuids(in BluetoothDevice device);
boolean sdpSearch(in BluetoothDevice device, in ParcelUuid uuid);
int getBatteryLevel(in BluetoothDevice device);
@@ -102,6 +106,7 @@ interface IBluetooth
int getSimAccessPermission(in BluetoothDevice device);
boolean setSimAccessPermission(in BluetoothDevice device, int value);
+ @UnsupportedAppUsage
void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState);
void registerCallback(in IBluetoothCallback callback);
diff --git a/binder/android/bluetooth/IBluetoothA2dp.aidl b/binder/android/bluetooth/IBluetoothA2dp.aidl
index 6606a1b53..9cbd9cabe 100644
--- a/binder/android/bluetooth/IBluetoothA2dp.aidl
+++ b/binder/android/bluetooth/IBluetoothA2dp.aidl
@@ -27,14 +27,20 @@ import android.bluetooth.BluetoothDevice;
*/
interface IBluetoothA2dp {
// Public API
+ @UnsupportedAppUsage
boolean connect(in BluetoothDevice device);
+ @UnsupportedAppUsage
boolean disconnect(in BluetoothDevice device);
+ @UnsupportedAppUsage
List<BluetoothDevice> getConnectedDevices();
+ @UnsupportedAppUsage
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ @UnsupportedAppUsage
int getConnectionState(in BluetoothDevice device);
boolean setActiveDevice(in BluetoothDevice device);
BluetoothDevice getActiveDevice();
boolean setPriority(in BluetoothDevice device, int priority);
+ @UnsupportedAppUsage
int getPriority(in BluetoothDevice device);
boolean isAvrcpAbsoluteVolumeSupported();
oneway void setAvrcpAbsoluteVolume(int volume);
diff --git a/binder/android/bluetooth/IBluetoothGatt.aidl b/binder/android/bluetooth/IBluetoothGatt.aidl
index c9e1c4bc8..016eeff95 100644
--- a/binder/android/bluetooth/IBluetoothGatt.aidl
+++ b/binder/android/bluetooth/IBluetoothGatt.aidl
@@ -71,8 +71,10 @@ interface IBluetoothGatt {
void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
void unregisterSync(in IPeriodicAdvertisingCallback callback);
+ @UnsupportedAppUsage
void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
+ @UnsupportedAppUsage
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in boolean opportunistic, in int phy);
void clientDisconnect(in int clientIf, in String address);
diff --git a/binder/android/bluetooth/IBluetoothHeadset.aidl b/binder/android/bluetooth/IBluetoothHeadset.aidl
index 0f6954cd1..c59cab1c3 100644
--- a/binder/android/bluetooth/IBluetoothHeadset.aidl
+++ b/binder/android/bluetooth/IBluetoothHeadset.aidl
@@ -29,8 +29,10 @@ import android.bluetooth.BluetoothDevice;
*/
interface IBluetoothHeadset {
// Public API
+ @UnsupportedAppUsage
List<BluetoothDevice> getConnectedDevices();
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ @UnsupportedAppUsage
int getConnectionState(in BluetoothDevice device);
boolean startVoiceRecognition(in BluetoothDevice device);
boolean stopVoiceRecognition(in BluetoothDevice device);
@@ -40,9 +42,13 @@ interface IBluetoothHeadset {
in String arg);
// Hidden API
+ @UnsupportedAppUsage
boolean connect(in BluetoothDevice device);
+ @UnsupportedAppUsage
boolean disconnect(in BluetoothDevice device);
+ @UnsupportedAppUsage
boolean setPriority(in BluetoothDevice device, int priority);
+ @UnsupportedAppUsage
int getPriority(in BluetoothDevice device);
int getAudioState(in BluetoothDevice device);
boolean isAudioOn();
diff --git a/binder/android/bluetooth/IBluetoothManager.aidl b/binder/android/bluetooth/IBluetoothManager.aidl
index 2e1270048..faf78d828 100644
--- a/binder/android/bluetooth/IBluetoothManager.aidl
+++ b/binder/android/bluetooth/IBluetoothManager.aidl
@@ -31,13 +31,16 @@ interface IBluetoothManager
{
IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
void unregisterAdapter(in IBluetoothManagerCallback callback);
+ @UnsupportedAppUsage
void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
+ @UnsupportedAppUsage
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
boolean enable(String packageName);
boolean enableNoAutoConnect(String packageName);
boolean disable(String packageName, boolean persist);
int getState();
+ @UnsupportedAppUsage
IBluetoothGatt getBluetoothGatt();
boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
diff --git a/build/Android.bp b/build/Android.bp
index c5ee79f53..32c0f31c0 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -29,9 +29,10 @@ fluoride_defaults {
},
}
+// Fuzzable defaults are the subset of defaults that are used in fuzzing, which
+// requires no shared libraries, and no explicit sanitization.
fluoride_defaults {
- name: "fluoride_types_defaults",
- defaults: ["libchrome_support_defaults"],
+ name: "fluoride_types_defaults_fuzzable",
cflags: [
"-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
"-fvisibility=hidden",
@@ -54,15 +55,22 @@ fluoride_defaults {
}
fluoride_defaults {
- name: "fluoride_defaults",
+ name: "fluoride_types_defaults",
+ defaults: [
+ "fluoride_types_defaults_fuzzable",
+ "libchrome_support_defaults"
+ ],
+}
+
+fluoride_defaults {
+ name: "fluoride_defaults_fuzzable",
target: {
android: {
test_config_template: ":BluetoothTestConfigTemplate",
},
},
- defaults: ["fluoride_types_defaults"],
+ defaults: ["fluoride_types_defaults_fuzzable"],
header_libs: ["libbluetooth_headers"],
- shared_libs: ["libstatslog"],
static_libs: [
"libbluetooth-types",
"libbt-platform-protos-lite",
@@ -73,6 +81,15 @@ fluoride_defaults {
},
}
+fluoride_defaults {
+ name: "fluoride_defaults",
+ defaults: ["fluoride_defaults_fuzzable", "fluoride_types_defaults"],
+ shared_libs: ["libstatslog"],
+ sanitize: {
+ misc_undefined: ["bounds"],
+ },
+}
+
// Enables code coverage for a set of source files. Must be combined with
// "clang_coverage_bin" in order to work. See //test/gen_coverage.py for more information
// on generating code coverage.
diff --git a/embdrv/sbc/decoder/srce/decoder-sbc.c b/embdrv/sbc/decoder/srce/decoder-sbc.c
index 20c5b67b7..50168b5f2 100644
--- a/embdrv/sbc/decoder/srce/decoder-sbc.c
+++ b/embdrv/sbc/decoder/srce/decoder-sbc.c
@@ -33,6 +33,12 @@
#define SPECIALIZE_READ_SAMPLES_JOINT
+#if __has_attribute(fallthrough)
+#define __fallthrough __attribute__((__fallthrough__))
+#else
+#define __fallthrough
+#endif
+
/**
* Scans through a buffer looking for a codec syncword. If the decoder has been
* set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search
@@ -413,7 +419,7 @@ uint8_t OI_CODEC_SBC_FrameCount(OI_BYTE* frameData, uint32_t frameBytes) {
case SBC_DUAL_CHANNEL:
frameLen *= 2;
- /* fall through */
+ __fallthrough;
default:
if (mode == SBC_MONO) {
diff --git a/gd/cert/gd_base_test.py b/gd/cert/gd_base_test.py
index 059c82c1e..45c20773f 100644
--- a/gd/cert/gd_base_test.py
+++ b/gd/cert/gd_base_test.py
@@ -70,7 +70,6 @@ class GdBaseTestClass(BaseTestClass):
builtin=True)
def teardown_class(self):
- self.unregister_controllers()
if self.rootcanal_running:
self.rootcanal_process.send_signal(signal.SIGINT)
rootcanal_return_code = self.rootcanal_process.wait()
diff --git a/gd/hci/Android.bp b/gd/hci/Android.bp
index 675a72e7b..8784a49e7 100644
--- a/gd/hci/Android.bp
+++ b/gd/hci/Android.bp
@@ -11,6 +11,7 @@ filegroup {
"device_database.cc",
"hci_layer.cc",
"le_advertising_manager.cc",
+ "le_scanning_manager.cc",
],
}
@@ -29,6 +30,8 @@ filegroup {
"dual_device_test.cc",
"hci_layer_test.cc",
"hci_packets_test.cc",
+ "le_advertising_manager_test.cc",
+ "le_scanning_manager_test.cc",
],
}
diff --git a/gd/hci/acl_manager.cc b/gd/hci/acl_manager.cc
index a2cb801ac..c60cf058d 100644
--- a/gd/hci/acl_manager.cc
+++ b/gd/hci/acl_manager.cc
@@ -30,6 +30,8 @@
namespace bluetooth {
namespace hci {
+constexpr uint16_t kQualcommDebugHandle = 0xedc;
+
using common::Bind;
using common::BindOnce;
@@ -85,15 +87,8 @@ struct AclManager::impl {
hci_layer_->RegisterEventHandler(EventCode::CONNECTION_PACKET_TYPE_CHANGED,
Bind(&impl::on_connection_packet_type_changed, common::Unretained(this)),
handler_);
- hci_layer_->RegisterEventHandler(EventCode::MASTER_LINK_KEY_COMPLETE,
- Bind(&impl::on_master_link_key_complete, common::Unretained(this)), handler_);
hci_layer_->RegisterEventHandler(EventCode::AUTHENTICATION_COMPLETE,
Bind(&impl::on_authentication_complete, common::Unretained(this)), handler_);
- hci_layer_->RegisterEventHandler(EventCode::ENCRYPTION_CHANGE,
- Bind(&impl::on_encryption_change, common::Unretained(this)), handler_);
- hci_layer_->RegisterEventHandler(EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE,
- Bind(&impl::on_change_connection_link_key_complete, common::Unretained(this)),
- handler_);
hci_layer_->RegisterEventHandler(EventCode::READ_CLOCK_OFFSET_COMPLETE,
Bind(&impl::on_read_clock_offset_complete, common::Unretained(this)), handler_);
hci_layer_->RegisterEventHandler(EventCode::MODE_CHANGE, Bind(&impl::on_mode_change, common::Unretained(this)),
@@ -228,6 +223,9 @@ struct AclManager::impl {
return;
}
uint16_t handle = packet->GetHandle();
+ if (handle == kQualcommDebugHandle) {
+ return;
+ }
auto connection_pair = acl_connections_.find(handle);
if (connection_pair == acl_connections_.end()) {
LOG_INFO("Dropping packet of size %zu to unknown connection 0x%0hx", packet->size(), handle);
diff --git a/gd/hci/acl_manager_test.cc b/gd/hci/acl_manager_test.cc
index 3c5704d47..8b2cb3271 100644
--- a/gd/hci/acl_manager_test.cc
+++ b/gd/hci/acl_manager_test.cc
@@ -73,11 +73,11 @@ class TestController : public Controller {
acl_cb_handler_ = handler;
}
- uint16_t GetControllerAclPacketLength() override {
+ uint16_t GetControllerAclPacketLength() const override {
return acl_buffer_length_;
}
- uint16_t GetControllerNumAclPacketBuffers() override {
+ uint16_t GetControllerNumAclPacketBuffers() const override {
return total_acl_buffers_;
}
@@ -676,17 +676,6 @@ TEST_F(AclManagerTest, acl_send_data_credits) {
connection->Disconnect(DisconnectReason::AUTHENTICATION_FAILURE);
}
-TEST_F(AclManagerWithConnectionTest, send_master_link_key) {
- acl_manager_->MasterLinkKey(KeyFlag::TEMPORARY);
- auto packet = test_hci_layer_->GetCommandPacket(OpCode::MASTER_LINK_KEY);
- auto command_view = MasterLinkKeyView::Create(packet);
- ASSERT(command_view.IsValid());
- EXPECT_EQ(command_view.GetKeyFlag(), KeyFlag::TEMPORARY);
-
- EXPECT_CALL(mock_acl_manager_callbacks_, OnMasterLinkKeyComplete(0x123, KeyFlag::TEMPORARY));
- test_hci_layer_->IncomingEvent(MasterLinkKeyCompleteBuilder::Create(ErrorCode::SUCCESS, 0x123, KeyFlag::TEMPORARY));
-}
-
TEST_F(AclManagerWithConnectionTest, send_switch_role) {
acl_manager_->SwitchRole(connection_->GetAddress(), Role::SLAVE);
auto packet = test_hci_layer_->GetCommandPacket(OpCode::SWITCH_ROLE);
@@ -744,28 +733,6 @@ TEST_F(AclManagerWithConnectionTest, send_authentication_requested) {
test_hci_layer_->IncomingEvent(AuthenticationCompleteBuilder::Create(ErrorCode::SUCCESS, handle_));
}
-TEST_F(AclManagerWithConnectionTest, send_set_connection_encryption) {
- connection_->SetConnectionEncryption(Enable::ENABLED);
- auto packet = test_hci_layer_->GetCommandPacket(OpCode::SET_CONNECTION_ENCRYPTION);
- auto command_view = SetConnectionEncryptionView::Create(packet);
- ASSERT(command_view.IsValid());
- EXPECT_EQ(command_view.GetEncryptionEnable(), Enable::ENABLED);
-
- EXPECT_CALL(mock_connection_management_callbacks_, OnEncryptionChange(EncryptionEnabled::BR_EDR_AES_CCM));
- test_hci_layer_->IncomingEvent(
- EncryptionChangeBuilder::Create(ErrorCode::SUCCESS, handle_, EncryptionEnabled::BR_EDR_AES_CCM));
-}
-
-TEST_F(AclManagerWithConnectionTest, send_change_connection_link_key) {
- connection_->ChangeConnectionLinkKey();
- auto packet = test_hci_layer_->GetCommandPacket(OpCode::CHANGE_CONNECTION_LINK_KEY);
- auto command_view = ChangeConnectionLinkKeyView::Create(packet);
- ASSERT(command_view.IsValid());
-
- EXPECT_CALL(mock_connection_management_callbacks_, OnChangeConnectionLinkKeyComplete);
- test_hci_layer_->IncomingEvent(ChangeConnectionLinkKeyCompleteBuilder::Create(ErrorCode::SUCCESS, handle_));
-}
-
TEST_F(AclManagerWithConnectionTest, send_read_clock_offset) {
connection_->ReadClockOffset();
auto packet = test_hci_layer_->GetCommandPacket(OpCode::READ_CLOCK_OFFSET);
diff --git a/gd/hci/controller.cc b/gd/hci/controller.cc
index 6ebe8956d..d9610645f 100644
--- a/gd/hci/controller.cc
+++ b/gd/hci/controller.cc
@@ -696,50 +696,50 @@ void Controller::RegisterCompletedAclPacketsCallback(Callback<void(uint16_t /* h
impl_->RegisterCompletedAclPacketsCallback(cb, handler); // TODO hsz: why here?
}
-std::string Controller::GetControllerLocalName() {
+std::string Controller::GetControllerLocalName() const {
return impl_->local_name_;
}
-LocalVersionInformation Controller::GetControllerLocalVersionInformation() {
+LocalVersionInformation Controller::GetControllerLocalVersionInformation() const {
return impl_->local_version_information_;
}
-std::array<uint8_t, 64> Controller::GetControllerLocalSupportedCommands() {
+std::array<uint8_t, 64> Controller::GetControllerLocalSupportedCommands() const {
return impl_->local_supported_commands_;
}
-uint8_t Controller::GetControllerLocalExtendedFeaturesMaxPageNumber() {
+uint8_t Controller::GetControllerLocalExtendedFeaturesMaxPageNumber() const {
return impl_->maximum_page_number_;
}
-uint64_t Controller::GetControllerLocalSupportedFeatures() {
+uint64_t Controller::GetControllerLocalSupportedFeatures() const {
return impl_->local_supported_features_;
}
-uint64_t Controller::GetControllerLocalExtendedFeatures(uint8_t page_number) {
+uint64_t Controller::GetControllerLocalExtendedFeatures(uint8_t page_number) const {
if (page_number <= impl_->maximum_page_number_) {
return impl_->extended_lmp_features_array_[page_number];
}
return 0x00;
}
-uint16_t Controller::GetControllerAclPacketLength() {
+uint16_t Controller::GetControllerAclPacketLength() const {
return impl_->acl_buffer_length_;
}
-uint16_t Controller::GetControllerNumAclPacketBuffers() {
+uint16_t Controller::GetControllerNumAclPacketBuffers() const {
return impl_->acl_buffers_;
}
-uint8_t Controller::GetControllerScoPacketLength() {
+uint8_t Controller::GetControllerScoPacketLength() const {
return impl_->sco_buffer_length_;
}
-uint16_t Controller::GetControllerNumScoPacketBuffers() {
+uint16_t Controller::GetControllerNumScoPacketBuffers() const {
return impl_->sco_buffers_;
}
-Address Controller::GetControllerMacAddress() {
+Address Controller::GetControllerMacAddress() const {
return impl_->mac_address_;
}
@@ -813,35 +813,35 @@ void Controller::LeSetEventMask(uint64_t le_event_mask) {
GetHandler()->Post(common::BindOnce(&impl::le_set_event_mask, common::Unretained(impl_.get()), le_event_mask));
}
-LeBufferSize Controller::GetControllerLeBufferSize() {
+LeBufferSize Controller::GetControllerLeBufferSize() const {
return impl_->le_buffer_size_;
}
-uint64_t Controller::GetControllerLeLocalSupportedFeatures() {
+uint64_t Controller::GetControllerLeLocalSupportedFeatures() const {
return impl_->le_local_supported_features_;
}
-uint64_t Controller::GetControllerLeSupportedStates() {
+uint64_t Controller::GetControllerLeSupportedStates() const {
return impl_->le_supported_states_;
}
-LeMaximumDataLength Controller::GetControllerLeMaximumDataLength() {
+LeMaximumDataLength Controller::GetControllerLeMaximumDataLength() const {
return impl_->le_maximum_data_length_;
}
-uint16_t Controller::GetControllerLeMaximumAdvertisingDataLength() {
+uint16_t Controller::GetControllerLeMaximumAdvertisingDataLength() const {
return impl_->le_maximum_advertising_data_length_;
}
-uint16_t Controller::GetControllerLeNumberOfSupportedAdverisingSets() {
+uint16_t Controller::GetControllerLeNumberOfSupportedAdverisingSets() const {
return impl_->le_number_supported_advertising_sets_;
}
-VendorCapabilities Controller::GetControllerVendorCapabilities() {
+VendorCapabilities Controller::GetControllerVendorCapabilities() const {
return impl_->vendor_capabilities_;
}
-bool Controller::IsSupported(bluetooth::hci::OpCode op_code) {
+bool Controller::IsSupported(bluetooth::hci::OpCode op_code) const {
return impl_->is_supported(op_code);
}
diff --git a/gd/hci/controller.h b/gd/hci/controller.h
index 3a4ee1c13..3f2d2cd6a 100644
--- a/gd/hci/controller.h
+++ b/gd/hci/controller.h
@@ -34,27 +34,27 @@ class Controller : public Module {
virtual void RegisterCompletedAclPacketsCallback(
common::Callback<void(uint16_t /* handle */, uint16_t /* num_packets */)> cb, os::Handler* handler);
- virtual std::string GetControllerLocalName();
+ virtual std::string GetControllerLocalName() const;
- virtual LocalVersionInformation GetControllerLocalVersionInformation();
+ virtual LocalVersionInformation GetControllerLocalVersionInformation() const;
- virtual std::array<uint8_t, 64> GetControllerLocalSupportedCommands();
+ virtual std::array<uint8_t, 64> GetControllerLocalSupportedCommands() const;
- virtual uint64_t GetControllerLocalSupportedFeatures();
+ virtual uint64_t GetControllerLocalSupportedFeatures() const;
- virtual uint8_t GetControllerLocalExtendedFeaturesMaxPageNumber();
+ virtual uint8_t GetControllerLocalExtendedFeaturesMaxPageNumber() const;
- virtual uint64_t GetControllerLocalExtendedFeatures(uint8_t page_number);
+ virtual uint64_t GetControllerLocalExtendedFeatures(uint8_t page_number) const;
- virtual uint16_t GetControllerAclPacketLength();
+ virtual uint16_t GetControllerAclPacketLength() const;
- virtual uint16_t GetControllerNumAclPacketBuffers();
+ virtual uint16_t GetControllerNumAclPacketBuffers() const;
- virtual uint8_t GetControllerScoPacketLength();
+ virtual uint8_t GetControllerScoPacketLength() const;
- virtual uint16_t GetControllerNumScoPacketBuffers();
+ virtual uint16_t GetControllerNumScoPacketBuffers() const;
- virtual Address GetControllerMacAddress();
+ virtual Address GetControllerMacAddress() const;
virtual void SetEventMask(uint64_t event_mask);
@@ -86,21 +86,21 @@ class Controller : public Module {
// LE controller commands
virtual void LeSetEventMask(uint64_t le_event_mask);
- LeBufferSize GetControllerLeBufferSize();
+ virtual LeBufferSize GetControllerLeBufferSize() const;
- uint64_t GetControllerLeLocalSupportedFeatures();
+ virtual uint64_t GetControllerLeLocalSupportedFeatures() const;
- uint64_t GetControllerLeSupportedStates();
+ virtual uint64_t GetControllerLeSupportedStates() const;
- LeMaximumDataLength GetControllerLeMaximumDataLength();
+ virtual LeMaximumDataLength GetControllerLeMaximumDataLength() const;
- uint16_t GetControllerLeMaximumAdvertisingDataLength();
+ virtual uint16_t GetControllerLeMaximumAdvertisingDataLength() const;
- uint16_t GetControllerLeNumberOfSupportedAdverisingSets();
+ virtual uint16_t GetControllerLeNumberOfSupportedAdverisingSets() const;
- VendorCapabilities GetControllerVendorCapabilities();
+ virtual VendorCapabilities GetControllerVendorCapabilities() const;
- bool IsSupported(OpCode op_code);
+ virtual bool IsSupported(OpCode op_code) const;
static const ModuleFactory Factory;
diff --git a/gd/hci/hci_packets.pdl b/gd/hci/hci_packets.pdl
index 911bc789a..255306cd2 100644
--- a/gd/hci/hci_packets.pdl
+++ b/gd/hci/hci_packets.pdl
@@ -2203,9 +2203,11 @@ packet LeSetRandomAddressComplete : CommandComplete (command_op_code = LE_SET_RA
status : ErrorCode,
}
-enum AdvertisingFilterPolicy : 1 {
+enum AdvertisingFilterPolicy : 2 {
ALL_DEVICES = 0, // Default
- ONLY_WHITE_LISTED_DEVICES = 1,
+ WHITELISTED_SCAN = 1,
+ WHITELISTED_CONNECT = 2,
+ WHITELISTED_SCAN_AND_CONNECT = 3,
}
enum PeerAddressType : 8 {
@@ -2616,12 +2618,33 @@ packet LeSetPeriodicAdvertisingEnable : LeAdvertisingCommand (op_code = LE_SET_P
_payload_, // placeholder (unimplemented)
}
-packet LeSetExtendedScanParameters : LeAdvertisingCommand (op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
- _payload_, // placeholder (unimplemented)
+packet LeSetExtendedScanParameters : LeScanningCommand (op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
+ le_scan_type : LeScanType,
+ le_scan_interval : 32, // 0x0004-0x00FFFFFF Default 0x10 (10ms)
+ le_scan_window : 32, // 0x004-0xFFFF Default 0x10 (10ms)
+ own_address_type : AddressType,
+ scanning_filter_policy : LeSetScanningFilterPolicy,
}
-packet LeSetExtendedScanEnable : LeAdvertisingCommand (op_code = LE_SET_EXTENDED_SCAN_ENABLE) {
- _payload_, // placeholder (unimplemented)
+packet LeSetExtendedScanParametersComplete : CommandComplete (command_op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
+ status : ErrorCode,
+}
+
+enum FilterDuplicates : 8 {
+ DISABLED = 0,
+ ENABLED = 1,
+ RESET_EACH_PERIOD = 2,
+}
+
+packet LeSetExtendedScanEnable : LeScanningCommand (op_code = LE_SET_EXTENDED_SCAN_ENABLE) {
+ enable : Enable,
+ filter_duplicates : FilterDuplicates,
+ duration : 16, // 0 - Scan continuously, N * 10 ms
+ period : 16, // 0 - Scan continuously, N * 1.28 sec
+}
+
+packet LeSetExtendedScanEnableComplete : CommandComplete (command_op_code = LE_SET_EXTENDED_SCAN_ENABLE) {
+ status : ErrorCode,
}
packet LeExtendedCreateConnection : LeConnectionManagementCommand (op_code = LE_EXTENDED_CREATE_CONNECTION) {
@@ -2728,11 +2751,11 @@ packet LeGetVendorCapabilitiesComplete098 : LeGetVendorCapabilitiesComplete096 {
}
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,
+ SET_PARAM = 0x01,
+ SET_DATA = 0x02,
+ SET_SCAN_RESP = 0x03,
+ SET_RANDOM_ADDR = 0x04,
+ SET_ENABLE = 0x05,
}
packet LeMultiAdvt : LeAdvertisingCommand (op_code = LE_MULTI_ADVT) {
@@ -2740,12 +2763,12 @@ packet LeMultiAdvt : LeAdvertisingCommand (op_code = LE_MULTI_ADVT) {
_body_,
}
-packet LeMultiAdvtParamComplete : CommandComplete (command_op_code = LE_MULTI_ADVT) {
+packet LeMultiAdvtComplete : CommandComplete (command_op_code = LE_MULTI_ADVT) {
status : ErrorCode,
sub_cmd : SubOcf,
}
-packet LeMultiAdvtParam : LeMultiAdvt (sub_cmd = SET_ADVT_PARAM) {
+packet LeMultiAdvtParam : LeMultiAdvt (sub_cmd = SET_PARAM) {
interval_min : 16,
interval_max : 16,
type : AdvertisingEventType,
@@ -2759,30 +2782,45 @@ packet LeMultiAdvtParam : LeMultiAdvt (sub_cmd = SET_ADVT_PARAM) {
tx_power : 8,
}
-packet LeMultiAdvtParamSetData : LeMultiAdvt (sub_cmd = SET_ADVT_DATA) {
+packet LeMultiAdvtParamComplete : LeMultiAdvtComplete (sub_cmd = SET_PARAM) {
+}
+
+packet LeMultiAdvtSetData : LeMultiAdvt (sub_cmd = SET_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) {
+packet LeMultiAdvtSetDataComplete : LeMultiAdvtComplete (sub_cmd = SET_DATA) {
+}
+
+packet LeMultiAdvtSetScanResp : LeMultiAdvt (sub_cmd = SET_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) {
+packet LeMultiAdvtSetScanRespComplete : LeMultiAdvtComplete (sub_cmd = SET_SCAN_RESP) {
+}
+
+packet LeMultiAdvtSetRandomAddr : LeMultiAdvt (sub_cmd = SET_RANDOM_ADDR) {
random_address : Address,
advertising_instance : 8,
}
-packet LeMultiAdvtParamSetEnable : LeMultiAdvt (sub_cmd = SET_ADVT_ENABLE) {
+packet LeMultiAdvtSetRandomAddrComplete : LeMultiAdvtComplete (sub_cmd = SET_RANDOM_ADDR) {
+}
+
+packet LeMultiAdvtSetEnable : LeMultiAdvt (sub_cmd = SET_ENABLE) {
advertising_enable : Enable, // Default DISABLED
advertising_instance : 8,
}
+packet LeMultiAdvtSetEnableComplete : LeMultiAdvtComplete (sub_cmd = SET_ENABLE) {
+}
+
packet LeBatchScan : VendorCommand (op_code = LE_BATCH_SCAN) {
_payload_, // placeholder (unimplemented)
}
@@ -2816,8 +2854,16 @@ packet LeEnergyInfo : VendorCommand (op_code = LE_ENERGY_INFO) {
_payload_, // placeholder (unimplemented)
}
-packet LeExtendedScanParams : VendorCommand (op_code = LE_EXTENDED_SCAN_PARAMS) {
- _payload_, // placeholder (unimplemented)
+packet LeExtendedScanParams : LeScanningCommand (op_code = LE_EXTENDED_SCAN_PARAMS) {
+ le_scan_type : LeScanType,
+ le_scan_interval : 32, // 0x0004-0x4000 Default 0x10 (10ms)
+ le_scan_window : 32, // Default 0x10 (10ms)
+ own_address_type : AddressType,
+ scanning_filter_policy : LeSetScanningFilterPolicy,
+}
+
+packet LeExtendedScanParamsComplete : CommandComplete (command_op_code = LE_EXTENDED_SCAN_PARAMS) {
+ status : ErrorCode,
}
packet ControllerDebugInfo : VendorCommand (op_code = CONTROLLER_DEBUG_INFO) {
diff --git a/gd/hci/le_advertising_manager.cc b/gd/hci/le_advertising_manager.cc
index a77611346..35e30a707 100644
--- a/gd/hci/le_advertising_manager.cc
+++ b/gd/hci/le_advertising_manager.cc
@@ -30,6 +30,12 @@ namespace hci {
const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });
+enum class AdvertisingApiType {
+ LE_4_0 = 1,
+ ANDROID_HCI = 2,
+ LE_5_0 = 3,
+};
+
struct Advertiser {
os::Handler* handler;
common::Callback<void(Address, AddressType)> scan_callback;
@@ -37,14 +43,22 @@ struct Advertiser {
};
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) {}
+ impl(Module* module) : module_(module), le_advertising_interface_(nullptr), num_instances_(0) {}
- void start() {
+ void start(os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) {
+ module_handler_ = handler;
+ hci_layer_ = hci_layer;
+ controller_ = controller;
le_advertising_interface_ = hci_layer_->GetLeAdvertisingInterface(
common::Bind(&LeAdvertisingManager::impl::handle_event, common::Unretained(this)), module_handler_);
num_instances_ = controller_->GetControllerLeNumberOfSupportedAdverisingSets();
+ if (controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) {
+ advertising_api_type_ = AdvertisingApiType::LE_5_0;
+ } else if (controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) {
+ advertising_api_type_ = AdvertisingApiType::ANDROID_HCI;
+ } else {
+ advertising_api_type_ = AdvertisingApiType::LE_4_0;
+ }
}
size_t GetNumberOfAdvertisingInstances() const {
@@ -87,7 +101,7 @@ struct LeAdvertisingManager::impl {
AdvertiserId id = 0;
{
std::unique_lock lock(id_mutex_);
- while (id < num_instances_ && advertising_sets_.count(id) == 0) {
+ while (id < num_instances_ && advertising_sets_.count(id) != 0) {
id++;
}
}
@@ -112,48 +126,72 @@ struct LeAdvertisingManager::impl {
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;
+ switch (advertising_api_type_) {
+ case (AdvertisingApiType::LE_4_0):
+ 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_status<LeSetAdvertisingParametersCompleteView>), module_handler_);
+ le_advertising_interface_->EnqueueCommand(hci::LeSetRandomAddressBuilder::Create(config.random_address),
+ common::BindOnce(impl::check_status<LeSetRandomAddressCompleteView>),
+ module_handler_);
+ if (!config.scan_response.empty()) {
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeSetScanResponseDataBuilder::Create(config.scan_response),
+ common::BindOnce(impl::check_status<LeSetScanResponseDataCompleteView>), module_handler_);
+ }
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeSetAdvertisingDataBuilder::Create(config.advertisement),
+ common::BindOnce(impl::check_status<LeSetAdvertisingDataCompleteView>), module_handler_);
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
+ common::BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>), module_handler_);
+ break;
+ case (AdvertisingApiType::ANDROID_HCI):
+ 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_status<LeMultiAdvtCompleteView>), module_handler_);
+ le_advertising_interface_->EnqueueCommand(hci::LeMultiAdvtSetDataBuilder::Create(config.advertisement, id),
+ common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>),
+ module_handler_);
+ if (!config.scan_response.empty()) {
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtSetScanRespBuilder::Create(config.scan_response, id),
+ common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>), module_handler_);
+ }
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtSetRandomAddrBuilder::Create(config.random_address, id),
+ common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>), module_handler_);
+ le_advertising_interface_->EnqueueCommand(hci::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id),
+ common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>),
+ module_handler_);
+ break;
+ case (AdvertisingApiType::LE_5_0): {
+ ExtendedAdvertisingConfig new_config;
+ AdvertisingConfig* base_config_ptr = &new_config;
+ *(base_config_ptr) = config;
+ create_extended_advertiser(id, new_config, scan_callback, set_terminated_callback, handler);
+ } break;
}
- 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)) {
+ if (advertising_api_type_ != AdvertisingApiType::LE_5_0) {
create_advertiser(id, config, scan_callback, set_terminated_callback, handler);
return;
- } else {
- LOG_ALWAYS_FATAL("LE_SET_EXTENDED_ADVERTISING_PARAMETERS isn't implemented.");
}
+ 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),
+ config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_status),
module_handler_);
*/
advertising_sets_[id].scan_callback = scan_callback;
@@ -167,14 +205,15 @@ struct LeAdvertisingManager::impl {
return;
}
le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
- common::BindOnce(impl::check_enable_status), module_handler_);
+ common::BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>),
+ 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_;
+ os::Handler* registered_handler_{nullptr};
Module* module_;
os::Handler* module_handler_;
hci::HciLayer* hci_layer_;
@@ -185,21 +224,21 @@ struct LeAdvertisingManager::impl {
std::mutex id_mutex_;
size_t num_instances_;
- static void check_enable_status(CommandCompleteView view) {
+ AdvertisingApiType advertising_api_type_{0};
+
+ template <class View>
+ static void check_status(CommandCompleteView view) {
ASSERT(view.IsValid());
- auto status_view = LeSetAdvertisingEnableCompleteView::Create(view);
+ auto status_view = View::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>());
+ pimpl_ = std::make_unique<impl>(this);
}
void LeAdvertisingManager::ListDependencies(ModuleList* list) {
@@ -208,7 +247,7 @@ void LeAdvertisingManager::ListDependencies(ModuleList* list) {
}
void LeAdvertisingManager::Start() {
- pimpl_->start();
+ pimpl_->start(GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>());
}
void LeAdvertisingManager::Stop() {
@@ -225,10 +264,12 @@ AdvertiserId LeAdvertisingManager::CreateAdvertiser(
if (config.peer_address == Address::kEmpty) {
if (config.address_type == hci::AddressType::PUBLIC_IDENTITY_ADDRESS ||
config.address_type == hci::AddressType::RANDOM_IDENTITY_ADDRESS) {
+ LOG_WARN("Peer address can not be empty");
return kInvalidId;
}
if (config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND ||
config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND_LOW) {
+ LOG_WARN("Peer address can not be empty for directed advertising");
return kInvalidId;
}
}
@@ -244,11 +285,34 @@ AdvertiserId LeAdvertisingManager::CreateAdvertiser(
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) {
+ if (config.directed) {
+ if (config.peer_address == Address::kEmpty) {
+ LOG_INFO("Peer address can not be empty for directed advertising");
+ return kInvalidId;
+ }
+ }
+ if (config.channel_map == 0) {
+ LOG_INFO("At least one channel must be set in the map");
+ return kInvalidId;
+ }
+ if (!config.legacy_pdus) {
+ if (config.connectable && config.scannable) {
+ LOG_INFO("Extended advertising PDUs can not be connectable and scannable");
+ return kInvalidId;
+ }
+ if (config.high_duty_directed_connectable) {
+ LOG_INFO("Extended advertising PDUs can not be high duty cycle");
+ return kInvalidId;
+ }
+ }
+ if (config.interval_min > config.interval_max) {
+ LOG_INFO("Advertising interval: min (%hu) > max (%hu)", config.interval_min, config.interval_max);
+ return kInvalidId;
+ }
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;
diff --git a/gd/hci/le_advertising_manager.h b/gd/hci/le_advertising_manager.h
index 90199e6f4..2cbfc5944 100644
--- a/gd/hci/le_advertising_manager.h
+++ b/gd/hci/le_advertising_manager.h
@@ -59,7 +59,7 @@ using AdvertiserId = int32_t;
class LeAdvertisingManager : public bluetooth::Module {
public:
- static const AdvertiserId kInvalidId;
+ static constexpr AdvertiserId kInvalidId = -1;
LeAdvertisingManager();
size_t GetNumberOfAdvertisingInstances() const;
diff --git a/gd/hci/le_advertising_manager_test.cc b/gd/hci/le_advertising_manager_test.cc
new file mode 100644
index 000000000..c4f40ad22
--- /dev/null
+++ b/gd/hci/le_advertising_manager_test.cc
@@ -0,0 +1,356 @@
+/*
+ * 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 "hci/le_advertising_manager.h"
+
+#include <algorithm>
+#include <chrono>
+#include <future>
+#include <map>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "common/bind.h"
+#include "hci/address.h"
+#include "hci/controller.h"
+#include "hci/hci_layer.h"
+#include "os/thread.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace hci {
+namespace {
+
+using packet::kLittleEndian;
+using packet::PacketView;
+using packet::RawBuilder;
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ BitInserter i(*bytes);
+ bytes->reserve(packet->size());
+ packet->Serialize(i);
+ return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+class TestController : public Controller {
+ public:
+ bool IsSupported(OpCode op_code) const override {
+ return supported_opcodes_.count(op_code) == 1;
+ }
+
+ void AddSupported(OpCode op_code) {
+ supported_opcodes_.insert(op_code);
+ }
+
+ uint16_t GetControllerLeNumberOfSupportedAdverisingSets() const override {
+ return num_advertisers;
+ }
+
+ uint16_t num_advertisers{0};
+
+ protected:
+ void Start() override {}
+ void Stop() override {}
+ void ListDependencies(ModuleList* list) override {}
+
+ private:
+ std::set<OpCode> supported_opcodes_{};
+};
+
+class TestHciLayer : public HciLayer {
+ public:
+ TestHciLayer() {
+ RegisterEventHandler(EventCode::COMMAND_COMPLETE,
+ base::Bind(&TestHciLayer::CommandCompleteCallback, common::Unretained(this)), nullptr);
+ RegisterEventHandler(EventCode::COMMAND_STATUS,
+ base::Bind(&TestHciLayer::CommandStatusCallback, common::Unretained(this)), nullptr);
+ }
+
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+ common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) override {
+ command_queue_.push_back(std::move(command));
+ command_status_callbacks.push_back(std::move(on_status));
+ if (command_promise_ != nullptr) {
+ command_promise_->set_value(command_queue_.size());
+ command_promise_.reset();
+ }
+ }
+
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+ common::OnceCallback<void(CommandCompleteView)> on_complete, os::Handler* handler) override {
+ command_queue_.push_back(std::move(command));
+ command_complete_callbacks.push_back(std::move(on_complete));
+ if (command_promise_ != nullptr) {
+ command_promise_->set_value(command_queue_.size());
+ command_promise_.reset();
+ }
+ }
+
+ std::future<size_t> GetCommandFuture() {
+ ASSERT_LOG(command_promise_ == nullptr, "Promises promises ... Only one at a time");
+ command_promise_ = std::make_unique<std::promise<size_t>>();
+ return command_promise_->get_future();
+ }
+
+ std::unique_ptr<CommandPacketBuilder> GetLastCommand() {
+ ASSERT(!command_queue_.empty());
+ auto last = std::move(command_queue_.front());
+ command_queue_.pop_front();
+ return last;
+ }
+
+ ConnectionManagementCommandView GetCommandPacket(OpCode op_code) {
+ auto packet_view = GetPacketView(GetLastCommand());
+ CommandPacketView command_packet_view = CommandPacketView::Create(packet_view);
+ ConnectionManagementCommandView command = ConnectionManagementCommandView::Create(command_packet_view);
+ ASSERT(command.IsValid());
+ EXPECT_EQ(command.GetOpCode(), op_code);
+
+ return command;
+ }
+
+ void RegisterEventHandler(EventCode event_code, common::Callback<void(EventPacketView)> event_handler,
+ os::Handler* handler) override {
+ registered_events_[event_code] = event_handler;
+ }
+
+ void RegisterLeEventHandler(SubeventCode subevent_code, common::Callback<void(LeMetaEventView)> event_handler,
+ os::Handler* handler) override {
+ registered_le_events_[subevent_code] = event_handler;
+ }
+
+ void IncomingEvent(std::unique_ptr<EventPacketBuilder> event_builder) {
+ auto packet = GetPacketView(std::move(event_builder));
+ EventPacketView event = EventPacketView::Create(packet);
+ ASSERT_TRUE(event.IsValid());
+ EventCode event_code = event.GetEventCode();
+ ASSERT_TRUE(registered_events_.find(event_code) != registered_events_.end()) << EventCodeText(event_code);
+ registered_events_[event_code].Run(event);
+ }
+
+ void IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) {
+ auto packet = GetPacketView(std::move(event_builder));
+ EventPacketView event = EventPacketView::Create(packet);
+ LeMetaEventView meta_event_view = LeMetaEventView::Create(event);
+ ASSERT_TRUE(meta_event_view.IsValid());
+ SubeventCode subevent_code = meta_event_view.GetSubeventCode();
+ ASSERT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end())
+ << SubeventCodeText(subevent_code);
+ registered_le_events_[subevent_code].Run(meta_event_view);
+ }
+
+ void CommandCompleteCallback(EventPacketView event) {
+ CommandCompleteView complete_view = CommandCompleteView::Create(event);
+ ASSERT(complete_view.IsValid());
+ std::move(command_complete_callbacks.front()).Run(complete_view);
+ command_complete_callbacks.pop_front();
+ }
+
+ void CommandStatusCallback(EventPacketView event) {
+ CommandStatusView status_view = CommandStatusView::Create(event);
+ ASSERT(status_view.IsValid());
+ std::move(command_status_callbacks.front()).Run(status_view);
+ command_status_callbacks.pop_front();
+ }
+
+ void ListDependencies(ModuleList* list) override {}
+ void Start() override {}
+ void Stop() override {}
+
+ private:
+ std::map<EventCode, common::Callback<void(EventPacketView)>> registered_events_;
+ std::map<SubeventCode, common::Callback<void(LeMetaEventView)>> registered_le_events_;
+ std::list<base::OnceCallback<void(CommandCompleteView)>> command_complete_callbacks;
+ std::list<base::OnceCallback<void(CommandStatusView)>> command_status_callbacks;
+
+ std::list<std::unique_ptr<CommandPacketBuilder>> command_queue_;
+ mutable std::mutex mutex_;
+ std::unique_ptr<std::promise<size_t>> command_promise_{};
+};
+
+class LeAdvertisingManagerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ test_hci_layer_ = new TestHciLayer; // Ownership is transferred to registry
+ test_controller_ = new TestController;
+ test_controller_->AddSupported(param_opcode_);
+ fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_);
+ fake_registry_.InjectTestModule(&Controller::Factory, test_controller_);
+ client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory);
+ ASSERT_NE(client_handler_, nullptr);
+ test_controller_->num_advertisers = 1;
+ fake_registry_.Start<LeAdvertisingManager>(&thread_);
+ le_advertising_manager_ =
+ static_cast<LeAdvertisingManager*>(fake_registry_.GetModuleUnderTest(&LeAdvertisingManager::Factory));
+ }
+
+ void TearDown() override {
+ fake_registry_.SynchronizeModuleHandler(&LeAdvertisingManager::Factory, std::chrono::milliseconds(20));
+ fake_registry_.StopAll();
+ }
+
+ TestModuleRegistry fake_registry_;
+ TestHciLayer* test_hci_layer_ = nullptr;
+ TestController* test_controller_ = nullptr;
+ os::Thread& thread_ = fake_registry_.GetTestThread();
+ LeAdvertisingManager* le_advertising_manager_ = nullptr;
+ os::Handler* client_handler_ = nullptr;
+
+ const common::Callback<void(Address, AddressType)> scan_callback =
+ common::Bind(&LeAdvertisingManagerTest::on_scan, common::Unretained(this));
+ const common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback =
+ common::Bind(&LeAdvertisingManagerTest::on_set_terminated, common::Unretained(this));
+
+ std::future<Address> GetOnScanPromise() {
+ ASSERT_LOG(address_promise_ == nullptr, "Promises promises ... Only one at a time");
+ address_promise_ = std::make_unique<std::promise<Address>>();
+ return address_promise_->get_future();
+ }
+ void on_scan(Address address, AddressType address_type) {
+ if (address_promise_ == nullptr) {
+ return;
+ }
+ address_promise_->set_value(address);
+ address_promise_.reset();
+ }
+
+ std::future<ErrorCode> GetSetTerminatedPromise() {
+ ASSERT_LOG(set_terminated_promise_ == nullptr, "Promises promises ... Only one at a time");
+ set_terminated_promise_ = std::make_unique<std::promise<ErrorCode>>();
+ return set_terminated_promise_->get_future();
+ }
+ void on_set_terminated(ErrorCode error_code, uint8_t, uint8_t) {
+ if (set_terminated_promise_ != nullptr) {
+ return;
+ }
+ set_terminated_promise_->set_value(error_code);
+ set_terminated_promise_.reset();
+ }
+
+ std::unique_ptr<std::promise<Address>> address_promise_{};
+ std::unique_ptr<std::promise<ErrorCode>> set_terminated_promise_{};
+
+ OpCode param_opcode_{OpCode::LE_SET_ADVERTISING_PARAMETERS};
+};
+
+class LeAndroidHciAdvertisingManagerTest : public LeAdvertisingManagerTest {
+ protected:
+ void SetUp() override {
+ param_opcode_ = OpCode::LE_MULTI_ADVT;
+ LeAdvertisingManagerTest::SetUp();
+ test_controller_->num_advertisers = 3;
+ }
+};
+
+class LeExtendedAdvertisingManagerTest : public LeAdvertisingManagerTest {
+ protected:
+ void SetUp() override {
+ param_opcode_ = OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS;
+ LeAdvertisingManagerTest::SetUp();
+ test_controller_->num_advertisers = 5;
+ }
+};
+
+TEST_F(LeAdvertisingManagerTest, startup_teardown) {}
+
+TEST_F(LeAndroidHciAdvertisingManagerTest, startup_teardown) {}
+
+TEST_F(LeExtendedAdvertisingManagerTest, startup_teardown) {}
+
+TEST_F(LeAdvertisingManagerTest, create_advertiser_test) {
+ AdvertisingConfig advertising_config{};
+ advertising_config.event_type = AdvertisingEventType::ADV_IND;
+ advertising_config.address_type = AddressType::PUBLIC_DEVICE_ADDRESS;
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ advertising_config.advertisement = gap_data;
+ advertising_config.scan_response = gap_data;
+
+ auto next_command_future = test_hci_layer_->GetCommandFuture();
+ auto id = le_advertising_manager_->CreateAdvertiser(advertising_config, scan_callback, set_terminated_callback,
+ client_handler_);
+ ASSERT_NE(LeAdvertisingManager::kInvalidId, id);
+ std::vector<OpCode> adv_opcodes = {
+ OpCode::LE_SET_ADVERTISING_PARAMETERS, OpCode::LE_SET_RANDOM_ADDRESS, OpCode::LE_SET_SCAN_RESPONSE_DATA,
+ OpCode::LE_SET_ADVERTISING_DATA, OpCode::LE_SET_ADVERTISING_ENABLE,
+ };
+ auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ ASSERT_NE(std::future_status::timeout, result);
+ size_t num_commands = next_command_future.get();
+ for (size_t i = 0; i < adv_opcodes.size(); i++) {
+ auto packet = test_hci_layer_->GetCommandPacket(adv_opcodes[i]);
+ std::vector<uint8_t> success_vector{static_cast<uint8_t>(ErrorCode::SUCCESS)};
+ test_hci_layer_->IncomingEvent(
+ CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
+ if (i < adv_opcodes.size() - 1 && --num_commands == 1) {
+ next_command_future = test_hci_layer_->GetCommandFuture();
+ result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ ASSERT_NE(std::future_status::timeout, result);
+ num_commands = next_command_future.get();
+ }
+ }
+}
+
+TEST_F(LeAndroidHciAdvertisingManagerTest, create_advertiser_test) {
+ AdvertisingConfig advertising_config{};
+ advertising_config.event_type = AdvertisingEventType::ADV_IND;
+ advertising_config.address_type = AddressType::PUBLIC_DEVICE_ADDRESS;
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ advertising_config.advertisement = gap_data;
+ advertising_config.scan_response = gap_data;
+
+ auto next_command_future = test_hci_layer_->GetCommandFuture();
+ auto id = le_advertising_manager_->CreateAdvertiser(advertising_config, scan_callback, set_terminated_callback,
+ client_handler_);
+ ASSERT_NE(LeAdvertisingManager::kInvalidId, id);
+ std::vector<SubOcf> sub_ocf = {
+ SubOcf::SET_PARAM, SubOcf::SET_DATA, SubOcf::SET_SCAN_RESP, SubOcf::SET_RANDOM_ADDR, SubOcf::SET_ENABLE,
+ };
+ auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ ASSERT_NE(std::future_status::timeout, result);
+ size_t num_commands = next_command_future.get();
+ for (size_t i = 0; i < sub_ocf.size(); i++) {
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ std::vector<uint8_t> success_vector{static_cast<uint8_t>(ErrorCode::SUCCESS), static_cast<uint8_t>(sub_ocf[i])};
+ test_hci_layer_->IncomingEvent(CommandCompleteBuilder::Create(uint8_t{1}, OpCode::LE_MULTI_ADVT,
+ std::make_unique<RawBuilder>(success_vector)));
+ if (i < sub_ocf.size() - 1 && --num_commands == 1) {
+ next_command_future = test_hci_layer_->GetCommandFuture();
+ result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ ASSERT_NE(std::future_status::timeout, result);
+ num_commands = next_command_future.get();
+ }
+ }
+}
+
+} // namespace
+} // namespace hci
+} // namespace bluetooth
diff --git a/gd/hci/le_report.h b/gd/hci/le_report.h
new file mode 100644
index 000000000..7dc075f8e
--- /dev/null
+++ b/gd/hci/le_report.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <memory>
+
+#include "hci/hci_packets.h"
+
+namespace bluetooth::hci {
+
+class LeReport {
+ public:
+ explicit LeReport(const LeAdvertisingReport& advertisement)
+ : report_type_(ReportType::ADVERTISING_EVENT), advertising_event_type_(advertisement.event_type_),
+ address_(advertisement.address_), address_type_(advertisement.address_type_), rssi_(advertisement.rssi_),
+ gap_data_(advertisement.advertising_data_) {}
+ explicit LeReport(const LeDirectedAdvertisingReport& advertisement)
+ : report_type_(ReportType::DIRECTED_ADVERTISING_EVENT), address_(advertisement.address_),
+ rssi_(advertisement.rssi_) {}
+ explicit LeReport(const LeExtendedAdvertisingReport& advertisement)
+ : report_type_(ReportType::EXTENDED_ADVERTISING_EVENT), address_(advertisement.address_),
+ rssi_(advertisement.rssi_), gap_data_(advertisement.advertising_data_) {}
+ virtual ~LeReport() = default;
+
+ enum class ReportType {
+ ADVERTISING_EVENT = 1,
+ DIRECTED_ADVERTISING_EVENT = 2,
+ EXTENDED_ADVERTISING_EVENT = 3,
+ };
+ const ReportType report_type_;
+
+ ReportType GetReportType() const {
+ return report_type_;
+ }
+
+ // Advertising Event
+ const AdvertisingEventType advertising_event_type_{};
+ const Address address_{};
+ const AddressType address_type_{};
+ const uint8_t rssi_;
+ const std::vector<GapData> gap_data_{};
+};
+
+class DirectedLeReport : public LeReport {
+ public:
+ explicit DirectedLeReport(const LeDirectedAdvertisingReport& advertisement)
+ : LeReport(advertisement), direct_address_type_(advertisement.address_type_) {}
+ explicit DirectedLeReport(const LeExtendedAdvertisingReport& advertisement)
+ : LeReport(advertisement), direct_address_type_(advertisement.address_type_) {}
+
+ const DirectAdvertisingAddressType direct_address_type_{};
+};
+
+class ExtendedLeReport : public DirectedLeReport {
+ public:
+ explicit ExtendedLeReport(const LeExtendedAdvertisingReport& advertisement)
+ : DirectedLeReport(advertisement), connectable_(advertisement.connectable_), scannable_(advertisement.scannable_),
+ directed_(advertisement.directed_), scan_response_(advertisement.scan_response_),
+ complete_(advertisement.data_status_ == DataStatus::COMPLETE),
+ truncated_(advertisement.data_status_ == DataStatus::TRUNCATED) {}
+
+ // Extended
+ bool connectable_;
+ bool scannable_;
+ bool directed_;
+ bool scan_response_;
+ bool complete_;
+ bool truncated_;
+};
+} // namespace bluetooth::hci \ No newline at end of file
diff --git a/gd/hci/le_scanning_interface.h b/gd/hci/le_scanning_interface.h
index 4d93f251c..97a676625 100644
--- a/gd/hci/le_scanning_interface.h
+++ b/gd/hci/le_scanning_interface.h
@@ -38,6 +38,12 @@ class LeScanningInterface {
static constexpr hci::SubeventCode LeScanningEvents[] = {
hci::SubeventCode::SCAN_TIMEOUT,
+ 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,
};
};
} // namespace hci
diff --git a/gd/hci/le_scanning_manager.cc b/gd/hci/le_scanning_manager.cc
new file mode 100644
index 000000000..1562dd626
--- /dev/null
+++ b/gd/hci/le_scanning_manager.cc
@@ -0,0 +1,247 @@
+/*
+ * 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 <set>
+
+#include "hci/controller.h"
+#include "hci/hci_layer.h"
+#include "hci/hci_packets.h"
+#include "hci/le_scanning_interface.h"
+#include "hci/le_scanning_manager.h"
+#include "module.h"
+#include "os/handler.h"
+#include "os/log.h"
+
+namespace bluetooth {
+namespace hci {
+
+const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });
+
+enum class ScanApiType {
+ LE_4_0 = 1,
+ ANDROID_HCI = 2,
+ LE_5_0 = 3,
+};
+
+struct LeScanningManager::impl {
+ impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {}
+
+ void start(os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) {
+ module_handler_ = handler;
+ hci_layer_ = hci_layer;
+ controller_ = controller;
+ le_scanning_interface_ = hci_layer_->GetLeScanningInterface(
+ common::Bind(&LeScanningManager::impl::handle_scan_results, common::Unretained(this)), module_handler_);
+ if (controller_->IsSupported(OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS)) {
+ api_type_ = ScanApiType::LE_5_0;
+ } else if (controller_->IsSupported(OpCode::LE_EXTENDED_SCAN_PARAMS)) {
+ api_type_ = ScanApiType::ANDROID_HCI;
+ } else {
+ api_type_ = ScanApiType::LE_4_0;
+ }
+ configure_scan();
+ }
+
+ void handle_scan_results(LeMetaEventView event) {
+ switch (event.GetSubeventCode()) {
+ case hci::SubeventCode::ADVERTISING_REPORT:
+ handle_advertising_report<LeAdvertisingReportView, LeAdvertisingReport, LeReport>(
+ LeAdvertisingReportView::Create(event));
+ break;
+ case hci::SubeventCode::DIRECTED_ADVERTISING_REPORT:
+ handle_advertising_report<LeDirectedAdvertisingReportView, LeDirectedAdvertisingReport, DirectedLeReport>(
+ LeDirectedAdvertisingReportView::Create(event));
+ break;
+ case hci::SubeventCode::EXTENDED_ADVERTISING_REPORT:
+ handle_advertising_report<LeExtendedAdvertisingReportView, LeExtendedAdvertisingReport, ExtendedLeReport>(
+ LeExtendedAdvertisingReportView::Create(event));
+ break;
+ case hci::SubeventCode::SCAN_TIMEOUT:
+ if (registered_callback_ != nullptr) {
+ registered_callback_->handler->Post(
+ common::BindOnce(&LeScanningManagerCallbacks::on_timeout, common::Unretained(registered_callback_)));
+ registered_callback_ = nullptr;
+ }
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unknown advertising subevent %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str());
+ }
+ }
+
+ template <class EventType, class ReportStructType, class ReportType>
+ void handle_advertising_report(EventType event_view) {
+ if (registered_callback_ == nullptr) {
+ LOG_INFO("Dropping advertising event (no registered handler)");
+ return;
+ }
+ if (!event_view.IsValid()) {
+ LOG_INFO("Dropping invalid advertising event");
+ return;
+ }
+ std::vector<ReportStructType> report_vector = event_view.GetAdvertisingReports();
+ if (report_vector.empty()) {
+ LOG_INFO("Zero results in advertising event");
+ return;
+ }
+ std::vector<std::shared_ptr<LeReport>> param;
+ param.reserve(report_vector.size());
+ for (const ReportStructType& report : report_vector) {
+ param.push_back(std::shared_ptr<LeReport>(static_cast<LeReport*>(new ReportType(report))));
+ }
+ registered_callback_->handler->Post(common::BindOnce(&LeScanningManagerCallbacks::on_advertisements,
+ common::Unretained(registered_callback_), param));
+ }
+
+ void configure_scan() {
+ switch (api_type_) {
+ case ScanApiType::LE_5_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetExtendedScanParametersBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_,
+ own_address_type_, filter_policy_),
+ common::BindOnce(impl::check_status), module_handler_);
+ break;
+ case ScanApiType::ANDROID_HCI:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeExtendedScanParamsBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_, own_address_type_,
+ filter_policy_),
+ common::BindOnce(impl::check_status), module_handler_);
+
+ break;
+ case ScanApiType::LE_4_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetScanParametersBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_, own_address_type_,
+ filter_policy_),
+ common::BindOnce(impl::check_status), module_handler_);
+ break;
+ }
+ }
+
+ void start_scan(LeScanningManagerCallbacks* le_scanning_manager_callbacks) {
+ registered_callback_ = le_scanning_manager_callbacks;
+ switch (api_type_) {
+ case ScanApiType::LE_5_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetExtendedScanEnableBuilder::Create(Enable::ENABLED,
+ FilterDuplicates::DISABLED /* filter duplicates */, 0, 0),
+ common::BindOnce(impl::check_status), module_handler_);
+ break;
+ case ScanApiType::ANDROID_HCI:
+ case ScanApiType::LE_4_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetScanEnableBuilder::Create(Enable::ENABLED, Enable::DISABLED /* filter duplicates */),
+ common::BindOnce(impl::check_status), module_handler_);
+ break;
+ }
+ }
+
+ void stop_scan(common::Callback<void()> on_stopped) {
+ if (registered_callback_ == nullptr) {
+ return;
+ }
+ registered_callback_->handler->Post(std::move(on_stopped));
+ switch (api_type_) {
+ case ScanApiType::LE_5_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetExtendedScanEnableBuilder::Create(Enable::DISABLED,
+ FilterDuplicates::DISABLED /* filter duplicates */, 0, 0),
+ common::BindOnce(impl::check_status), module_handler_);
+ registered_callback_->handler = nullptr;
+ break;
+ case ScanApiType::ANDROID_HCI:
+ case ScanApiType::LE_4_0:
+ le_scanning_interface_->EnqueueCommand(
+ hci::LeSetScanEnableBuilder::Create(Enable::DISABLED, Enable::DISABLED /* filter duplicates */),
+ common::BindOnce(impl::check_status), module_handler_);
+ registered_callback_->handler = nullptr;
+ break;
+ }
+ }
+
+ ScanApiType api_type_;
+
+ LeScanningManagerCallbacks* registered_callback_;
+ Module* module_;
+ os::Handler* module_handler_;
+ hci::HciLayer* hci_layer_;
+ hci::Controller* controller_;
+ hci::LeScanningInterface* le_scanning_interface_;
+
+ uint32_t interval_ms_{1000};
+ uint16_t window_ms_{1000};
+ AddressType own_address_type_{AddressType::PUBLIC_DEVICE_ADDRESS};
+ LeSetScanningFilterPolicy filter_policy_{LeSetScanningFilterPolicy::ACCEPT_ALL};
+
+ static void check_status(CommandCompleteView view) {
+ switch (view.GetCommandOpCode()) {
+ case (OpCode::LE_SET_SCAN_ENABLE): {
+ auto status_view = LeSetScanEnableCompleteView::Create(view);
+ ASSERT(status_view.IsValid());
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+ } break;
+ case (OpCode::LE_SET_EXTENDED_SCAN_ENABLE): {
+ auto status_view = LeSetExtendedScanEnableCompleteView::Create(view);
+ ASSERT(status_view.IsValid());
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+ } break;
+ case (OpCode::LE_SET_SCAN_PARAMETERS): {
+ auto status_view = LeSetScanParametersCompleteView::Create(view);
+ ASSERT(status_view.IsValid());
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+ } break;
+ case (OpCode::LE_EXTENDED_SCAN_PARAMS): {
+ auto status_view = LeExtendedScanParamsCompleteView::Create(view);
+ ASSERT(status_view.IsValid());
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+ } break;
+ case (OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS): {
+ auto status_view = LeSetExtendedScanParametersCompleteView::Create(view);
+ ASSERT(status_view.IsValid());
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
+ } break;
+ default:
+ LOG_ALWAYS_FATAL("Unhandled event %s", OpCodeText(view.GetCommandOpCode()).c_str());
+ }
+ }
+};
+
+LeScanningManager::LeScanningManager() {
+ pimpl_ = std::make_unique<impl>(this);
+}
+
+void LeScanningManager::ListDependencies(ModuleList* list) {
+ list->add<hci::HciLayer>();
+ list->add<hci::Controller>();
+}
+
+void LeScanningManager::Start() {
+ pimpl_->start(GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>());
+}
+
+void LeScanningManager::Stop() {
+ pimpl_.reset();
+}
+
+void LeScanningManager::StartScan(LeScanningManagerCallbacks* callbacks) {
+ GetHandler()->Post(common::Bind(&impl::start_scan, common::Unretained(pimpl_.get()), callbacks));
+}
+
+void LeScanningManager::StopScan(common::Callback<void()> on_stopped) {
+ GetHandler()->Post(common::Bind(&impl::stop_scan, common::Unretained(pimpl_.get()), on_stopped));
+}
+
+} // namespace hci
+} // namespace bluetooth \ No newline at end of file
diff --git a/gd/hci/le_scanning_manager.h b/gd/hci/le_scanning_manager.h
new file mode 100644
index 000000000..1de0f0862
--- /dev/null
+++ b/gd/hci/le_scanning_manager.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <memory>
+
+#include "common/callback.h"
+#include "hci/hci_packets.h"
+#include "hci/le_report.h"
+#include "module.h"
+
+namespace bluetooth {
+namespace hci {
+
+class LeScanningManagerCallbacks {
+ public:
+ virtual ~LeScanningManagerCallbacks() = default;
+ virtual void on_advertisements(std::vector<std::shared_ptr<LeReport>>) = 0;
+ virtual void on_timeout() = 0;
+ os::Handler* handler;
+};
+
+class LeScanningManager : public bluetooth::Module {
+ public:
+ LeScanningManager();
+
+ void StartScan(LeScanningManagerCallbacks* callbacks);
+
+ void StopScan(common::Callback<void()> on_stopped);
+
+ static const ModuleFactory Factory;
+
+ protected:
+ void ListDependencies(ModuleList* list) override;
+
+ void Start() override;
+
+ void Stop() override;
+
+ private:
+ struct impl;
+ std::unique_ptr<impl> pimpl_;
+ DISALLOW_COPY_AND_ASSIGN(LeScanningManager);
+};
+
+} // namespace hci
+} // namespace bluetooth \ No newline at end of file
diff --git a/gd/hci/le_scanning_manager_test.cc b/gd/hci/le_scanning_manager_test.cc
new file mode 100644
index 000000000..e5e461e9b
--- /dev/null
+++ b/gd/hci/le_scanning_manager_test.cc
@@ -0,0 +1,336 @@
+/*
+ * 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 "hci/le_scanning_manager.h"
+
+#include <algorithm>
+#include <chrono>
+#include <future>
+#include <map>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "common/bind.h"
+#include "hci/address.h"
+#include "hci/controller.h"
+#include "hci/hci_layer.h"
+#include "os/thread.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace hci {
+namespace {
+
+using packet::kLittleEndian;
+using packet::PacketView;
+using packet::RawBuilder;
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ BitInserter i(*bytes);
+ bytes->reserve(packet->size());
+ packet->Serialize(i);
+ return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+class TestController : public Controller {
+ public:
+ bool IsSupported(OpCode op_code) const override {
+ return supported_opcodes_.count(op_code) == 1;
+ }
+
+ void AddSupported(OpCode op_code) {
+ supported_opcodes_.insert(op_code);
+ }
+
+ protected:
+ void Start() override {}
+ void Stop() override {}
+ void ListDependencies(ModuleList* list) override {}
+
+ private:
+ std::set<OpCode> supported_opcodes_{};
+};
+
+class TestHciLayer : public HciLayer {
+ public:
+ TestHciLayer() {
+ RegisterEventHandler(EventCode::COMMAND_COMPLETE,
+ base::Bind(&TestHciLayer::CommandCompleteCallback, common::Unretained(this)), nullptr);
+ RegisterEventHandler(EventCode::COMMAND_STATUS,
+ base::Bind(&TestHciLayer::CommandStatusCallback, common::Unretained(this)), nullptr);
+ }
+
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+ common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) override {
+ command_queue_.push(std::move(command));
+ command_status_callbacks.push_front(std::move(on_status));
+ if (command_promise_ != nullptr) {
+ command_promise_->set_value();
+ command_promise_.reset();
+ }
+ }
+
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+ common::OnceCallback<void(CommandCompleteView)> on_complete, os::Handler* handler) override {
+ command_queue_.push(std::move(command));
+ command_complete_callbacks.push_front(std::move(on_complete));
+ if (command_promise_ != nullptr) {
+ command_promise_->set_value();
+ command_promise_.reset();
+ }
+ }
+
+ std::future<void> GetCommandFuture() {
+ ASSERT_LOG(command_promise_ == nullptr, "Promises promises ... Only one at a time");
+ command_promise_ = std::make_unique<std::promise<void>>();
+ return command_promise_->get_future();
+ }
+
+ std::unique_ptr<CommandPacketBuilder> GetLastCommand() {
+ ASSERT(!command_queue_.empty());
+ auto last = std::move(command_queue_.front());
+ command_queue_.pop();
+ return last;
+ }
+
+ ConnectionManagementCommandView GetCommandPacket(OpCode op_code) {
+ auto packet_view = GetPacketView(GetLastCommand());
+ CommandPacketView command_packet_view = CommandPacketView::Create(packet_view);
+ ConnectionManagementCommandView command = ConnectionManagementCommandView::Create(command_packet_view);
+ ASSERT(command.IsValid());
+ EXPECT_EQ(command.GetOpCode(), op_code);
+
+ return command;
+ }
+
+ void RegisterEventHandler(EventCode event_code, common::Callback<void(EventPacketView)> event_handler,
+ os::Handler* handler) override {
+ registered_events_[event_code] = event_handler;
+ }
+
+ void RegisterLeEventHandler(SubeventCode subevent_code, common::Callback<void(LeMetaEventView)> event_handler,
+ os::Handler* handler) override {
+ registered_le_events_[subevent_code] = event_handler;
+ }
+
+ void IncomingEvent(std::unique_ptr<EventPacketBuilder> event_builder) {
+ auto packet = GetPacketView(std::move(event_builder));
+ EventPacketView event = EventPacketView::Create(packet);
+ ASSERT_TRUE(event.IsValid());
+ EventCode event_code = event.GetEventCode();
+ ASSERT_TRUE(registered_events_.find(event_code) != registered_events_.end()) << EventCodeText(event_code);
+ registered_events_[event_code].Run(event);
+ }
+
+ void IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) {
+ auto packet = GetPacketView(std::move(event_builder));
+ EventPacketView event = EventPacketView::Create(packet);
+ LeMetaEventView meta_event_view = LeMetaEventView::Create(event);
+ ASSERT_TRUE(meta_event_view.IsValid());
+ SubeventCode subevent_code = meta_event_view.GetSubeventCode();
+ ASSERT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end())
+ << SubeventCodeText(subevent_code);
+ registered_le_events_[subevent_code].Run(meta_event_view);
+ }
+
+ void CommandCompleteCallback(EventPacketView event) {
+ CommandCompleteView complete_view = CommandCompleteView::Create(event);
+ ASSERT(complete_view.IsValid());
+ std::move(command_complete_callbacks.front()).Run(complete_view);
+ command_complete_callbacks.pop_front();
+ }
+
+ void CommandStatusCallback(EventPacketView event) {
+ CommandStatusView status_view = CommandStatusView::Create(event);
+ ASSERT(status_view.IsValid());
+ std::move(command_status_callbacks.front()).Run(status_view);
+ command_status_callbacks.pop_front();
+ }
+
+ void ListDependencies(ModuleList* list) override {}
+ void Start() override {}
+ void Stop() override {}
+
+ private:
+ std::map<EventCode, common::Callback<void(EventPacketView)>> registered_events_;
+ std::map<SubeventCode, common::Callback<void(LeMetaEventView)>> registered_le_events_;
+ std::list<base::OnceCallback<void(CommandCompleteView)>> command_complete_callbacks;
+ std::list<base::OnceCallback<void(CommandStatusView)>> command_status_callbacks;
+
+ std::queue<std::unique_ptr<CommandPacketBuilder>> command_queue_;
+ mutable std::mutex mutex_;
+ std::unique_ptr<std::promise<void>> command_promise_{};
+};
+
+class LeScanningManagerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ test_hci_layer_ = new TestHciLayer; // Ownership is transferred to registry
+ test_controller_ = new TestController;
+ test_controller_->AddSupported(param_opcode_);
+ fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_);
+ fake_registry_.InjectTestModule(&Controller::Factory, test_controller_);
+ client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory);
+ ASSERT_NE(client_handler_, nullptr);
+ mock_callbacks_.handler = client_handler_;
+ std::future<void> config_future = test_hci_layer_->GetCommandFuture();
+ fake_registry_.Start<LeScanningManager>(&thread_);
+ le_scanning_manager =
+ static_cast<LeScanningManager*>(fake_registry_.GetModuleUnderTest(&LeScanningManager::Factory));
+ config_future.wait_for(std::chrono::duration(std::chrono::milliseconds(1000)));
+ HandleConfiguration();
+ }
+
+ void TearDown() override {
+ fake_registry_.SynchronizeModuleHandler(&LeScanningManager::Factory, std::chrono::milliseconds(20));
+ fake_registry_.StopAll();
+ }
+
+ virtual void HandleConfiguration() {
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_SET_SCAN_PARAMETERS);
+ test_hci_layer_->IncomingEvent(LeSetScanParametersCompleteBuilder::Create(1, ErrorCode::SUCCESS));
+ }
+
+ TestModuleRegistry fake_registry_;
+ TestHciLayer* test_hci_layer_ = nullptr;
+ TestController* test_controller_ = nullptr;
+ os::Thread& thread_ = fake_registry_.GetTestThread();
+ LeScanningManager* le_scanning_manager = nullptr;
+ os::Handler* client_handler_ = nullptr;
+
+ class MockLeScanningManagerCallbacks : public LeScanningManagerCallbacks {
+ public:
+ MOCK_METHOD(void, on_advertisements, (std::vector<std::shared_ptr<LeReport>>), (override));
+ MOCK_METHOD(void, on_timeout, (), (override));
+ } mock_callbacks_;
+
+ OpCode param_opcode_{OpCode::LE_SET_ADVERTISING_PARAMETERS};
+};
+
+class LeAndroidHciScanningManagerTest : public LeScanningManagerTest {
+ protected:
+ void SetUp() override {
+ param_opcode_ = OpCode::LE_EXTENDED_SCAN_PARAMS;
+ LeScanningManagerTest::SetUp();
+ }
+
+ void HandleConfiguration() override {
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_EXTENDED_SCAN_PARAMS);
+ test_hci_layer_->IncomingEvent(LeExtendedScanParamsCompleteBuilder::Create(1, ErrorCode::SUCCESS));
+ }
+};
+
+class LeExtendedScanningManagerTest : public LeScanningManagerTest {
+ protected:
+ void SetUp() override {
+ param_opcode_ = OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS;
+ LeScanningManagerTest::SetUp();
+ }
+
+ void HandleConfiguration() override {
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS);
+ test_hci_layer_->IncomingEvent(LeSetExtendedScanParametersCompleteBuilder::Create(1, ErrorCode::SUCCESS));
+ }
+};
+
+TEST_F(LeScanningManagerTest, startup_teardown) {}
+
+TEST_F(LeScanningManagerTest, start_scan_test) {
+ auto next_command_future = test_hci_layer_->GetCommandFuture();
+ le_scanning_manager->StartScan(&mock_callbacks_);
+
+ next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ test_hci_layer_->IncomingEvent(LeSetScanEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
+
+ LeAdvertisingReport report{};
+ report.event_type_ = AdvertisingEventType::ADV_IND;
+ report.address_type_ = AddressType::PUBLIC_DEVICE_ADDRESS;
+ Address::FromString("12:34:56:78:9a:bc", report.address_);
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ report.advertising_data_ = gap_data;
+
+ EXPECT_CALL(mock_callbacks_, on_advertisements);
+
+ test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report}));
+}
+
+TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) {
+ auto next_command_future = test_hci_layer_->GetCommandFuture();
+ le_scanning_manager->StartScan(&mock_callbacks_);
+
+ next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ test_hci_layer_->IncomingEvent(LeSetScanEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
+
+ LeAdvertisingReport report{};
+ report.event_type_ = AdvertisingEventType::ADV_IND;
+ report.address_type_ = AddressType::PUBLIC_DEVICE_ADDRESS;
+ Address::FromString("12:34:56:78:9a:bc", report.address_);
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ report.advertising_data_ = gap_data;
+
+ EXPECT_CALL(mock_callbacks_, on_advertisements);
+
+ test_hci_layer_->IncomingLeMetaEvent(LeAdvertisingReportBuilder::Create({report}));
+}
+
+TEST_F(LeExtendedScanningManagerTest, start_scan_test) {
+ auto next_command_future = test_hci_layer_->GetCommandFuture();
+ le_scanning_manager->StartScan(&mock_callbacks_);
+
+ next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_SET_EXTENDED_SCAN_ENABLE);
+
+ test_hci_layer_->IncomingEvent(LeSetScanEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
+
+ LeExtendedAdvertisingReport report{};
+ report.connectable_ = 1;
+ report.scannable_ = 1;
+ report.address_type_ = DirectAdvertisingAddressType::PUBLIC_DEVICE_ADDRESS;
+ Address::FromString("12:34:56:78:9a:bc", report.address_);
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ report.advertising_data_ = gap_data;
+
+ EXPECT_CALL(mock_callbacks_, on_advertisements);
+
+ test_hci_layer_->IncomingLeMetaEvent(LeExtendedAdvertisingReportBuilder::Create({report}));
+}
+
+} // namespace
+} // namespace hci
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/cert/simple_l2cap_test.py b/gd/l2cap/classic/cert/simple_l2cap_test.py
index 48065c4da..d8a52cd7c 100644
--- a/gd/l2cap/classic/cert/simple_l2cap_test.py
+++ b/gd/l2cap/classic/cert/simple_l2cap_test.py
@@ -29,6 +29,8 @@ from l2cap.classic.cert import api_pb2 as l2cap_cert_pb2
import time
+ASYNC_OP_TIME_SECONDS = 1 # TODO: Use events to synchronize events instead
+
class SimpleL2capTest(GdBaseTestClass):
def setup_test(self):
self.device_under_test = self.gd_devices[0]
@@ -85,14 +87,14 @@ class SimpleL2capTest(GdBaseTestClass):
dut_connection_stream.unsubscribe()
self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101, psm=1))
- time.sleep(1)
-
+ time.sleep(ASYNC_OP_TIME_SECONDS)
open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest())
cid = open_channels.dcid[0]
+ self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(scid=cid))
+ time.sleep(ASYNC_OP_TIME_SECONDS)
dut_packet_stream.subscribe()
cert_packet_stream.subscribe()
- self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(scid=cid))
self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=2, payload=b"abc"))
dut_packet_stream.assert_event_occurs(
@@ -114,7 +116,7 @@ class SimpleL2capTest(GdBaseTestClass):
)
self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest(dcid=0x40, scid=101))
- time.sleep(1)
+ time.sleep(ASYNC_OP_TIME_SECONDS)
dut_packet_stream.unsubscribe()
cert_packet_stream.unsubscribe()
@@ -127,10 +129,37 @@ class SimpleL2capTest(GdBaseTestClass):
lambda device: device.remote == self.dut_address
)
cert_connection_stream.unsubscribe()
- time.sleep(1)
+ time.sleep(ASYNC_OP_TIME_SECONDS)
open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest())
assert len(open_channels.dcid) == 2
+ def test_accept_disconnect(self):
+ """
+ L2CAP/COS/CED/BV-07-C
+ """
+ self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01))
+ cert_connection_stream = self.cert_device.l2cap.connection_complete_stream
+ cert_connection_stream.subscribe()
+ self.device_under_test.l2cap.Connect(self.cert_address)
+ cert_connection_stream.assert_event_occurs(
+ lambda device: device.remote == self.dut_address
+ )
+ cert_connection_stream.unsubscribe()
+ time.sleep(ASYNC_OP_TIME_SECONDS)
+ cert_packet_stream = self.cert_device.l2cap.packet_stream
+ cert_packet_stream.subscribe()
+ open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest())
+ cid = open_channels.dcid[0]
+ disconnection_request_packet = b"\x06\x01\x04\x00\x40\x00\x40\x01"
+ disconnection_response_packet = b"\x07\x01\x04\x00\x40\x00\x40\x01"
+ #TODO(b/143374372): Instead of hardcoding this, use packet builder
+ self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=1, payload=disconnection_request_packet))
+ cert_packet_stream.assert_event_occurs(
+ lambda packet: disconnection_response_packet in packet.payload
+ )
+ cert_packet_stream.unsubscribe()
+ time.sleep(ASYNC_OP_TIME_SECONDS) # TODO(b/144186649): Remove this line
+
def test_basic_operation_request_connection(self):
"""
L2CAP/COS/CED/BV-01-C [Request Connection]
@@ -167,4 +196,28 @@ class SimpleL2capTest(GdBaseTestClass):
lambda packet: echo_response_packet in packet.payload
)
cert_packet_stream.unsubscribe()
+ time.sleep(ASYNC_OP_TIME_SECONDS) # TODO(b/144186649): Remove this line
+
+ def test_reject_unknown_command(self):
+ """
+ L2CAP/COS/CED/BI-01-C
+ """
+ cert_connection_stream = self.cert_device.l2cap.connection_complete_stream
+ cert_connection_stream.subscribe()
+ self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
+ self.device_under_test.l2cap.Connect(self.cert_address)
+ cert_connection_stream.assert_event_occurs(
+ lambda device: device.remote == self.dut_address
+ )
+ cert_connection_stream.unsubscribe()
+ cert_packet_stream = self.cert_device.l2cap.packet_stream
+ cert_packet_stream.subscribe()
+ invalid_command_packet = b"\xff\x01\x00\x00"
+ self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=1, payload=invalid_command_packet))
+ command_reject_packet = b"\x01\x01\x02\x00\x00\x00"
+ cert_packet_stream.assert_event_occurs(
+ lambda packet: command_reject_packet in packet.payload
+ )
+ cert_packet_stream.unsubscribe()
+ time.sleep(ASYNC_OP_TIME_SECONDS) # TODO(b/144186649): Remove this line
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.cc b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
index 47bfd5e93..d81096d5a 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.cc
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
@@ -81,6 +81,14 @@ std::string DynamicChannelImpl::ToString() {
return ss.str();
}
+void DynamicChannelImpl::SetOutgoingConfigurationStatus(ConfigurationStatus status) {
+ outgoing_configuration_status_ = status;
+}
+
+void DynamicChannelImpl::SetIncomingConfigurationStatus(ConfigurationStatus status) {
+ incoming_configuration_status_ = status;
+}
+
} // namespace internal
} // namespace classic
} // namespace l2cap
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.h b/gd/l2cap/classic/internal/dynamic_channel_impl.h
index 8a6270a59..1f293eb33 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.h
@@ -65,6 +65,19 @@ class DynamicChannelImpl {
return psm_;
}
+ enum class ConfigurationStatus { NOT_CONFIGURED, CONFIGURED };
+
+ virtual void SetOutgoingConfigurationStatus(ConfigurationStatus status);
+ virtual void SetIncomingConfigurationStatus(ConfigurationStatus status);
+
+ virtual ConfigurationStatus GetOutgoingConfigurationStatus() const {
+ return outgoing_configuration_status_;
+ }
+
+ virtual ConfigurationStatus GetIncomingConfigurationStatus() const {
+ return incoming_configuration_status_;
+ }
+
private:
const Psm psm_;
const Cid cid_;
@@ -83,6 +96,8 @@ class DynamicChannelImpl {
static constexpr size_t kChannelQueueSize = 10;
common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> channel_queue_{
kChannelQueueSize};
+ ConfigurationStatus outgoing_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
+ ConfigurationStatus incoming_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
DISALLOW_COPY_AND_ASSIGN(DynamicChannelImpl);
};
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index 358062bca..d59d72205 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -58,7 +58,7 @@ void Link::Disconnect() {
std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
- scheduler_->AttachChannel(cid, channel->GetQueueDownEnd());
+ scheduler_->AttachChannel(cid, channel->GetQueueDownEnd(), cid);
return channel;
}
@@ -86,7 +86,7 @@ std::shared_ptr<DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, Cid re
SecurityPolicy security_policy) {
auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
if (channel != nullptr) {
- scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd());
+ scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
}
return channel;
}
@@ -95,7 +95,7 @@ std::shared_ptr<DynamicChannelImpl> Link::AllocateReservedDynamicChannel(Cid res
SecurityPolicy security_policy) {
auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
if (channel != nullptr) {
- scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd());
+ scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
}
return channel;
}
diff --git a/gd/l2cap/classic/internal/signalling_manager.cc b/gd/l2cap/classic/internal/signalling_manager.cc
index 8475bcc21..47792b08f 100644
--- a/gd/l2cap/classic/internal/signalling_manager.cc
+++ b/gd/l2cap/classic/internal/signalling_manager.cc
@@ -147,9 +147,7 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm,
}
send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS,
ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
- std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_);
SendConfigurationRequest(remote_cid, {});
- dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(channel));
}
void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
@@ -180,10 +178,8 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remo
handle_send_next_command();
return;
}
- std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_);
- dynamic_service_manager_->GetService(pending_psm)->NotifyChannelCreation(std::move(channel));
- SendConfigurationRequest(remote_cid, {});
alarm_.Cancel();
+ SendConfigurationRequest(remote_cid, {});
handle_send_next_command();
}
@@ -194,10 +190,15 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
LOG_WARN("Configuration request for an unknown channel");
return;
}
- auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), cid, is_continuation,
+ auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
ConfigurationResponseResult::SUCCESS, {});
enqueue_buffer_->Enqueue(std::move(response), handler_);
handle_send_next_command();
+ channel->SetIncomingConfigurationStatus(DynamicChannelImpl::ConfigurationStatus::CONFIGURED);
+ if (channel->GetOutgoingConfigurationStatus() == DynamicChannelImpl::ConfigurationStatus::CONFIGURED) {
+ std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
+ dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
+ }
}
void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
@@ -211,14 +212,18 @@ void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid c
auto last_sent_command = std::move(pending_commands_.front());
pending_commands_.pop();
- auto channel = channel_allocator_->FindChannelByRemoteCid(cid);
+ auto channel = channel_allocator_->FindChannelByCid(cid);
if (channel == nullptr) {
LOG_WARN("Configuration request for an unknown channel");
handle_send_next_command();
return;
}
- // TODO(cmanton) verify configuration parameters are satisfied
- // TODO(cmanton) Indicate channel is open if config params are agreed upon
+ channel->SetOutgoingConfigurationStatus(DynamicChannelImpl::ConfigurationStatus::CONFIGURED);
+ if (channel->GetIncomingConfigurationStatus() == DynamicChannelImpl::ConfigurationStatus::CONFIGURED) {
+ std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
+ dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
+ }
+ alarm_.Cancel();
handle_send_next_command();
}
@@ -229,20 +234,21 @@ void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid ci
LOG_WARN("Disconnect request for an unknown channel");
return;
}
- auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), remote_cid, cid);
+ auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
enqueue_buffer_->Enqueue(std::move(builder), handler_);
channel->OnClosed(hci::ErrorCode::SUCCESS);
link_->FreeDynamicChannel(cid);
handle_send_next_command();
}
-void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid) {
+void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
if (pending_commands_.empty()) {
LOG_WARN("Unexpected response: no pending request");
return;
}
auto last_sent_command = std::move(pending_commands_.front());
pending_commands_.pop();
+ alarm_.Cancel();
if (last_sent_command.signal_id_ != signal_id ||
last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
@@ -282,6 +288,7 @@ void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketVi
return;
}
LOG_INFO("Echo response received");
+ alarm_.Cancel();
handle_send_next_command();
}
@@ -322,6 +329,7 @@ void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const I
return;
}
// TODO (hsz): Store the information response
+ alarm_.Cancel();
handle_send_next_command();
}
@@ -433,6 +441,8 @@ void ClassicSignallingManager::on_incoming_packet() {
}
default:
LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
+ auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
+ enqueue_buffer_->Enqueue(std::move(builder), handler_);
return;
}
}
diff --git a/gd/l2cap/internal/scheduler.h b/gd/l2cap/internal/scheduler.h
index 7fd3790ee..32d00cfc9 100644
--- a/gd/l2cap/internal/scheduler.h
+++ b/gd/l2cap/internal/scheduler.h
@@ -48,8 +48,9 @@ class Scheduler {
*
* @param cid The channel to attach to the scheduler.
* @param channel_down_end The ChannelQueueDownEnd associated with the channel to attach to the scheduler.
+ * @param remote_cid The destination endpoint of the packet.
*/
- virtual void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end) {}
+ virtual void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) {}
/**
* Detach the channel from the scheduler.
diff --git a/gd/l2cap/internal/scheduler_fifo.cc b/gd/l2cap/internal/scheduler_fifo.cc
index 3e68c28fa..2e2677906 100644
--- a/gd/l2cap/internal/scheduler_fifo.cc
+++ b/gd/l2cap/internal/scheduler_fifo.cc
@@ -30,10 +30,10 @@ Fifo::~Fifo() {
}
}
-void Fifo::AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end) {
+void Fifo::AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) {
ASSERT(channel_queue_end_map_.find(cid) == channel_queue_end_map_.end());
channel_queue_end_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
- std::forward_as_tuple(handler_, channel_down_end, this, cid));
+ std::forward_as_tuple(handler_, channel_down_end, this, cid, remote_cid));
}
void Fifo::DetachChannel(Cid cid) {
@@ -55,7 +55,8 @@ std::unique_ptr<Fifo::UpperDequeue> Fifo::link_queue_enqueue_callback() {
link_queue_up_end_->UnregisterEnqueue();
link_queue_enqueue_registered_ = false;
}
- return BasicFrameBuilder::Create(channel_id, std::move(packet));
+ Cid remote_channel_id = channel_queue_end_map_.find(channel_id)->second.remote_channel_id_;
+ return BasicFrameBuilder::Create(remote_channel_id, std::move(packet));
}
void Fifo::try_register_link_queue_enqueue() {
diff --git a/gd/l2cap/internal/scheduler_fifo.h b/gd/l2cap/internal/scheduler_fifo.h
index f5a2415c6..3f14c7554 100644
--- a/gd/l2cap/internal/scheduler_fifo.h
+++ b/gd/l2cap/internal/scheduler_fifo.h
@@ -42,7 +42,7 @@ class Fifo : public Scheduler {
}
~Fifo() override;
- void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end) override;
+ void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) override;
void DetachChannel(Cid cid) override;
LowerQueueUpEnd* GetLowerQueueUpEnd() const override {
return link_queue_up_end_;
@@ -53,9 +53,10 @@ class Fifo : public Scheduler {
os::Handler* handler_;
struct ChannelQueueEndAndBuffer {
- ChannelQueueEndAndBuffer(os::Handler* handler, UpperQueueDownEnd* queue_end, Fifo* scheduler, Cid channel_id)
+ ChannelQueueEndAndBuffer(os::Handler* handler, UpperQueueDownEnd* queue_end, Fifo* scheduler, Cid channel_id,
+ Cid remote_channel_id)
: handler_(handler), queue_end_(queue_end), enqueue_buffer_(queue_end), scheduler_(scheduler),
- channel_id_(channel_id) {
+ channel_id_(channel_id), remote_channel_id_(remote_channel_id) {
try_register_dequeue();
}
os::Handler* handler_;
@@ -65,6 +66,7 @@ class Fifo : public Scheduler {
std::queue<std::unique_ptr<UpperDequeue>> dequeue_buffer_;
Fifo* scheduler_;
Cid channel_id_;
+ Cid remote_channel_id_;
bool is_dequeue_registered_ = false;
void try_register_dequeue();
diff --git a/gd/l2cap/internal/scheduler_fifo_test.cc b/gd/l2cap/internal/scheduler_fifo_test.cc
index 4ef4f9026..fe4d1498e 100644
--- a/gd/l2cap/internal/scheduler_fifo_test.cc
+++ b/gd/l2cap/internal/scheduler_fifo_test.cc
@@ -78,8 +78,8 @@ class L2capSchedulerFifoTest : public ::testing::Test {
TEST_F(L2capSchedulerFifoTest, receive_packet) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_one_queue_{10};
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_two_queue_{10};
- fifo_->AttachChannel(1, channel_one_queue_.GetDownEnd());
- fifo_->AttachChannel(2, channel_two_queue_.GetDownEnd());
+ fifo_->AttachChannel(1, channel_one_queue_.GetDownEnd(), 1);
+ fifo_->AttachChannel(2, channel_two_queue_.GetDownEnd(), 2);
os::EnqueueBuffer<Scheduler::UpperEnqueue> link_queue_enqueue_buffer{link_queue_.GetDownEnd()};
auto packet_one = CreateSampleL2capPacket(1, {1, 2, 3});
auto packet_two = CreateSampleL2capPacket(2, {4, 5, 6, 7});
@@ -103,8 +103,8 @@ TEST_F(L2capSchedulerFifoTest, receive_packet) {
TEST_F(L2capSchedulerFifoTest, send_packet) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_one_queue_{10};
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_two_queue_{10};
- fifo_->AttachChannel(1, channel_one_queue_.GetDownEnd());
- fifo_->AttachChannel(2, channel_two_queue_.GetDownEnd());
+ fifo_->AttachChannel(1, channel_one_queue_.GetDownEnd(), 1);
+ fifo_->AttachChannel(2, channel_two_queue_.GetDownEnd(), 2);
os::EnqueueBuffer<Scheduler::UpperDequeue> channel_one_enqueue_buffer{channel_one_queue_.GetUpEnd()};
os::EnqueueBuffer<Scheduler::UpperDequeue> channel_two_enqueue_buffer{channel_two_queue_.GetUpEnd()};
auto packet_one = std::make_unique<packet::RawBuilder>();
diff --git a/gd/l2cap/internal/scheduler_mock.h b/gd/l2cap/internal/scheduler_mock.h
index b49e138d4..616d15634 100644
--- a/gd/l2cap/internal/scheduler_mock.h
+++ b/gd/l2cap/internal/scheduler_mock.h
@@ -29,7 +29,7 @@ using hci::testing::MockAclConnection;
class MockScheduler : public Scheduler {
public:
- MOCK_METHOD(void, AttachChannel, (Cid cid, UpperQueueDownEnd* channel_down_end), (override));
+ MOCK_METHOD(void, AttachChannel, (Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid), (override));
MOCK_METHOD(void, DetachChannel, (Cid cid), (override));
MOCK_METHOD(LowerQueueUpEnd*, GetLowerQueueUpEnd, (), (override, const));
};
@@ -37,4 +37,4 @@ class MockScheduler : public Scheduler {
} // namespace testing
} // namespace internal
} // namespace l2cap
-} // namespace bluetooth \ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/l2cap/le/internal/link.h b/gd/l2cap/le/internal/link.h
index cda866be8..85f0280ce 100644
--- a/gd/l2cap/le/internal/link.h
+++ b/gd/l2cap/le/internal/link.h
@@ -69,7 +69,7 @@ class Link {
virtual std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
- scheduler_->AttachChannel(cid, channel->GetQueueDownEnd());
+ scheduler_->AttachChannel(cid, channel->GetQueueDownEnd(), cid);
return channel;
}
diff --git a/gd/security/Android.bp b/gd/security/Android.bp
index ee682b4f8..776246195 100644
--- a/gd/security/Android.bp
+++ b/gd/security/Android.bp
@@ -7,8 +7,11 @@ filegroup {
"pairing_handler_le.cc",
"pairing_handler_le_legacy.cc",
"pairing_handler_le_secure_connections.cc",
+ "security_manager.cc",
+ "internal/security_manager_impl.cc",
"security_module.cc",
- ]
+ ":BluetoothSecurityChannelSources",
+ ],
}
filegroup {
@@ -18,5 +21,6 @@ filegroup {
"pairing_handler_le_unittest.cc",
"test/fake_l2cap_test.cc",
"test/pairing_handler_le_pair_test.cc",
- ]
+ ":BluetoothSecurityChannelTestSources",
+ ],
}
diff --git a/gd/security/channel/Android.bp b/gd/security/channel/Android.bp
new file mode 100644
index 000000000..653902b15
--- /dev/null
+++ b/gd/security/channel/Android.bp
@@ -0,0 +1,13 @@
+filegroup {
+ name: "BluetoothSecurityChannelSources",
+ srcs: [
+ "security_manager_channel.cc",
+ ]
+}
+
+filegroup {
+ name: "BluetoothSecurityChannelTestSources",
+ srcs: [
+ "security_manager_channel_unittest.cc",
+ ]
+}
diff --git a/gd/security/channel/security_manager_channel.cc b/gd/security/channel/security_manager_channel.cc
new file mode 100644
index 000000000..419386d00
--- /dev/null
+++ b/gd/security/channel/security_manager_channel.cc
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * 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 "security_manager_channel.h"
+
+#include "security/smp_packets.h"
+
+using namespace bluetooth::hci;
+using namespace bluetooth::packet;
+using namespace bluetooth::security::channel;
+
+void SecurityManagerChannel::SendCommand(std::shared_ptr<hci::Device> device,
+ std::unique_ptr<SecurityCommandBuilder> command) {
+ hci_security_interface_->EnqueueCommand(
+ std::move(command), common::BindOnce(&SecurityManagerChannel::OnCommandComplete, common::Unretained(this)),
+ handler_);
+}
+
+void SecurityManagerChannel::OnCommandComplete(CommandCompleteView packet) {
+ ASSERT_LOG(packet.IsValid(), "Received invalid packet: %hx", packet.GetCommandOpCode());
+ // TODO(optedoblivion): Verify HCI commands
+}
+
+void SecurityManagerChannel::OnHciEventReceived(EventPacketView packet) {
+ ASSERT_LOG(listener_ != nullptr, "No listener set!");
+ std::shared_ptr<Device> device = nullptr;
+ auto event = EventPacketView::Create(std::move(packet));
+ ASSERT_LOG(event.IsValid(), "Received invalid packet: %hhx", event.GetEventCode());
+ const hci::EventCode code = event.GetEventCode();
+ switch (code) {
+ case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
+ listener_->OnChangeConnectionLinkKeyComplete(device,
+ hci::ChangeConnectionLinkKeyCompleteView::Create(std::move(event)));
+ break;
+ case hci::EventCode::MASTER_LINK_KEY_COMPLETE:
+ listener_->OnMasterLinkKeyComplete(device, hci::MasterLinkKeyCompleteView::Create(std::move(event)));
+ break;
+ case hci::EventCode::PIN_CODE_REQUEST:
+ listener_->OnPinCodeRequest(device, hci::PinCodeRequestView::Create(std::move(event)));
+ break;
+ case hci::EventCode::LINK_KEY_REQUEST:
+ listener_->OnLinkKeyRequest(device, hci::LinkKeyRequestView::Create(std::move(event)));
+ break;
+ case hci::EventCode::LINK_KEY_NOTIFICATION:
+ listener_->OnLinkKeyNotification(device, hci::LinkKeyNotificationView::Create(std::move(event)));
+ break;
+ case hci::EventCode::IO_CAPABILITY_REQUEST:
+ listener_->OnIoCapabilityRequest(device, hci::IoCapabilityRequestView::Create(std::move(event)));
+ break;
+ case hci::EventCode::IO_CAPABILITY_RESPONSE:
+ listener_->OnIoCapabilityResponse(device, IoCapabilityResponseView::Create(std::move(event)));
+ break;
+ case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
+ listener_->OnSimplePairingComplete(device, SimplePairingCompleteView::Create(std::move(event)));
+ break;
+ case hci::EventCode::RETURN_LINK_KEYS:
+ listener_->OnReturnLinkKeys(device, hci::ReturnLinkKeysView::Create(std::move(event)));
+ break;
+ case hci::EventCode::ENCRYPTION_CHANGE:
+ listener_->OnEncryptionChange(device, hci::EncryptionChangeView::Create(std::move(event)));
+ break;
+ case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
+ listener_->OnEncryptionKeyRefreshComplete(device,
+ hci::EncryptionKeyRefreshCompleteView::Create(std::move(event)));
+ break;
+ case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
+ listener_->OnRemoteOobDataRequest(device, hci::RemoteOobDataRequestView::Create(std::move(event)));
+ break;
+ case hci::EventCode::USER_PASSKEY_NOTIFICATION:
+ // listener_->OnUserPasskeyNotification(device, <packet>);
+ break;
+ case hci::EventCode::KEYPRESS_NOTIFICATION:
+ // listener_->OnSendKeypressNotification(device, <packet>);
+ break;
+ default:
+ ASSERT_LOG(false, "Invalid packet received: %hhx", code);
+ break;
+ }
+}
diff --git a/gd/security/channel/security_manager_channel.h b/gd/security/channel/security_manager_channel.h
new file mode 100644
index 000000000..6a2b624bb
--- /dev/null
+++ b/gd/security/channel/security_manager_channel.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "hci/classic_device.h"
+#include "hci/hci_layer.h"
+#include "hci/security_interface.h"
+#include "security/smp_packets.h"
+
+namespace bluetooth {
+namespace security {
+namespace channel {
+
+using hci::CommandCompleteView;
+using hci::EventPacketView;
+using hci::SecurityCommandBuilder;
+using hci::SecurityCommandView;
+
+/**
+ * Interface for listening to the channel for SMP commands.
+ */
+class ISecurityManagerChannelListener {
+ public:
+ virtual ~ISecurityManagerChannelListener() = default;
+
+ virtual void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
+ hci::ChangeConnectionLinkKeyCompleteView packet) = 0;
+ virtual void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) = 0;
+ virtual void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) = 0;
+ virtual void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) = 0;
+ virtual void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) = 0;
+ virtual void OnIoCapabilityRequest(std::shared_ptr<hci::Device> device, hci::IoCapabilityRequestView packet) = 0;
+ virtual void OnIoCapabilityResponse(std::shared_ptr<hci::Device> device, hci::IoCapabilityResponseView packet) = 0;
+ virtual void OnSimplePairingComplete(std::shared_ptr<hci::Device> device, hci::SimplePairingCompleteView packet) = 0;
+ virtual void OnReturnLinkKeys(std::shared_ptr<hci::Device> device, hci::ReturnLinkKeysView packet) = 0;
+ virtual void OnEncryptionChange(std::shared_ptr<hci::Device> device, hci::EncryptionChangeView packet) = 0;
+ virtual void OnEncryptionKeyRefreshComplete(std::shared_ptr<hci::Device> device,
+ hci::EncryptionKeyRefreshCompleteView packet) = 0;
+ virtual void OnRemoteOobDataRequest(std::shared_ptr<hci::Device> device, hci::RemoteOobDataRequestView packet) = 0;
+};
+
+/**
+ * Channel for consolidating traffic and making the transport agnostic.
+ */
+class SecurityManagerChannel {
+ public:
+ explicit SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
+ : listener_(nullptr),
+ hci_security_interface_(hci_layer->GetSecurityInterface(
+ common::Bind(&SecurityManagerChannel::OnHciEventReceived, common::Unretained(this)), handler)),
+ handler_(handler) {}
+ ~SecurityManagerChannel() {
+ delete listener_;
+ }
+
+ /**
+ * Send a given SMP command over the SecurityManagerChannel
+ *
+ * @param device target where command will be sent
+ * @param command smp command to send
+ */
+ void SendCommand(std::shared_ptr<hci::Device> device, std::unique_ptr<SecurityCommandBuilder> command);
+
+ /**
+ * Sets the listener to listen for channel events
+ *
+ * @param listener the caller interested in events
+ */
+ void SetChannelListener(ISecurityManagerChannelListener* listener) {
+ listener_ = listener;
+ }
+
+ /**
+ * Called when an incoming HCI event happens
+ *
+ * @param event_packet
+ */
+ void OnHciEventReceived(EventPacketView packet);
+
+ /**
+ * Called when an HCI command is completed
+ *
+ * @param on_complete
+ */
+ void OnCommandComplete(CommandCompleteView packet);
+
+ private:
+ ISecurityManagerChannelListener* listener_;
+ hci::SecurityInterface* hci_security_interface_;
+ os::Handler* handler_;
+};
+
+} // namespace channel
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/security/channel/security_manager_channel_unittest.cc b/gd/security/channel/security_manager_channel_unittest.cc
new file mode 100644
index 000000000..f34625573
--- /dev/null
+++ b/gd/security/channel/security_manager_channel_unittest.cc
@@ -0,0 +1,276 @@
+/******************************************************************************
+ *
+ * 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 "security_manager_channel.h"
+
+#include <gtest/gtest.h>
+
+#include "hci/device.h"
+#include "hci/device_database.h"
+#include "hci/hci_packets.h"
+#include "packet/raw_builder.h"
+#include "security/smp_packets.h"
+#include "security/test/fake_hci_layer.h"
+
+namespace bluetooth {
+namespace security {
+namespace channel {
+namespace {
+
+using bluetooth::security::channel::SecurityManagerChannel;
+using hci::AuthenticationRequirements;
+using hci::CommandCompleteBuilder;
+using hci::Device;
+using hci::DeviceDatabase;
+using hci::IoCapabilityRequestReplyBuilder;
+using hci::IoCapabilityRequestView;
+using hci::OobDataPresent;
+using hci::OpCode;
+using os::Handler;
+using os::Thread;
+using packet::RawBuilder;
+
+static DeviceDatabase kDeviceDatabase;
+
+class TestPayloadBuilder : public PacketBuilder<kLittleEndian> {
+ public:
+ ~TestPayloadBuilder() override = default;
+ size_t size() const override {
+ return 1;
+ }
+ void Serialize(BitInserter& inserter) const override {}
+ static std::unique_ptr<TestPayloadBuilder> Create() {
+ return std::unique_ptr<TestPayloadBuilder>(new TestPayloadBuilder());
+ }
+
+ private:
+ TestPayloadBuilder() : PacketBuilder<kLittleEndian>(){};
+};
+
+class SecurityManagerChannelCallback : public ISecurityManagerChannelListener {
+ public:
+ // HCI
+ bool receivedChangeConnectionLinkKeyComplete = false;
+ bool receivedMasterLinkKeyComplete = false;
+ bool receivedPinCodeRequest = false;
+ bool receivedLinkKeyRequest = false;
+ bool receivedLinkKeyNotification = false;
+ bool receivedIoCapabilityRequest = false;
+ bool receivedIoCapabilityResponse = false;
+ bool receivedSimplePairingComplete = false;
+ bool receivedReturnLinkKeys = false;
+ bool receivedEncryptionChange = false;
+ bool receivedEncryptionKeyRefreshComplete = false;
+ bool receivedRemoteOobDataRequest = false;
+
+ void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
+ hci::ChangeConnectionLinkKeyCompleteView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedChangeConnectionLinkKeyComplete = true;
+ }
+ void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedMasterLinkKeyComplete = true;
+ }
+ void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedPinCodeRequest = true;
+ }
+ void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedLinkKeyRequest = true;
+ }
+ void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedLinkKeyNotification = true;
+ }
+ void OnIoCapabilityRequest(std::shared_ptr<Device> device, hci::IoCapabilityRequestView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedIoCapabilityRequest = true;
+ }
+ void OnIoCapabilityResponse(std::shared_ptr<Device> device, hci::IoCapabilityResponseView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedIoCapabilityResponse = true;
+ }
+ void OnSimplePairingComplete(std::shared_ptr<Device> device, hci::SimplePairingCompleteView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedSimplePairingComplete = true;
+ }
+ void OnReturnLinkKeys(std::shared_ptr<Device> device, hci::ReturnLinkKeysView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedReturnLinkKeys = true;
+ }
+ void OnEncryptionChange(std::shared_ptr<Device> device, hci::EncryptionChangeView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedEncryptionChange = true;
+ }
+ void OnEncryptionKeyRefreshComplete(std::shared_ptr<Device> device, hci::EncryptionKeyRefreshCompleteView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedEncryptionKeyRefreshComplete = true;
+ }
+ void OnRemoteOobDataRequest(std::shared_ptr<Device> device, hci::RemoteOobDataRequestView packet) {
+ EXPECT_TRUE(packet.IsValid());
+ receivedRemoteOobDataRequest = true;
+ }
+};
+
+class SecurityManagerChannelTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ device_ = kDeviceDatabase.CreateClassicDevice(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}));
+ handler_ = new Handler(&thread_);
+ callback_ = new SecurityManagerChannelCallback();
+ hci_layer_ = new FakeHciLayer();
+ fake_registry_.InjectTestModule(&FakeHciLayer::Factory, hci_layer_);
+ fake_registry_.Start<FakeHciLayer>(&thread_);
+ channel_ = new SecurityManagerChannel(handler_, hci_layer_);
+ channel_->SetChannelListener(callback_);
+ }
+
+ void TearDown() override {
+ channel_->SetChannelListener(nullptr);
+ handler_->Clear();
+ fake_registry_.SynchronizeModuleHandler(&FakeHciLayer::Factory, std::chrono::milliseconds(20));
+ fake_registry_.StopAll();
+ delete handler_;
+ delete channel_;
+ delete callback_;
+ }
+
+ TestModuleRegistry fake_registry_;
+ Thread& thread_ = fake_registry_.GetTestThread();
+ Handler* handler_ = nullptr;
+ FakeHciLayer* hci_layer_ = nullptr;
+ SecurityManagerChannel* channel_ = nullptr;
+ SecurityManagerChannelCallback* callback_ = nullptr;
+ std::shared_ptr<Device> device_ = nullptr;
+};
+
+TEST_F(SecurityManagerChannelTest, setup_teardown) {}
+
+TEST_F(SecurityManagerChannelTest, recv_io_cap_request) {
+ hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device_->GetAddress()));
+ EXPECT_TRUE(callback_->receivedIoCapabilityRequest);
+}
+
+TEST_F(SecurityManagerChannelTest, send_io_cap_request_reply) {
+ // Arrange
+ hci::IoCapability io_capability = (hci::IoCapability)0x00;
+ OobDataPresent oob_present = (OobDataPresent)0x00;
+ AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
+ auto packet = hci::IoCapabilityRequestReplyBuilder::Create(device_->GetAddress(), io_capability, oob_present,
+ authentication_requirements);
+
+ // Act
+ channel_->SendCommand(device_, std::move(packet));
+ auto last_command = std::move(hci_layer_->GetLastCommand()->command);
+ auto command_packet = GetPacketView(std::move(last_command));
+ hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
+
+ // Assert
+ EXPECT_TRUE(packet_view.IsValid());
+ EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, packet_view.GetOpCode());
+}
+
+TEST_F(SecurityManagerChannelTest, send_io_cap_request_neg_reply) {
+ // Arrange
+ auto packet =
+ hci::IoCapabilityRequestNegativeReplyBuilder::Create(device_->GetAddress(), hci::ErrorCode::COMMAND_DISALLOWED);
+
+ // Act
+ channel_->SendCommand(device_, std::move(packet));
+ auto last_command = std::move(hci_layer_->GetLastCommand()->command);
+ auto command_packet = GetPacketView(std::move(last_command));
+ hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
+
+ // Assert
+ EXPECT_TRUE(packet_view.IsValid());
+ EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+}
+
+TEST_F(SecurityManagerChannelTest, recv_io_cap_response) {
+ hci::IoCapability io_capability = (hci::IoCapability)0x00;
+ OobDataPresent oob_present = (OobDataPresent)0x00;
+ AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
+ hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create(device_->GetAddress(), io_capability, oob_present,
+ authentication_requirements));
+ EXPECT_TRUE(callback_->receivedIoCapabilityResponse);
+}
+
+TEST_F(SecurityManagerChannelTest, recv_pin_code_request) {
+ hci_layer_->IncomingEvent(hci::PinCodeRequestBuilder::Create(device_->GetAddress()));
+ EXPECT_TRUE(callback_->receivedPinCodeRequest);
+}
+
+TEST_F(SecurityManagerChannelTest, send_pin_code_request_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_pin_code_request_neg_reply) {}
+
+TEST_F(SecurityManagerChannelTest, recv_user_passkey_notification) {}
+
+TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_neg_reply) {}
+
+TEST_F(SecurityManagerChannelTest, recv_remote_oob_data_request) {}
+
+TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_neg_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_read_local_oob_data) {}
+
+TEST_F(SecurityManagerChannelTest, send_read_local_oob_extended_data) {}
+
+TEST_F(SecurityManagerChannelTest, recv_link_key_request) {}
+
+TEST_F(SecurityManagerChannelTest, recv_link_key_notification) {}
+
+TEST_F(SecurityManagerChannelTest, recv_master_link_complete) {}
+
+TEST_F(SecurityManagerChannelTest, recv_change_connection_link_key_complete) {}
+
+TEST_F(SecurityManagerChannelTest, recv_return_link_keys) {}
+
+TEST_F(SecurityManagerChannelTest, send_link_key_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_link_key_neg_reply) {}
+
+TEST_F(SecurityManagerChannelTest, send_read_stored_link_key) {}
+
+TEST_F(SecurityManagerChannelTest, send_write_stored_link_key) {}
+
+TEST_F(SecurityManagerChannelTest, send_delete_stored_link_key) {}
+
+TEST_F(SecurityManagerChannelTest, recv_encryption_change) {}
+
+TEST_F(SecurityManagerChannelTest, send_refresh_encryption_key) {}
+
+TEST_F(SecurityManagerChannelTest, send_read_encryption_key_size) {}
+
+TEST_F(SecurityManagerChannelTest, recv_simple_pairing_complete) {}
+
+TEST_F(SecurityManagerChannelTest, send_read_simple_pairing_mode) {}
+
+TEST_F(SecurityManagerChannelTest, send_write_simple_pairing_mode) {}
+
+TEST_F(SecurityManagerChannelTest, send_keypress_notification) {}
+
+} // namespace
+} // namespace channel
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/security/internal/security_manager_impl.cc b/gd/security/internal/security_manager_impl.cc
new file mode 100644
index 000000000..21d8151b9
--- /dev/null
+++ b/gd/security/internal/security_manager_impl.cc
@@ -0,0 +1,152 @@
+/******************************************************************************
+ *
+ * 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 "security_manager_impl.h"
+
+#include <iostream>
+#include <unordered_map>
+
+#include "os/log.h"
+#include "security/pairing/classic_pairing_handler.h"
+
+using namespace bluetooth::security::internal;
+using bluetooth::hci::Device;
+using bluetooth::hci::DeviceType;
+using bluetooth::security::pairing::PairingHandler;
+
+namespace {
+std::unordered_map<std::shared_ptr<Device>, std::unique_ptr<PairingHandler>> pairing_handler_map_;
+
+void dispatch_new_pairing_handler(std::shared_ptr<bluetooth::security::record::SecurityRecord> record) {
+ auto entry = pairing_handler_map_.find(record->GetDevice());
+ if (entry != pairing_handler_map_.end()) {
+ LOG_WARN("Device already has a pairing handler, and is in the middle of pairing!");
+ return;
+ }
+ std::unique_ptr<PairingHandler> pairing_handler = nullptr;
+ switch (record->GetDevice()->GetDeviceType()) {
+ case DeviceType::CLASSIC:
+ pairing_handler = std::make_unique<bluetooth::security::pairing::ClassicPairingHandler>(record);
+ break;
+ default:
+ ASSERT_LOG(false, "Pairing type %d not implemented!", record->GetDevice()->GetDeviceType());
+ }
+ auto new_entry = std::pair<std::shared_ptr<Device>, std::unique_ptr<PairingHandler>>(record->GetDevice(),
+ std::move(pairing_handler));
+ pairing_handler_map_.insert(std::move(new_entry));
+}
+} // namespace
+
+void SecurityManagerImpl::Init() {
+ // TODO(optedoblivion): Populate security record memory map from disk
+ // security_manager_channel_->SetChannelListener(this);
+}
+
+void SecurityManagerImpl::CreateBond(std::shared_ptr<hci::ClassicDevice> device) {
+ std::string uuid = device->GetUuid();
+ // Security record check
+ // if (device_database_->GetDeviceById(uuid) != nullptr) {
+ // LOG_WARN("Device already exists in the database");
+ // TODO(optedoblivion): Check security record if device is already bonded
+ // if no security record, need to initiate bonding
+ // if security record and not bonded, need to initiate bonding
+ // if security record and is bonded, then do nothing
+ // }
+
+ // device_database_->AddDevice(device);
+ // Create security record
+ // Pass to pairing handler
+ std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(device);
+ dispatch_new_pairing_handler(record);
+ // init the pairing handler
+ // Update bonded flag on security record
+ // Update bonded flag on device to BONDING (pairing handler does this)
+}
+
+void SecurityManagerImpl::CancelBond(std::shared_ptr<hci::ClassicDevice> device) {
+ auto entry = pairing_handler_map_.find(device);
+ if (entry != pairing_handler_map_.end()) {
+ pairing_handler_map_.erase(device);
+ }
+ // Remove from DB
+ // device_database_->RemoveDevice(device);
+ // Remove from map, no longer will the event queue use it
+ // If currently bonding, cancel pairing handler job
+ // else, cancel fails
+}
+
+void SecurityManagerImpl::RemoveBond(std::shared_ptr<hci::ClassicDevice> device) {
+ CancelBond(device);
+ // Update bonded flag on device to UNBONDED
+ // Signal disconnect
+ // Signal unbonding
+ // Remove security record
+ // Signal Remove from database
+}
+
+void SecurityManagerImpl::RegisterCallbackListener(ISecurityManagerListener* listener) {
+ if (listeners_.size() < 1) {
+ listeners_.push_back(listener);
+ } else {
+ bool found = false;
+ for (auto it = listeners_.begin(); it != listeners_.end(); ++it) {
+ found = *it == listener;
+ if (found) break;
+ }
+
+ if (found) {
+ LOG_ERROR("Listener has already been registered!");
+ } else {
+ listeners_.push_back(listener);
+ }
+ }
+}
+
+void SecurityManagerImpl::UnregisterCallbackListener(ISecurityManagerListener* listener) {
+ if (listeners_.size() < 1) {
+ LOG_ERROR("Listener has not been registered!");
+ } else {
+ bool found = false;
+ auto it = listeners_.begin();
+ while (it != listeners_.end()) {
+ found = *it == listener;
+ if (found) break;
+ ++it;
+ }
+ if (found) {
+ listeners_.erase(it);
+ }
+ }
+}
+
+void SecurityManagerImpl::FireDeviceBondedCallbacks(std::shared_ptr<Device> device) {
+ for (auto& iter : listeners_) {
+ iter->handler_->Post(common::Bind(&ISecurityManagerListener::OnDeviceBonded, common::Unretained(iter), device));
+ }
+}
+
+void SecurityManagerImpl::FireBondFailedCallbacks(std::shared_ptr<Device> device) {
+ for (auto& iter : listeners_) {
+ iter->handler_->Post(common::Bind(&ISecurityManagerListener::OnDeviceBondFailed, common::Unretained(iter), device));
+ }
+}
+
+void SecurityManagerImpl::FireUnbondCallbacks(std::shared_ptr<Device> device) {
+ for (auto& iter : listeners_) {
+ iter->handler_->Post(common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, common::Unretained(iter), device));
+ }
+}
diff --git a/gd/security/internal/security_manager_impl.h b/gd/security/internal/security_manager_impl.h
index 183cfae3e..13d66b919 100644
--- a/gd/security/internal/security_manager_impl.h
+++ b/gd/security/internal/security_manager_impl.h
@@ -16,30 +16,139 @@
#pragma once
+#include "hci/classic_device.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "l2cap/le/l2cap_le_module.h"
#include "os/handler.h"
+#include "security/channel/security_manager_channel.h"
namespace bluetooth {
namespace security {
namespace internal {
-class SecurityManagerImpl {
+/**
+ * Interface for listening to the channel for SMP commands.
+ */
+class ISecurityManagerListener {
+ public:
+ ISecurityManagerListener(os::Handler* handler) : handler_(handler) {}
+ virtual ~ISecurityManagerListener() = default;
+
+ /**
+ * Called when a device is successfully bonded.
+ *
+ * @param device pointer to the bonded device
+ */
+ virtual void OnDeviceBonded(std::shared_ptr<bluetooth::hci::Device> device);
+
+ /**
+ * Called when a device is successfully un-bonded.
+ *
+ * @param device pointer to the device that is no longer bonded
+ */
+ virtual void OnDeviceUnbonded(std::shared_ptr<bluetooth::hci::Device> device);
+
+ /**
+ * Called as a result of a failure during the bonding process.
+ *
+ * @param device pointer to the device that is no longer bonded
+ */
+ virtual void OnDeviceBondFailed(std::shared_ptr<bluetooth::hci::Device> device);
+
+ bool operator==(const ISecurityManagerListener& rhs) const {
+ return &*this == &rhs;
+ }
+
+ os::Handler* handler_ = nullptr;
+};
+
+class SecurityManagerImpl /*: public channel::ISecurityManagerChannelListener*/ {
public:
explicit SecurityManagerImpl(os::Handler* security_handler, l2cap::le::L2capLeModule* l2cap_le_module,
- l2cap::classic::L2capClassicModule* l2cap_classic_module)
+ l2cap::classic::L2capClassicModule* l2cap_classic_module,
+ channel::SecurityManagerChannel* security_manager_channel)
: security_handler_(security_handler), l2cap_le_module_(l2cap_le_module),
- l2cap_classic_module_(l2cap_classic_module) {}
+ l2cap_classic_module_(l2cap_classic_module), security_manager_channel_(security_manager_channel) {}
virtual ~SecurityManagerImpl() = default;
- // All APIs must be invoked in L2CAP layer handler
+ // All APIs must be invoked in SM layer handler
+
+ /**
+ * Initialize the security record map from an internal device database.
+ */
+ void Init();
+
+ /**
+ * Checks the device for existing bond, if not bonded, initiates pairing.
+ *
+ * @param device pointer to device we want to bond with
+ * @return true if bonded or pairing started successfully, false if currently pairing
+ */
+ void CreateBond(std::shared_ptr<hci::ClassicDevice> device);
+
+ /* void CreateBond(std::shared_ptr<hci::LeDevice> device); */
+
+ /**
+ * Cancels the pairing process for this device.
+ *
+ * @param device pointer to device with which we want to cancel our bond
+ * @return <code>true</code> if successfully stopped
+ */
+ void CancelBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+
+ /* void CancelBond(std::shared_ptr<hci::LeDevice> device); */
+
+ /**
+ * Disassociates the device and removes the persistent LTK
+ *
+ * @param device pointer to device we want to forget
+ * @return true if removed
+ */
+ void RemoveBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+
+ /* void RemoveBond(std::shared_ptr<hci::LeDevice> device); */
+
+ /**
+ * Register to listen for callback events from SecurityManager
+ *
+ * @param listener ISecurityManagerListener instance to handle callbacks
+ */
+ void RegisterCallbackListener(ISecurityManagerListener* listener);
+
+ /**
+ * Unregister listener for callback events from SecurityManager
+ *
+ * @param listener ISecurityManagerListener instance to unregister
+ */
+ void UnregisterCallbackListener(ISecurityManagerListener* listener);
+
+ protected:
+ std::vector<ISecurityManagerListener*> listeners_;
+ void FireDeviceBondedCallbacks(std::shared_ptr<bluetooth::hci::Device> device);
+ void FireBondFailedCallbacks(std::shared_ptr<bluetooth::hci::Device> device);
+ void FireUnbondCallbacks(std::shared_ptr<bluetooth::hci::Device> device);
- // TODO: put all API methods here
+ // ISecurityManagerChannel
+ void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
+ hci::ChangeConnectionLinkKeyCompleteView packet);
+ void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet);
+ void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet);
+ void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet);
+ void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet);
+ void OnIoCapabilityRequest(std::shared_ptr<hci::Device> device, hci::IoCapabilityRequestView packet);
+ void OnIoCapabilityResponse(std::shared_ptr<hci::Device> device, hci::IoCapabilityResponseView packet);
+ void OnSimplePairingComplete(std::shared_ptr<hci::Device> device, hci::SimplePairingCompleteView packet);
+ void OnReturnLinkKeys(std::shared_ptr<hci::Device> device, hci::ReturnLinkKeysView packet);
+ void OnEncryptionChange(std::shared_ptr<hci::Device> device, hci::EncryptionChangeView packet);
+ void OnEncryptionKeyRefreshComplete(std::shared_ptr<hci::Device> device,
+ hci::EncryptionKeyRefreshCompleteView packet);
+ void OnRemoteOobDataRequest(std::shared_ptr<hci::Device> device, hci::RemoteOobDataRequestView packet);
private:
os::Handler* security_handler_ __attribute__((unused));
l2cap::le::L2capLeModule* l2cap_le_module_ __attribute__((unused));
l2cap::classic::L2capClassicModule* l2cap_classic_module_ __attribute__((unused));
+ channel::SecurityManagerChannel* security_manager_channel_ __attribute__((unused));
};
} // namespace internal
} // namespace security
diff --git a/gd/security/pairing/classic_pairing_handler.h b/gd/security/pairing/classic_pairing_handler.h
new file mode 100644
index 000000000..fc8eed4c7
--- /dev/null
+++ b/gd/security/pairing/classic_pairing_handler.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License") override;
+ * 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.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include "pairing_handler.h"
+
+#include "security/smp_packets.h"
+
+using namespace bluetooth::security::pairing;
+
+namespace bluetooth {
+namespace security {
+namespace pairing {
+
+class ClassicPairingHandler : public PairingHandler {
+ public:
+ explicit ClassicPairingHandler(std::shared_ptr<record::SecurityRecord> record) : PairingHandler(record) {}
+
+ void Init() {
+ // Set auth required
+ // Connect to device
+ }
+};
+
+} // namespace pairing
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/security/pairing/pairing_handler.h b/gd/security/pairing/pairing_handler.h
new file mode 100644
index 000000000..61cad6258
--- /dev/null
+++ b/gd/security/pairing/pairing_handler.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "hci/device.h"
+#include "security/channel/security_manager_channel.h"
+#include "security/record/security_record.h"
+#include "security/smp_packets.h"
+
+namespace bluetooth {
+namespace security {
+namespace pairing {
+
+/**
+ * Base structure for handling pairing events.
+ *
+ * <p>Extend this class in order to implement a new style of pairing.
+ */
+class PairingHandler {
+ public:
+ PairingHandler(std::shared_ptr<record::SecurityRecord> record) : record_(record){};
+ virtual ~PairingHandler() = default;
+
+ std::shared_ptr<record::SecurityRecord> GetRecord() {
+ return record_;
+ }
+
+ private:
+ std::shared_ptr<record::SecurityRecord> record_ __attribute__((unused));
+};
+
+} // namespace pairing
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/security/record/security_record.h b/gd/security/record/security_record.h
new file mode 100644
index 000000000..0c78113ab
--- /dev/null
+++ b/gd/security/record/security_record.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <memory>
+
+#include "hci/device.h"
+
+namespace bluetooth {
+namespace security {
+namespace record {
+
+enum BondState { NOT_BONDED, PAIRING, BONDED };
+
+class SecurityRecord {
+ public:
+ SecurityRecord(std::shared_ptr<hci::Device> device) : device_(device), state_(NOT_BONDED) {}
+
+ /**
+ * Returns true if the device is bonded to another device
+ */
+ bool IsBonded() {
+ return state_ == BONDED;
+ }
+
+ /**
+ * Returns true if a device is currently pairing to another device
+ */
+ bool IsPairing() {
+ return state_ == PAIRING;
+ }
+
+ std::shared_ptr<hci::Device> GetDevice() {
+ return device_;
+ }
+
+ private:
+ const std::shared_ptr<hci::Device> device_;
+ BondState state_;
+};
+
+} // namespace record
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/security/security_manager.cc b/gd/security/security_manager.cc
new file mode 100644
index 000000000..9a7df85ef
--- /dev/null
+++ b/gd/security/security_manager.cc
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * 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 "security_manager.h"
+
+#include "os/log.h"
+
+using namespace bluetooth::security;
+
+void SecurityManager::Init() {
+ security_handler_->Post(
+ common::BindOnce(&internal::SecurityManagerImpl::Init, common::Unretained(security_manager_impl_)));
+}
+
+void SecurityManager::CreateBond(std::shared_ptr<hci::ClassicDevice> device) {
+ security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CreateBond,
+ common::Unretained(security_manager_impl_),
+ std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+}
+
+void SecurityManager::CancelBond(std::shared_ptr<hci::ClassicDevice> device) {
+ security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CancelBond,
+ common::Unretained(security_manager_impl_),
+ std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+}
+
+void SecurityManager::RemoveBond(std::shared_ptr<hci::ClassicDevice> device) {
+ security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::RemoveBond,
+ common::Unretained(security_manager_impl_),
+ std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+}
+
+void SecurityManager::RegisterCallbackListener(internal::ISecurityManagerListener* listener) {
+ security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::RegisterCallbackListener,
+ common::Unretained(security_manager_impl_),
+ std::forward<internal::ISecurityManagerListener*>(listener)));
+}
+
+void SecurityManager::UnregisterCallbackListener(internal::ISecurityManagerListener* listener) {
+ security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::UnregisterCallbackListener,
+ common::Unretained(security_manager_impl_),
+ std::forward<internal::ISecurityManagerListener*>(listener)));
+}
diff --git a/gd/security/security_manager.h b/gd/security/security_manager.h
index 73992c9e4..bc09c0020 100644
--- a/gd/security/security_manager.h
+++ b/gd/security/security_manager.h
@@ -18,25 +18,73 @@
#pragma once
+#include <memory>
+#include <vector>
+
+#include "hci/device.h"
+#include "hci/device_database.h"
#include "security/internal/security_manager_impl.h"
namespace bluetooth {
namespace security {
+/**
+ * Manages the security attributes, pairing, bonding of devices, and the
+ * encryption/decryption of communications.
+ */
class SecurityManager {
public:
- // TODO: put SMP API methods here
-
friend class SecurityModule;
- private:
+ /**
+ * Initialize the security record map from an internal device database.
+ */
+ void Init();
+
+ /**
+ * Checks the device for existing bond, if not bonded, initiates pairing.
+ *
+ * @param device pointer to device we want to bond with
+ */
+ void CreateBond(std::shared_ptr<hci::ClassicDevice> device);
+
+ /**
+ * Cancels the pairing process for this device.
+ *
+ * @param device pointer to device with which we want to cancel our bond
+ */
+ void CancelBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+
+ /**
+ * Disassociates the device and removes the persistent LTK
+ *
+ * @param device pointer to device we want to forget
+ */
+ void RemoveBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+
+ /**
+ * Register to listen for callback events from SecurityManager
+ *
+ * @param listener ISecurityManagerListener instance to handle callbacks
+ */
+ void RegisterCallbackListener(internal::ISecurityManagerListener* listener);
+
+ /**
+ * Unregister listener for callback events from SecurityManager
+ *
+ * @param listener ISecurityManagerListener instance to unregister
+ */
+ void UnregisterCallbackListener(internal::ISecurityManagerListener* listener);
+
+ protected:
SecurityManager(os::Handler* security_handler, internal::SecurityManagerImpl* security_manager_impl)
: security_handler_(security_handler), security_manager_impl_(security_manager_impl) {}
+ private:
os::Handler* security_handler_ = nullptr;
internal::SecurityManagerImpl* security_manager_impl_;
DISALLOW_COPY_AND_ASSIGN(SecurityManager);
};
} // namespace security
-} // namespace bluetooth \ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/security/security_module.cc b/gd/security/security_module.cc
index 0d9b1cae0..e1d01d7ca 100644
--- a/gd/security/security_module.cc
+++ b/gd/security/security_module.cc
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-#define LOG_TAG "smp"
+#define LOG_TAG "security"
#include <memory>
#include "module.h"
#include "os/handler.h"
#include "os/log.h"
-#include "l2cap/classic/l2cap_classic_module.h"
+#include "hci/hci_layer.h"
#include "l2cap/le/l2cap_le_module.h"
+#include "security/channel/security_manager_channel.h"
#include "security/internal/security_manager_impl.h"
#include "security/security_module.h"
@@ -33,23 +34,28 @@ const ModuleFactory SecurityModule::Factory = ModuleFactory([]() { return new Se
struct SecurityModule::impl {
impl(os::Handler* security_handler, l2cap::le::L2capLeModule* l2cap_le_module,
- l2cap::classic::L2capClassicModule* l2cap_classic_module)
+ l2cap::classic::L2capClassicModule* l2cap_classic_module, hci::HciLayer* hci_layer)
: security_handler_(security_handler), l2cap_le_module_(l2cap_le_module),
- l2cap_classic_module_(l2cap_classic_module) {}
+ l2cap_classic_module_(l2cap_classic_module),
+ security_manager_channel_(new channel::SecurityManagerChannel(security_handler_, hci_layer)) {}
+
os::Handler* security_handler_;
l2cap::le::L2capLeModule* l2cap_le_module_;
l2cap::classic::L2capClassicModule* l2cap_classic_module_;
- internal::SecurityManagerImpl security_manager_impl{security_handler_, l2cap_le_module_, l2cap_classic_module_};
+ channel::SecurityManagerChannel* security_manager_channel_;
+ internal::SecurityManagerImpl security_manager_impl{security_handler_, l2cap_le_module_, l2cap_classic_module_,
+ security_manager_channel_};
};
void SecurityModule::ListDependencies(ModuleList* list) {
list->add<l2cap::le::L2capLeModule>();
list->add<l2cap::classic::L2capClassicModule>();
+ list->add<hci::HciLayer>();
}
void SecurityModule::Start() {
pimpl_ = std::make_unique<impl>(GetHandler(), GetDependency<l2cap::le::L2capLeModule>(),
- GetDependency<l2cap::classic::L2capClassicModule>());
+ GetDependency<l2cap::classic::L2capClassicModule>(), GetDependency<hci::HciLayer>());
}
void SecurityModule::Stop() {
diff --git a/gd/security/test/fake_hci_layer.h b/gd/security/test/fake_hci_layer.h
new file mode 100644
index 000000000..310a75c45
--- /dev/null
+++ b/gd/security/test/fake_hci_layer.h
@@ -0,0 +1,115 @@
+/******************************************************************************
+ *
+ * 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 "common/bind.h"
+#include "hci/hci_layer.h"
+
+namespace bluetooth {
+namespace security {
+
+using common::OnceCallback;
+using hci::CommandCompleteView;
+using hci::CommandPacketBuilder;
+using hci::CommandStatusView;
+using hci::EventCode;
+using hci::EventPacketBuilder;
+using hci::EventPacketView;
+using hci::HciLayer;
+using os::Handler;
+
+namespace {
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ BitInserter i(*bytes);
+ bytes->reserve(packet->size());
+ packet->Serialize(i);
+ return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+class CommandQueueEntry {
+ public:
+ CommandQueueEntry(std::unique_ptr<CommandPacketBuilder> command_packet,
+ OnceCallback<void(CommandCompleteView)> on_complete_function, Handler* handler)
+ : command(std::move(command_packet)), waiting_for_status_(false), on_complete(std::move(on_complete_function)),
+ caller_handler(handler) {}
+
+ CommandQueueEntry(std::unique_ptr<CommandPacketBuilder> command_packet,
+ OnceCallback<void(CommandStatusView)> on_status_function, Handler* handler)
+ : command(std::move(command_packet)), waiting_for_status_(true), on_status(std::move(on_status_function)),
+ caller_handler(handler) {}
+
+ std::unique_ptr<CommandPacketBuilder> command;
+ bool waiting_for_status_;
+ OnceCallback<void(CommandStatusView)> on_status;
+ OnceCallback<void(CommandCompleteView)> on_complete;
+ Handler* caller_handler;
+};
+
+} // namespace
+
+class FakeHciLayer : public HciLayer {
+ public:
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command, OnceCallback<void(CommandStatusView)> on_status,
+ Handler* handler) override {
+ auto command_queue_entry = std::make_unique<CommandQueueEntry>(std::move(command), std::move(on_status), handler);
+ command_queue_.push(std::move(command_queue_entry));
+ }
+
+ void EnqueueCommand(std::unique_ptr<CommandPacketBuilder> command,
+ OnceCallback<void(CommandCompleteView)> on_complete, Handler* handler) override {
+ auto command_queue_entry = std::make_unique<CommandQueueEntry>(std::move(command), std::move(on_complete), handler);
+ command_queue_.push(std::move(command_queue_entry));
+ }
+
+ std::unique_ptr<CommandQueueEntry> GetLastCommand() {
+ EXPECT_FALSE(command_queue_.empty());
+ auto last = std::move(command_queue_.front());
+ command_queue_.pop();
+ return last;
+ }
+
+ void RegisterEventHandler(EventCode event_code, common::Callback<void(EventPacketView)> event_handler,
+ Handler* handler) override {
+ registered_events_[event_code] = event_handler;
+ }
+
+ void UnregisterEventHandler(EventCode event_code) override {
+ registered_events_.erase(event_code);
+ }
+
+ void IncomingEvent(std::unique_ptr<EventPacketBuilder> event_builder) {
+ auto packet = GetPacketView(std::move(event_builder));
+ EventPacketView event = EventPacketView::Create(packet);
+ EXPECT_TRUE(event.IsValid());
+ EventCode event_code = event.GetEventCode();
+ EXPECT_TRUE(registered_events_.find(event_code) != registered_events_.end());
+ registered_events_[event_code].Run(event);
+ }
+
+ void ListDependencies(ModuleList* list) override {}
+ void Start() override {}
+ void Stop() override {}
+
+ private:
+ std::map<EventCode, common::Callback<void(EventPacketView)>> registered_events_;
+ std::queue<std::unique_ptr<CommandQueueEntry>> command_queue_;
+};
+
+} // namespace security
+} // namespace bluetooth
diff --git a/gd/shim/il2cap.h b/gd/shim/il2cap.h
index 1c92f9ffe..c4e746359 100644
--- a/gd/shim/il2cap.h
+++ b/gd/shim/il2cap.h
@@ -16,6 +16,7 @@
#pragma once
#include <cstdint>
+#include <functional>
#include <future>
#include <string>
#include <vector>
@@ -26,20 +27,25 @@
namespace bluetooth {
namespace shim {
-using OnReadDataReady = std::function<void(uint16_t cid, std::vector<const uint8_t> data)>;
-using OnClose = std::function<void(int error_code)>;
+using ConnectionClosedCallback = std::function<void(uint16_t cid, int error_code)>;
+using Postable = std::function<void(std::function<void(uint16_t cid)>)>;
+using ConnectionOpenCallback = std::function<void(uint16_t psm, uint16_t cid, Postable postable)>;
+using ReadDataReadyCallback = std::function<void(uint16_t cid, std::vector<const uint8_t> data)>;
struct IL2cap {
- virtual void RegisterService(uint16_t psm, bool snoop_enabled, std::promise<void> completed) = 0;
- virtual void Connect(uint16_t psm, const std::string address, std::promise<uint16_t> completed) = 0;
+ virtual void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) = 0;
+ virtual void UnregisterService(uint16_t psm) = 0;
+
+ virtual void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) = 0;
+ virtual void CloseConnection(uint16_t cid) = 0;
+
+ virtual void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) = 0;
+ virtual void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) = 0;
- virtual void SetOnReadDataReady(uint16_t cid, OnReadDataReady on_data_ready) = 0;
virtual bool Write(uint16_t cid, const uint8_t* data, size_t len) = 0;
virtual bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;
virtual bool WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;
- virtual void SetOnClose(uint16_t cid, OnClose on_close) = 0;
-
virtual bool IsCongested(uint16_t cid) = 0;
virtual ~IL2cap() {}
};
diff --git a/gd/shim/l2cap.cc b/gd/shim/l2cap.cc
index 3dd98fc11..58b10b562 100644
--- a/gd/shim/l2cap.cc
+++ b/gd/shim/l2cap.cc
@@ -19,6 +19,7 @@
#include <functional>
#include <future>
#include <memory>
+#include <mutex>
#include <queue>
#include <unordered_map>
#include <vector>
@@ -42,10 +43,15 @@ namespace shim {
const ModuleFactory L2cap::Factory = ModuleFactory([]() { return new L2cap(); });
-using ChannelInterfaceId = uint16_t;
-static const ChannelInterfaceId kInvalidChannelInterfaceId = 0;
-static const ChannelInterfaceId kStartChannelInterfaceId = 64;
-static const ChannelInterfaceId kMaxChannels = UINT16_MAX - 1;
+using ConnectionInterfaceDescriptor = uint16_t;
+static const ConnectionInterfaceDescriptor kInvalidConnectionInterfaceDescriptor = 0;
+static const ConnectionInterfaceDescriptor kStartConnectionInterfaceDescriptor = 64;
+static const ConnectionInterfaceDescriptor kMaxConnections = UINT16_MAX - kStartConnectionInterfaceDescriptor - 1;
+
+using ServiceInterfaceCallback =
+ std::function<void(l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result)>;
+using ConnectionInterfaceCallback =
+ std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel>)>;
std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) {
packet::RawBuilder builder;
@@ -55,21 +61,21 @@ std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t
return payload;
}
-class ChannelInterface {
+class ConnectionInterface {
public:
- ChannelInterface(ChannelInterfaceId id, std::unique_ptr<l2cap::classic::DynamicChannel> channel, os::Handler* handler)
- : channel_interface_id_(id), channel_(std::move(channel)), handler_(handler), on_data_ready_callback_{nullptr} {
- channel_->RegisterOnCloseCallback(handler_, common::BindOnce(&ChannelInterface::OnClose, common::Unretained(this)));
- channel_->GetQueueUpEnd()->RegisterDequeue(handler_,
- common::Bind(&ChannelInterface::OnReadReady, common::Unretained(this)));
+ ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel,
+ os::Handler* handler)
+ : cid_(cid), channel_(std::move(channel)), handler_(handler), on_data_ready_callback_(nullptr),
+ on_connection_closed_callback_(nullptr), address_(channel_->GetDevice()) {
+ channel_->RegisterOnCloseCallback(
+ handler_, common::BindOnce(&ConnectionInterface::OnConnectionClosed, common::Unretained(this)));
+ channel_->GetQueueUpEnd()->RegisterDequeue(
+ handler_, common::Bind(&ConnectionInterface::OnReadReady, common::Unretained(this)));
dequeue_registered_ = true;
}
- ~ChannelInterface() {
- if (dequeue_registered_) {
- channel_->GetQueueUpEnd()->UnregisterDequeue();
- dequeue_registered_ = false;
- }
+ ~ConnectionInterface() {
+ ASSERT(!dequeue_registered_);
}
void OnReadReady() {
@@ -80,14 +86,13 @@ class ChannelInterface {
}
std::vector<const uint8_t> data(packet->begin(), packet->end());
ASSERT(on_data_ready_callback_ != nullptr);
- on_data_ready_callback_(channel_interface_id_, data);
+ on_data_ready_callback_(cid_, data);
}
- void OnClose(hci::ErrorCode error_code) {
- LOG_DEBUG("Channel interface closed reason:%s id:%hd device:%s", hci::ErrorCodeText(error_code).c_str(),
- channel_interface_id_, channel_->GetDevice().ToString().c_str());
- ASSERT(on_close_callback_ != nullptr);
- on_close_callback_(static_cast<int>(error_code));
+ void SetReadDataReadyCallback(ReadDataReadyCallback on_data_ready) {
+ ASSERT(on_data_ready != nullptr);
+ ASSERT(on_data_ready_callback_ == nullptr);
+ on_data_ready_callback_ = on_data_ready;
}
std::unique_ptr<packet::BasePacketBuilder> WriteReady() {
@@ -100,38 +105,47 @@ class ChannelInterface {
return data;
}
- void SetOnReadDataReady(OnReadDataReady on_data_ready) {
- ASSERT(on_data_ready_callback_ == nullptr);
- on_data_ready_callback_ = on_data_ready;
- }
-
- void SetOnClose(::bluetooth::shim::OnClose on_close) {
- ASSERT(on_close == nullptr);
- on_close_callback_ = on_close;
- }
-
void Write(std::unique_ptr<packet::RawBuilder> packet) {
+ LOG_DEBUG("Writing packet cid:%hd size:%zd", cid_, packet->size());
write_queue_.push(std::move(packet));
if (!enqueue_registered_) {
enqueue_registered_ = true;
- channel_->GetQueueUpEnd()->RegisterEnqueue(handler_,
- common::Bind(&ChannelInterface::WriteReady, common::Unretained(this)));
+ channel_->GetQueueUpEnd()->RegisterEnqueue(
+ handler_, common::Bind(&ConnectionInterface::WriteReady, common::Unretained(this)));
}
}
void Close() {
+ if (dequeue_registered_) {
+ channel_->GetQueueUpEnd()->UnregisterDequeue();
+ dequeue_registered_ = false;
+ }
ASSERT(write_queue_.empty());
- channel_->GetQueueUpEnd()->UnregisterDequeue();
channel_->Close();
}
+ void OnConnectionClosed(hci::ErrorCode error_code) {
+ LOG_DEBUG("Channel interface closed reason:%s cid:%hd device:%s", hci::ErrorCodeText(error_code).c_str(), cid_,
+ address_.ToString().c_str());
+ ASSERT(on_connection_closed_callback_ != nullptr);
+ on_connection_closed_callback_(cid_, static_cast<int>(error_code));
+ }
+
+ void SetConnectionClosedCallback(::bluetooth::shim::ConnectionClosedCallback on_connection_closed) {
+ ASSERT(on_connection_closed != nullptr);
+ ASSERT(on_connection_closed_callback_ == nullptr);
+ on_connection_closed_callback_ = std::move(on_connection_closed);
+ }
+
private:
- ChannelInterfaceId channel_interface_id_;
- std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
+ const ConnectionInterfaceDescriptor cid_;
+ const std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
os::Handler* handler_;
- OnReadDataReady on_data_ready_callback_;
- ::bluetooth::shim::OnClose on_close_callback_;
+ ReadDataReadyCallback on_data_ready_callback_;
+ ConnectionClosedCallback on_connection_closed_callback_;
+
+ const hci::Address address_;
std::queue<std::unique_ptr<packet::PacketBuilder<hci::kLittleEndian>>> write_queue_;
@@ -139,95 +153,164 @@ class ChannelInterface {
bool dequeue_registered_{false};
};
-struct ChannelInterfaceManager {
+struct ConnectionInterfaceManager {
public:
- ChannelInterfaceId AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
- void RemoveChannel(ChannelInterfaceId id);
+ ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
+ void RemoveConnection(ConnectionInterfaceDescriptor cid);
- void SetOnReadDataReady(ChannelInterfaceId id, OnReadDataReady on_data_ready);
- bool Write(ChannelInterfaceId id, std::unique_ptr<packet::RawBuilder> packet);
+ void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
+ void SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid, ConnectionClosedCallback on_closed);
- void SetOnClose(ChannelInterfaceId id, OnClose on_close);
+ bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);
- bool HasResources() const;
void SetHandler(os::Handler* handler) {
handler_ = handler;
}
- ChannelInterfaceManager();
+ size_t NumberOfActiveConnections() const {
+ return cid_to_interface_map_.size();
+ }
+
+ ConnectionInterfaceManager();
private:
- std::unordered_map<ChannelInterfaceId, std::unique_ptr<ChannelInterface>> channel_id_to_interface_map_;
- ChannelInterfaceId current_channel_interface_id_;
+ std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
+ ConnectionInterfaceDescriptor current_connection_interface_descriptor_;
os::Handler* handler_;
- bool Exists(ChannelInterfaceId id) const;
+ bool HasResources() const;
+ bool Exists(ConnectionInterfaceDescriptor id) const;
+ ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
};
-ChannelInterfaceManager::ChannelInterfaceManager() : current_channel_interface_id_(kStartChannelInterfaceId) {}
+ConnectionInterfaceManager::ConnectionInterfaceManager()
+ : current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}
+
+bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
+ return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
+}
-ChannelInterfaceId ChannelInterfaceManager::AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
- while (!Exists(++current_channel_interface_id_)) {
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AllocateConnectionInterfaceDescriptor() {
+ ASSERT(HasResources());
+ while (Exists(current_connection_interface_descriptor_)) {
+ if (++current_connection_interface_descriptor_ == kInvalidConnectionInterfaceDescriptor) {
+ current_connection_interface_descriptor_ = kStartConnectionInterfaceDescriptor;
+ }
}
- auto channel_interface =
- std::make_unique<ChannelInterface>(current_channel_interface_id_, std::move(channel), handler_);
- channel_id_to_interface_map_[current_channel_interface_id_] = std::move(channel_interface);
- return current_channel_interface_id_;
+ return current_connection_interface_descriptor_++;
}
-void ChannelInterfaceManager::RemoveChannel(ChannelInterfaceId id) {
- ASSERT(channel_id_to_interface_map_.erase(id) == 1);
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
+ std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+ if (!HasResources()) {
+ return kInvalidConnectionInterfaceDescriptor;
+ }
+ ConnectionInterfaceDescriptor cid = AllocateConnectionInterfaceDescriptor();
+
+ auto channel_interface = std::make_unique<ConnectionInterface>(cid, std::move(channel), handler_);
+ cid_to_interface_map_[cid] = std::move(channel_interface);
+ return cid;
}
-bool ChannelInterfaceManager::HasResources() const {
- return channel_id_to_interface_map_.size() < kMaxChannels;
+void ConnectionInterfaceManager::RemoveConnection(ConnectionInterfaceDescriptor cid) {
+ ASSERT(cid_to_interface_map_.count(cid) == 1);
+ cid_to_interface_map_.find(cid)->second->Close();
+ cid_to_interface_map_.erase(cid);
}
-bool ChannelInterfaceManager::Exists(ChannelInterfaceId id) const {
- return channel_id_to_interface_map_.find(id) != channel_id_to_interface_map_.end();
+bool ConnectionInterfaceManager::HasResources() const {
+ return cid_to_interface_map_.size() < kMaxConnections;
}
-void ChannelInterfaceManager::SetOnReadDataReady(ChannelInterfaceId id, OnReadDataReady on_data_ready) {
- ASSERT(Exists(id));
- return channel_id_to_interface_map_[id]->SetOnReadDataReady(on_data_ready);
+void ConnectionInterfaceManager::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid,
+ ReadDataReadyCallback on_data_ready) {
+ ASSERT(Exists(cid));
+ return cid_to_interface_map_[cid]->SetReadDataReadyCallback(on_data_ready);
}
-void ChannelInterfaceManager::SetOnClose(ChannelInterfaceId id, OnClose on_close) {
- ASSERT(Exists(id));
- return channel_id_to_interface_map_[id]->SetOnClose(on_close);
+void ConnectionInterfaceManager::SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid,
+ ConnectionClosedCallback on_closed) {
+ ASSERT(Exists(cid));
+ return cid_to_interface_map_[cid]->SetConnectionClosedCallback(on_closed);
}
-bool ChannelInterfaceManager::Write(ChannelInterfaceId id, std::unique_ptr<packet::RawBuilder> packet) {
- if (!Exists(id)) {
+bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
+ if (!Exists(cid)) {
return false;
}
- channel_id_to_interface_map_[id]->Write(std::move(packet));
+ cid_to_interface_map_[cid]->Write(std::move(packet));
return true;
}
+class ServiceInterface {
+ public:
+ ServiceInterface(uint16_t psm, ServiceInterfaceCallback register_callback,
+ ConnectionInterfaceCallback connection_callback)
+ : psm_(psm), register_callback_(register_callback), connection_callback_(connection_callback) {}
+
+ void OnRegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
+ std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
+ ASSERT(service_ == nullptr);
+ ASSERT(psm_ == service->GetPsm());
+ LOG_DEBUG("Registration is complete for psm:%hd", psm_);
+ service_ = std::move(service);
+ register_callback_(psm_, result);
+ }
+
+ void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+ LOG_DEBUG("Connection is open to device:%s for psm:%hd", channel->GetDevice().ToString().c_str(), psm_);
+ connection_callback_(psm_, std::move(channel));
+ }
+
+ l2cap::SecurityPolicy GetSecurityPolicy() const {
+ return security_policy_;
+ }
+
+ void RegisterService(
+ std::function<void(l2cap::Psm, l2cap::SecurityPolicy security_policy,
+ l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
+ l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open)>
+ func) {
+ func(psm_, security_policy_, common::BindOnce(&ServiceInterface::OnRegistrationComplete, common::Unretained(this)),
+ common::Bind(&ServiceInterface::OnConnectionOpen, common::Unretained(this)));
+ }
+
+ private:
+ const l2cap::Psm psm_;
+ std::unique_ptr<l2cap::classic::DynamicChannelService> service_;
+ const l2cap::SecurityPolicy security_policy_;
+ ServiceInterfaceCallback register_callback_;
+ ConnectionInterfaceCallback connection_callback_;
+};
+
struct L2cap::impl {
- void RegisterService(l2cap::Psm psm, std::promise<void> completed);
- void Connect(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed);
+ void RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed);
+ void UnregisterService(l2cap::Psm psm);
+
+ void CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed);
+ void CloseConnection(ConnectionInterfaceDescriptor cid);
- void RegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
- std::unique_ptr<l2cap::classic::DynamicChannelService> service);
- void LocalConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
- void RemoteConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
- void ConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result);
+ void OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
+ void OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result);
- bool Write(ChannelInterfaceId cid, std::unique_ptr<packet::RawBuilder> packet);
+ bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);
impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_module);
- ChannelInterfaceManager channel_interface_manager_;
+ ConnectionInterfaceManager connection_interface_manager_;
+
+ void OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid);
private:
L2cap& module_;
l2cap::classic::L2capClassicModule* l2cap_module_{nullptr};
-
std::unique_ptr<l2cap::classic::DynamicChannelManager> dynamic_channel_manager_;
- std::queue<std::promise<void>> register_completed_queue_;
- std::queue<std::promise<uint16_t>> connect_completed_queue_;
+ std::unordered_map<l2cap::Psm, std::shared_ptr<ServiceInterface>> psm_to_service_interface_map_;
+ std::unordered_map<l2cap::Psm, ConnectionOpenCallback> psm_to_on_open_map_;
+
+ std::mutex mutex_;
+ std::unordered_map<l2cap::Psm, std::promise<void>> psm_to_register_complete_map_;
+ std::unordered_map<l2cap::Psm, std::queue<std::promise<uint16_t>>> psm_to_connect_completed_queue_;
os::Handler* handler_;
};
@@ -236,35 +319,15 @@ L2cap::impl::impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_modul
: module_(module), l2cap_module_(l2cap_module) {
handler_ = module_.GetHandler();
dynamic_channel_manager_ = l2cap_module_->GetDynamicChannelManager();
- channel_interface_manager_.SetHandler(handler_);
+ connection_interface_manager_.SetHandler(handler_);
}
-void L2cap::impl::RegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
- std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
- LOG_DEBUG("Registration is complete");
- auto completed = std::move(register_completed_queue_.front());
- register_completed_queue_.pop();
- completed.set_value();
+void L2cap::impl::OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+ ASSERT(false);
}
-void L2cap::impl::LocalConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
- LOG_DEBUG("Local initiated connection is open to connect_queue_size:%zd device:%s", connect_completed_queue_.size(),
- channel->GetDevice().ToString().c_str());
- auto completed = std::move(connect_completed_queue_.front());
- connect_completed_queue_.pop();
- if (!channel_interface_manager_.HasResources()) {
- completed.set_value(kInvalidChannelInterfaceId);
- }
- completed.set_value(channel_interface_manager_.AddChannel(std::move(channel)));
-}
-
-void L2cap::impl::RemoteConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
- LOG_DEBUG("Remote initiated connection is open to connect_queue_size:%zd device:%s", connect_completed_queue_.size(),
- channel->GetDevice().ToString().c_str());
- // TODO(cmanton) plumb back to legacy somehow
-}
-
-void L2cap::impl::ConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
+void L2cap::impl::OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
+ ASSERT(false);
switch (result.connection_result_code) {
case l2cap::classic::DynamicChannelManager::ConnectionResultCode::SUCCESS:
LOG_WARN("Connection failed result:success hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
@@ -280,60 +343,131 @@ void L2cap::impl::ConnectionFailure(l2cap::classic::DynamicChannelManager::Conne
l2cap::ConnectionResponseResultText(result.l2cap_connection_response_result).c_str());
break;
}
- auto completed = std::move(connect_completed_queue_.front());
- connect_completed_queue_.pop();
- completed.set_value(kInvalidChannelInterfaceId);
}
-void L2cap::impl::RegisterService(l2cap::Psm psm, std::promise<void> register_completed) {
- l2cap::SecurityPolicy security_policy;
- register_completed_queue_.push(std::move(register_completed));
- bool rc = dynamic_channel_manager_->RegisterService(
- psm, security_policy, common::BindOnce(&L2cap::impl::RegistrationComplete, common::Unretained(this)),
- common::Bind(&L2cap::impl::RemoteConnectionOpen, common::Unretained(this)), handler_);
- ASSERT_LOG(rc == true, "Failed to request register classic service");
+void L2cap::impl::OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid) {
+ LOG_INFO("About to call back to client indicating open connection psm:%hd cid:%hd", psm, cid);
+ psm_to_on_open_map_[psm](psm, cid, [cid](std::function<void(uint16_t cid)> func) {
+ LOG_DEBUG("About to run postable on this thread and inform sdp that connection is open");
+ func(cid);
+ });
}
-void L2cap::impl::Connect(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> connect_completed) {
- connect_completed_queue_.push(std::move(connect_completed));
- bool rc = dynamic_channel_manager_->ConnectChannel(
- address, psm, common::Bind(&L2cap::impl::LocalConnectionOpen, common::Unretained(this)),
- common::Bind(&L2cap::impl::ConnectionFailure, common::Unretained(this)), handler_);
- ASSERT_LOG(rc == true, "Failed to request connect classic channel");
+void L2cap::impl::RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
+ ASSERT(psm_to_service_interface_map_.find(psm) == psm_to_service_interface_map_.end());
+ ASSERT(psm_to_register_complete_map_.find(psm) == psm_to_register_complete_map_.end());
+ ASSERT(psm_to_on_open_map_.find(psm) == psm_to_on_open_map_.end());
+
+ psm_to_on_open_map_[psm] = on_open;
+
+ psm_to_service_interface_map_.emplace(
+ psm, std::make_shared<ServiceInterface>(
+ psm,
+ [this](l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result) {
+ LOG_DEBUG("Service has been registered");
+ ASSERT(psm_to_register_complete_map_.find(psm) != psm_to_register_complete_map_.end());
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ auto completed = std::move(psm_to_register_complete_map_[psm]);
+ psm_to_register_complete_map_.erase(psm);
+ completed.set_value();
+ }
+ },
+
+ [this](l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+ ConnectionInterfaceDescriptor cid = connection_interface_manager_.AddChannel(std::move(channel));
+ LOG_DEBUG("Connection has been opened cid:%hd psm:%hd", cid, psm);
+ {
+ // If initiated locally unblock requestor that
+ // we now have a connection by providing the
+ // cid.
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (psm_to_connect_completed_queue_.find(psm) != psm_to_connect_completed_queue_.end()) {
+ if (!psm_to_connect_completed_queue_[psm].empty()) {
+ LOG_DEBUG("Locally initiated, so inform waiting client of the cid %hd", cid);
+ auto completed = std::move(psm_to_connect_completed_queue_[psm].front());
+ psm_to_connect_completed_queue_[psm].pop();
+ completed.set_value(cid);
+ }
+ }
+ std::this_thread::yield();
+ }
+ if (cid != kInvalidConnectionInterfaceDescriptor) {
+ handler_->Post(common::BindOnce(&L2cap::impl::OpenConnection, common::Unretained(this), psm, cid));
+ }
+ usleep(10);
+ }));
+
+ psm_to_service_interface_map_.find(psm)->second->RegisterService(
+ [this](l2cap::Psm psm, l2cap::SecurityPolicy security_policy,
+ l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
+ l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open) {
+ bool rc = dynamic_channel_manager_->RegisterService(psm, security_policy, std::move(on_registration_complete),
+ on_connection_open, handler_);
+ ASSERT_LOG(rc == true, "Failed to register classic service");
+ });
}
-bool L2cap::impl::Write(ChannelInterfaceId cid, std::unique_ptr<packet::RawBuilder> packet) {
- return channel_interface_manager_.Write(cid, std::move(packet));
+void L2cap::impl::UnregisterService(l2cap::Psm psm) {
+ psm_to_service_interface_map_.erase(psm);
}
-void L2cap::RegisterService(uint16_t raw_psm, bool snoop_enabled, std::promise<void> register_completed) {
- if (!snoop_enabled) {
- LOG_WARN("UNIMPLEMENTED Cannot disable snooping on psm:%d", raw_psm);
+void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed) {
+ LOG_INFO("Creating connection to psm:%hd device:%s", psm, address.ToString().c_str());
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ psm_to_connect_completed_queue_[psm].push(std::move(completed));
}
+ bool rc = dynamic_channel_manager_->ConnectChannel(
+ address, psm, common::Bind(&L2cap::impl::OnConnectionOpenNever, common::Unretained(this)),
+ common::Bind(&L2cap::impl::OnConnectionFailureNever, common::Unretained(this)), handler_);
+ ASSERT_LOG(rc == true, "Failed to create classic connection channel");
+}
- l2cap::Psm psm = raw_psm;
- pimpl_->RegisterService(psm, std::move(register_completed));
+void L2cap::impl::CloseConnection(ConnectionInterfaceDescriptor cid) {
+ connection_interface_manager_.RemoveConnection(cid);
}
-void L2cap::Connect(uint16_t raw_psm, const std::string address_string, std::promise<uint16_t> connect_completed) {
- l2cap::Psm psm = raw_psm;
+bool L2cap::impl::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
+ return connection_interface_manager_.Write(cid, std::move(packet));
+}
+
+void L2cap::RegisterService(uint16_t raw_psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
+ l2cap::Psm psm{raw_psm};
+ pimpl_->RegisterService(psm, on_open, std::move(completed));
+}
+
+void L2cap::UnregisterService(uint16_t raw_psm) {
+ l2cap::Psm psm{raw_psm};
+ pimpl_->UnregisterService(psm);
+}
+
+void L2cap::CreateConnection(uint16_t raw_psm, const std::string address_string, std::promise<uint16_t> completed) {
+ l2cap::Psm psm{raw_psm};
hci::Address address;
hci::Address::FromString(address_string, address);
- return pimpl_->Connect(psm, address, std::move(connect_completed));
+ return pimpl_->CreateConnection(psm, address, std::move(completed));
+}
+
+void L2cap::CloseConnection(uint16_t raw_cid) {
+ ConnectionInterfaceDescriptor cid(raw_cid);
+ return pimpl_->CloseConnection(cid);
}
-void L2cap::SetOnReadDataReady(uint16_t cid, OnReadDataReady on_data_ready) {
- pimpl_->channel_interface_manager_.SetOnReadDataReady(static_cast<ChannelInterfaceId>(cid), on_data_ready);
+void L2cap::SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) {
+ pimpl_->connection_interface_manager_.SetReadDataReadyCallback(static_cast<ConnectionInterfaceDescriptor>(cid),
+ on_data_ready);
}
-void L2cap::SetOnClose(uint16_t cid, OnClose on_close) {
- pimpl_->channel_interface_manager_.SetOnClose(static_cast<ChannelInterfaceId>(cid), on_close);
+void L2cap::SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) {
+ pimpl_->connection_interface_manager_.SetConnectionClosedCallback(static_cast<ConnectionInterfaceDescriptor>(cid),
+ on_closed);
}
bool L2cap::Write(uint16_t cid, const uint8_t* data, size_t len) {
auto packet = MakeUniquePacket(data, len);
- return pimpl_->Write(static_cast<ChannelInterfaceId>(cid), std::move(packet));
+ return pimpl_->Write(static_cast<ConnectionInterfaceDescriptor>(cid), std::move(packet));
}
bool L2cap::WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) {
@@ -346,7 +480,7 @@ bool L2cap::WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) {
return false;
}
-bool L2cap::IsCongested(ChannelInterfaceId cid) {
+bool L2cap::IsCongested(ConnectionInterfaceDescriptor cid) {
LOG_WARN("UNIMPLEMENTED Congestion check on channels or links");
return false;
}
diff --git a/gd/shim/l2cap.h b/gd/shim/l2cap.h
index 35ea13f01..67a75d9da 100644
--- a/gd/shim/l2cap.h
+++ b/gd/shim/l2cap.h
@@ -16,6 +16,7 @@
#pragma once
#include <cstdint>
+#include <functional>
#include <future>
#include <memory>
#include <string>
@@ -28,16 +29,19 @@ namespace shim {
class L2cap : public bluetooth::Module, public bluetooth::shim::IL2cap {
public:
- void RegisterService(uint16_t psm, bool snoop_enabled, std::promise<void> register_completed) override;
- void Connect(uint16_t psm, const std::string address, std::promise<uint16_t> connect_completed) override;
+ void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) override;
+ void UnregisterService(uint16_t psm) override;
+
+ void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) override;
+ void CloseConnection(uint16_t cid) override;
+
+ void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) override;
+ void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) override;
- void SetOnReadDataReady(uint16_t cid, OnReadDataReady on_data_ready) override;
bool Write(uint16_t cid, const uint8_t* data, size_t len) override;
bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
bool WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
- virtual void SetOnClose(uint16_t cid, OnClose on_close) override;
-
bool IsCongested(uint16_t cid) override;
L2cap() = default;
diff --git a/gd/shim/stack.cc b/gd/shim/stack.cc
index 3fbc7f995..8b02e6b87 100644
--- a/gd/shim/stack.cc
+++ b/gd/shim/stack.cc
@@ -52,7 +52,6 @@ struct bluetooth::shim::Stack::impl {
ModuleList modules;
modules.add<::bluetooth::hal::HciHal>();
modules.add<::bluetooth::hci::AclManager>();
- modules.add<::bluetooth::hci::ClassicSecurityManager>();
modules.add<::bluetooth::l2cap::classic::L2capClassicModule>();
modules.add<::bluetooth::l2cap::le::L2capLeModule>();
modules.add<::bluetooth::neighbor::ConnectabilityModule>();
diff --git a/main/Android.bp b/main/Android.bp
index 1ef608fb1..fec664425 100644
--- a/main/Android.bp
+++ b/main/Android.bp
@@ -123,6 +123,7 @@ cc_library_static {
":LibBluetoothSources",
"shim/entry_for_test.cc",
],
+ host_supported: true,
include_dirs: [
"system/bt",
"system/bt/bta/include",
@@ -137,3 +138,33 @@ cc_library_static {
"-DBUILDCFG",
],
}
+
+filegroup {
+ name: "BluetoothLegacyShimTestSources",
+ srcs: [
+ "shim/l2cap_test.cc",
+ "shim/test_stack.cc",
+ ]
+}
+
+cc_test {
+ name: "bluetooth_test_legacy",
+ defaults: ["fluoride_defaults",
+ "fluoride_osi_defaults",
+ ],
+ test_suites: ["device-tests"],
+ host_supported: true,
+ srcs: [
+ ":BluetoothLegacyShimTestSources",
+ ],
+ static_libs: [
+ "libgmock",
+ "libbluetooth-for-tests",
+ "libosi",
+ ],
+ shared_libs: [
+ "libchrome",
+ "liblog",
+ ],
+}
+
diff --git a/main/shim/l2c_api.cc b/main/shim/l2c_api.cc
index dde3ab894..7623df1e8 100644
--- a/main/shim/l2c_api.cc
+++ b/main/shim/l2c_api.cc
@@ -21,7 +21,7 @@
#include "main/shim/shim.h"
#include "osi/include/log.h"
-static bluetooth::shim::L2cap shim_l2cap;
+static bluetooth::legacy::shim::L2cap shim_l2cap;
/**
* Classic Service Registration APIs
@@ -60,7 +60,7 @@ uint16_t bluetooth::shim::L2CA_Register(uint16_t client_psm,
LOG_INFO(LOG_TAG, "%s classic client_psm:%hd psm:%hd", __func__, client_psm,
psm);
- shim_l2cap.Register(psm, callbacks, enable_snoop);
+ shim_l2cap.RegisterService(psm, callbacks, enable_snoop);
return client_psm;
}
@@ -116,7 +116,7 @@ uint16_t bluetooth::shim::L2CA_ErtmConnectReq(uint16_t psm,
tL2CAP_ERTM_INFO* p_ertm_info) {
CHECK(p_ertm_info == nullptr)
<< "UNIMPLEMENTED set enhanced retransmission mode config";
- return shim_l2cap.Connect(psm, raw_address);
+ return shim_l2cap.CreateConnection(psm, raw_address);
}
uint16_t bluetooth::shim::L2CA_ConnectReq(uint16_t psm,
@@ -143,24 +143,20 @@ bool bluetooth::shim::L2CA_ConnectRsp(const RawAddress& p_bd_addr, uint8_t id,
status, NULL);
}
-bool bluetooth::shim::L2CA_ConfigReq(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s cid:%hd p_cfg:%p", __func__, cid, p_cfg);
- return false;
+bool bluetooth::shim::L2CA_ConfigReq(uint16_t cid, tL2CAP_CFG_INFO* cfg_info) {
+ return shim_l2cap.ConfigRequest(cid, cfg_info);
}
-bool bluetooth::shim::L2CA_ConfigRsp(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s cid:%hd p_cfg:%p", __func__, cid, p_cfg);
- return false;
+bool bluetooth::shim::L2CA_ConfigRsp(uint16_t cid, tL2CAP_CFG_INFO* cfg_info) {
+ return shim_l2cap.ConfigResponse(cid, cfg_info);
}
bool bluetooth::shim::L2CA_DisconnectReq(uint16_t cid) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s cid:%hd ", __func__, cid);
- return false;
+ return shim_l2cap.DisconnectRequest(cid);
}
bool bluetooth::shim::L2CA_DisconnectRsp(uint16_t cid) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s cid:%hd ", __func__, cid);
- return false;
+ return shim_l2cap.DisconnectResponse(cid);
}
/**
diff --git a/main/shim/l2cap.cc b/main/shim/l2cap.cc
index da4292953..5cf3b92a1 100644
--- a/main/shim/l2cap.cc
+++ b/main/shim/l2cap.cc
@@ -15,49 +15,69 @@
*/
#define LOG_TAG "bt_shim_l2cap"
-#include "main/shim/l2cap.h"
+#include <cstdint>
+
#include "main/shim/entry.h"
+#include "main/shim/l2cap.h"
#include "main/shim/shim.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
constexpr size_t kBtHdrSize = sizeof(BT_HDR);
+constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
-bool bluetooth::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
- return psm_to_callback_map.find(psm) != psm_to_callback_map.end();
+bool bluetooth::legacy::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
+ return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
}
-bool bluetooth::shim::PsmData::IsPsmRegistered(uint16_t psm) const {
- return IsPsmAllocated(psm) && psm_to_callback_map.at(psm) != nullptr;
+bool bluetooth::legacy::shim::PsmData::IsPsmRegistered(uint16_t psm) const {
+ return IsPsmAllocated(psm) && psm_to_callback_map_.at(psm) != nullptr;
}
-void bluetooth::shim::PsmData::AllocatePsm(uint16_t psm) {
+void bluetooth::legacy::shim::PsmData::AllocatePsm(uint16_t psm) {
RegisterPsm(psm, nullptr);
}
-void bluetooth::shim::PsmData::RegisterPsm(uint16_t psm,
- const tL2CAP_APPL_INFO* callbacks) {
- psm_to_callback_map[psm] = callbacks;
+void bluetooth::legacy::shim::PsmData::RegisterPsm(
+ uint16_t psm, const tL2CAP_APPL_INFO* callbacks) {
+ psm_to_callback_map_[psm] = callbacks;
}
-void bluetooth::shim::PsmData::UnregisterPsm(uint16_t psm) {
- psm_to_callback_map[psm] = nullptr;
+void bluetooth::legacy::shim::PsmData::UnregisterPsm(uint16_t psm) {
+ psm_to_callback_map_[psm] = nullptr;
}
-void bluetooth::shim::PsmData::DeallocatePsm(uint16_t psm) {
- psm_to_callback_map.erase(psm);
+void bluetooth::legacy::shim::PsmData::DeallocatePsm(uint16_t psm) {
+ psm_to_callback_map_.erase(psm);
+}
+
+const tL2CAP_APPL_INFO* bluetooth::legacy::shim::PsmData::Callbacks(
+ uint16_t psm) {
+ if (psm_to_callback_map_.find(psm) == psm_to_callback_map_.end()) {
+ LOG_WARN(LOG_TAG, "Accessing unknown psm:%hd:", psm);
+ return nullptr;
+ }
+ return psm_to_callback_map_[psm];
}
-bluetooth::shim::L2cap::L2cap()
+bluetooth::legacy::shim::L2cap::L2cap()
: classic_dynamic_psm_(kInitialClassicDynamicPsm),
le_dynamic_psm_(kInitialLeDynamicPsm),
classic_virtual_psm_(kInitialClassicVirtualPsm) {}
-bluetooth::shim::PsmData& bluetooth::shim::L2cap::Le() { return le_; }
+bluetooth::legacy::shim::PsmData& bluetooth::legacy::shim::L2cap::Le() {
+ return le_;
+}
+
+bluetooth::legacy::shim::PsmData& bluetooth::legacy::shim::L2cap::Classic() {
+ return classic_;
+}
-bluetooth::shim::PsmData& bluetooth::shim::L2cap::Classic() { return classic_; }
+bool bluetooth::legacy::shim::L2cap::ConnectionExists(uint16_t cid) const {
+ return cid_to_psm_map_.find(cid) != cid_to_psm_map_.end();
+}
-uint16_t bluetooth::shim::L2cap::ConvertClientToRealPsm(
+uint16_t bluetooth::legacy::shim::L2cap::ConvertClientToRealPsm(
uint16_t client_psm, bool is_outgoing_only_connection) {
if (!is_outgoing_only_connection) {
return client_psm;
@@ -65,7 +85,8 @@ uint16_t bluetooth::shim::L2cap::ConvertClientToRealPsm(
return GetNextVirtualPsm(client_psm);
}
-uint16_t bluetooth::shim::L2cap::ConvertClientToRealPsm(uint16_t client_psm) {
+uint16_t bluetooth::legacy::shim::L2cap::ConvertClientToRealPsm(
+ uint16_t client_psm) {
if (client_psm_to_real_psm_map_.find(client_psm) ==
client_psm_to_real_psm_map_.end()) {
return client_psm;
@@ -73,14 +94,14 @@ uint16_t bluetooth::shim::L2cap::ConvertClientToRealPsm(uint16_t client_psm) {
return client_psm_to_real_psm_map_.at(client_psm);
}
-void bluetooth::shim::L2cap::RemoveClientPsm(uint16_t client_psm) {
+void bluetooth::legacy::shim::L2cap::RemoveClientPsm(uint16_t client_psm) {
if (client_psm_to_real_psm_map_.find(client_psm) !=
client_psm_to_real_psm_map_.end()) {
client_psm_to_real_psm_map_.erase(client_psm);
}
}
-uint16_t bluetooth::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
+uint16_t bluetooth::legacy::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
if (real_psm < kInitialClassicDynamicPsm) {
return real_psm;
}
@@ -94,7 +115,7 @@ uint16_t bluetooth::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
return classic_virtual_psm_;
}
-uint16_t bluetooth::shim::L2cap::GetNextDynamicLePsm() {
+uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
while (Le().IsPsmAllocated(le_dynamic_psm_)) {
le_dynamic_psm_++;
if (le_dynamic_psm_ > kFinalLeDynamicPsm) {
@@ -104,7 +125,7 @@ uint16_t bluetooth::shim::L2cap::GetNextDynamicLePsm() {
return le_dynamic_psm_;
}
-uint16_t bluetooth::shim::L2cap::GetNextDynamicClassicPsm() {
+uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicClassicPsm() {
while (Classic().IsPsmAllocated(classic_dynamic_psm_)) {
classic_dynamic_psm_ += 2;
if (classic_dynamic_psm_ > kFinalClassicDynamicPsm) {
@@ -123,89 +144,210 @@ uint16_t bluetooth::shim::L2cap::GetNextDynamicClassicPsm() {
return classic_dynamic_psm_;
}
-void bluetooth::shim::L2cap::Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
- bool enable_snoop) {
+void bluetooth::legacy::shim::L2cap::RegisterService(
+ uint16_t psm, const tL2CAP_APPL_INFO* callbacks, bool enable_snoop) {
LOG_DEBUG(LOG_TAG, "Registering service on psm:%hd", psm);
+ if (!enable_snoop) {
+ LOG_WARN(LOG_TAG, "UNIMPLEMENTED Cannot disable snooping on psm:%d", psm);
+ }
+
+ Classic().RegisterPsm(psm, callbacks);
+
std::promise<void> register_completed;
auto completed = register_completed.get_future();
- bluetooth::shim::GetL2cap()->RegisterService(psm, enable_snoop,
- std::move(register_completed));
+ bluetooth::shim::GetL2cap()->RegisterService(
+ psm,
+ std::bind(&bluetooth::legacy::shim::L2cap::OnConnectionReady, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3),
+ std::move(register_completed));
completed.wait();
LOG_DEBUG(LOG_TAG, "Successfully registered service on psm:%hd", psm);
}
-uint16_t bluetooth::shim::L2cap::Connect(uint16_t psm,
- const RawAddress& raw_address) {
+uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
+ uint16_t psm, const RawAddress& raw_address) {
LOG_DEBUG(LOG_TAG, "Requesting connection to psm:%hd address:%s", psm,
raw_address.ToString().c_str());
+ if (!Classic().IsPsmRegistered(psm)) {
+ LOG_WARN(LOG_TAG, "Service must be registered in order to connect psm:%hd",
+ psm);
+ return kInvalidConnectionInterfaceDescriptor;
+ }
+
std::promise<uint16_t> connect_completed;
auto completed = connect_completed.get_future();
- bluetooth::shim::GetL2cap()->Connect(psm, raw_address.ToString(),
- std::move(connect_completed));
+ bluetooth::shim::GetL2cap()->CreateConnection(psm, raw_address.ToString(),
+ std::move(connect_completed));
uint16_t cid = completed.get();
- LOG_INFO(LOG_TAG,
- "Successfully connected using connection_interface_descriptor:%hd "
- "psm:%hd address:%s",
- cid, psm, raw_address.ToString().c_str());
+ if (cid == kInvalidConnectionInterfaceDescriptor) {
+ LOG_WARN(LOG_TAG,
+ "Failed to allocate resources to connect to psm:%hd address:%s",
+ psm, raw_address.ToString().c_str());
+ } else {
+ LOG_DEBUG(LOG_TAG,
+ "Successfully started connection to psm:%hd address:%s"
+ " connection_interface_descriptor:%hd",
+ psm, raw_address.ToString().c_str(), cid);
+ CHECK(cid_to_psm_map_.find(cid) == cid_to_psm_map_.end());
+ cid_to_psm_map_[cid] = psm;
+ SetCallbacks(cid, Classic().Callbacks(psm));
+ const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
+ CHECK(callbacks != nullptr);
+ }
return cid;
}
-bool bluetooth::shim::L2cap::IsCongested(uint16_t cid) const {
- LOG_WARN(LOG_TAG, "UNIMPLEMENTED checking congestion on a channel");
+void bluetooth::legacy::shim::L2cap::OnConnectionReady(
+ uint16_t psm, uint16_t cid,
+ std::function<void(std::function<void(uint16_t c)>)> func) {
+ LOG_DEBUG(
+ LOG_TAG,
+ "l2cap got new connection psm:%hd connection_interface_descriptor:%hd",
+ psm, cid);
+ const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
+ if (callbacks == nullptr) {
+ return;
+ }
+ LOG_DEBUG(LOG_TAG, "%s Setting postable map for cid:%d", __func__, cid);
+ cid_to_postable_map_[cid] = func;
+ func([&cid, &callbacks](uint16_t cid2) {
+ LOG_WARN(LOG_TAG,
+ "Queuing up the connection confirm to the upper stack but really "
+ "a connection has already been done Cid:%hd Cid2:%hd",
+ cid, cid2);
+ callbacks->pL2CA_ConnectCfm_Cb(cid2, 0);
+ });
+}
+
+bool bluetooth::legacy::shim::L2cap::IsCongested(uint16_t cid) const {
+ CHECK(ConnectionExists(cid));
+ LOG_WARN(LOG_TAG, "Ignoring checks for congestion on cid:%hd", cid);
return false;
}
-bool bluetooth::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
+bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
+ CHECK(ConnectionExists(cid));
+ CHECK(bt_hdr != nullptr);
const uint8_t* data = bt_hdr->data + bt_hdr->offset;
size_t len = bt_hdr->len;
+ LOG_DEBUG(LOG_TAG, "Writing data cid:%hd len:%zd", cid, len);
return bluetooth::shim::GetL2cap()->Write(cid, data, len);
}
-bool bluetooth::shim::L2cap::WriteFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+bool bluetooth::legacy::shim::L2cap::WriteFlushable(uint16_t cid,
+ BT_HDR* bt_hdr) {
+ CHECK(ConnectionExists(cid));
+ CHECK(bt_hdr != nullptr);
const uint8_t* data = bt_hdr->data + bt_hdr->offset;
size_t len = bt_hdr->len;
return bluetooth::shim::GetL2cap()->WriteFlushable(cid, data, len);
}
-bool bluetooth::shim::L2cap::WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+bool bluetooth::legacy::shim::L2cap::WriteNonFlushable(uint16_t cid,
+ BT_HDR* bt_hdr) {
+ CHECK(ConnectionExists(cid));
+ CHECK(bt_hdr != nullptr);
const uint8_t* data = bt_hdr->data + bt_hdr->offset;
size_t len = bt_hdr->len;
return bluetooth::shim::GetL2cap()->WriteNonFlushable(cid, data, len);
}
-bool bluetooth::shim::L2cap::SetCallbacks(uint16_t cid,
- const tL2CAP_APPL_INFO* callbacks) {
- LOG_ASSERT(cid_to_callback_map_.find(cid) != cid_to_callback_map_.end())
- << "Registering multiple channel callbacks "
+bool bluetooth::legacy::shim::L2cap::SetCallbacks(
+ uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
+ CHECK(callbacks != nullptr);
+ CHECK(ConnectionExists(cid));
+ LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
+ << "Already have callbacks registered for "
"connection_interface_descriptor:"
<< cid;
cid_to_callback_map_[cid] = callbacks;
- bluetooth::shim::GetL2cap()->SetOnReadDataReady(
- cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
- LOG_INFO(LOG_TAG,
- "Got data on connection_interface_descriptor:%hd len:%zd", cid,
- data.size());
+ bluetooth::shim::GetL2cap()->SetReadDataReadyCallback(
+ cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
+ LOG_DEBUG(LOG_TAG, "OnDataReady cid:%hd len:%zd", cid, data.size());
BT_HDR* bt_hdr =
static_cast<BT_HDR*>(osi_calloc(data.size() + kBtHdrSize));
std::copy(data.begin(), data.end(), bt_hdr->data);
bt_hdr->len = data.size();
-
cid_to_callback_map_[cid]->pL2CA_DataInd_Cb(cid, bt_hdr);
});
- bluetooth::shim::GetL2cap()->SetOnClose(cid, [this, &cid](int error_code) {
- LOG_DEBUG(LOG_TAG, "Channel closed connection_interface_descriptor:%hd",
- cid);
- cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(cid, true);
- });
+
+ bluetooth::shim::GetL2cap()->SetConnectionClosedCallback(
+ cid, [this](uint16_t cid, int error_code) {
+ LOG_DEBUG(LOG_TAG, "OnChannel closed callback cid:%hd", cid);
+ cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(cid, true);
+ });
return true;
}
-void bluetooth::shim::L2cap::ClearCallbacks(uint16_t cid) {
- LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
- << "Clearing callbacks that do not exist connection_interface_descriptor:"
- << cid;
+void bluetooth::legacy::shim::L2cap::ClearCallbacks(uint16_t cid) {
+ CHECK(ConnectionExists(cid));
cid_to_callback_map_.erase(cid);
}
+
+bool bluetooth::legacy::shim::L2cap::ConnectResponse(
+ const RawAddress& raw_address, uint8_t signal_id, uint16_t cid,
+ uint16_t result, uint16_t status, tL2CAP_ERTM_INFO* ertm_info) {
+ CHECK(ConnectionExists(cid));
+ LOG_DEBUG(LOG_TAG,
+ "%s Silently dropping client connect response as channel is "
+ "already connected",
+ __func__);
+ return true;
+}
+
+bool bluetooth::legacy::shim::L2cap::ConfigRequest(
+ uint16_t cid, const tL2CAP_CFG_INFO* config_info) {
+ CHECK(ConnectionExists(cid));
+ LOG_INFO(LOG_TAG, "Received config request from upper layer");
+ CHECK(cid_to_psm_map_.find(cid) != cid_to_psm_map_.end());
+ const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(cid_to_psm_map_[cid]);
+ CHECK(callbacks != nullptr);
+ CHECK(cid_to_postable_map_.count(cid) == 1);
+
+ auto func = cid_to_postable_map_[cid];
+ func([&cid, &callbacks](uint16_t cid2) {
+ tL2CAP_CFG_INFO cfg_info{
+ .result = L2CAP_CFG_OK,
+ .mtu_present = false,
+ .qos_present = false,
+ .flush_to_present = false,
+ .fcr_present = false,
+ .fcs_present = false,
+ .ext_flow_spec_present = false,
+ .flags = 0,
+ };
+ LOG_INFO(LOG_TAG, "Config request lambda");
+ callbacks->pL2CA_ConfigCfm_Cb(cid, &cfg_info);
+ callbacks->pL2CA_ConfigInd_Cb(cid, &cfg_info);
+ });
+ return true;
+}
+
+bool bluetooth::legacy::shim::L2cap::ConfigResponse(
+ uint16_t cid, const tL2CAP_CFG_INFO* config_info) {
+ CHECK(ConnectionExists(cid));
+ LOG_DEBUG(
+ LOG_TAG,
+ "%s Silently dropping client config response as channel is already open",
+ __func__);
+ return true;
+}
+
+bool bluetooth::legacy::shim::L2cap::DisconnectRequest(uint16_t cid) {
+ CHECK(ConnectionExists(cid));
+ bluetooth::shim::GetL2cap()->CloseConnection(cid);
+ return true;
+}
+
+bool bluetooth::legacy::shim::L2cap::DisconnectResponse(uint16_t cid) {
+ CHECK(ConnectionExists(cid));
+ LOG_DEBUG(LOG_TAG,
+ "%s Silently dropping client disconnect response as channel is "
+ "already disconnected",
+ __func__);
+ return true;
+}
diff --git a/main/shim/l2cap.h b/main/shim/l2cap.h
index 6653a4acd..d238a0b79 100644
--- a/main/shim/l2cap.h
+++ b/main/shim/l2cap.h
@@ -22,6 +22,7 @@
#include "stack/include/l2c_api.h"
namespace bluetooth {
+namespace legacy {
namespace shim {
static constexpr uint16_t kInitialClassicDynamicPsm = 0x1001;
@@ -41,16 +42,28 @@ using PsmData = struct {
void UnregisterPsm(uint16_t psm);
void DeallocatePsm(uint16_t psm);
+ const tL2CAP_APPL_INFO* Callbacks(uint16_t psm);
+
private:
- std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> psm_to_callback_map;
+ std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> psm_to_callback_map_;
};
class L2cap {
public:
- L2cap();
+ void RegisterService(uint16_t psm, const tL2CAP_APPL_INFO* callbacks,
+ bool enable_snoop);
+ uint16_t CreateConnection(uint16_t psm, const RawAddress& raw_address);
+ void OnConnectionReady(
+ uint16_t psm, uint16_t cid,
+ std::function<void(std::function<void(uint16_t cid)>)> func);
- PsmData& Classic();
- PsmData& Le();
+ bool Write(uint16_t cid, BT_HDR* bt_hdr);
+ bool WriteFlushable(uint16_t cid, BT_HDR* bt_hdr);
+ bool WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr);
+ bool IsCongested(uint16_t cid) const;
+
+ bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* callbacks);
+ void ClearCallbacks(uint16_t cid);
uint16_t GetNextDynamicClassicPsm();
uint16_t GetNextDynamicLePsm();
@@ -60,16 +73,22 @@ class L2cap {
uint16_t ConvertClientToRealPsm(uint16_t psm);
void RemoveClientPsm(uint16_t client_psm);
- void Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info, bool enable_snoop);
- uint16_t Connect(uint16_t psm, const RawAddress& raw_address);
+ // Legacy API entry points
+ bool ConnectResponse(const RawAddress& raw_address, uint8_t signal_id,
+ uint16_t cid, uint16_t result, uint16_t status,
+ tL2CAP_ERTM_INFO* ertm_info);
+ bool ConfigRequest(uint16_t cid, const tL2CAP_CFG_INFO* config_info);
+ bool ConfigResponse(uint16_t cid, const tL2CAP_CFG_INFO* config_info);
+ bool DisconnectRequest(uint16_t cid);
+ bool DisconnectResponse(uint16_t cid);
- bool Write(uint16_t cid, BT_HDR* bt_hdr);
- bool WriteFlushable(uint16_t cid, BT_HDR* bt_hdr);
- bool WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr);
- bool IsCongested(uint16_t cid) const;
+ void Test(void* context);
+ void Test2();
- bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* client_callbacks);
- void ClearCallbacks(uint16_t cid);
+ L2cap();
+
+ PsmData& Classic();
+ PsmData& Le();
private:
uint16_t GetNextVirtualPsm(uint16_t real_psm);
@@ -77,13 +96,20 @@ class L2cap {
PsmData classic_;
PsmData le_;
+ bool ConnectionExists(uint16_t cid) const;
+
uint16_t classic_dynamic_psm_;
uint16_t le_dynamic_psm_;
uint16_t classic_virtual_psm_;
+ std::unordered_map<uint16_t,
+ std::function<void(std::function<void(uint16_t c)>)>>
+ cid_to_postable_map_;
+ std::unordered_map<uint16_t, uint16_t> cid_to_psm_map_;
std::unordered_map<uint16_t, uint16_t> client_psm_to_real_psm_map_;
std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> cid_to_callback_map_;
};
} // namespace shim
+} // namespace legacy
} // namespace bluetooth
diff --git a/main/shim/l2cap_test.cc b/main/shim/l2cap_test.cc
new file mode 100644
index 000000000..c0f9a7b95
--- /dev/null
+++ b/main/shim/l2cap_test.cc
@@ -0,0 +1,254 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <cstdint>
+
+#define LOG_TAG "bt_shim_test"
+
+#include "osi/include/log.h"
+#include "shim/l2cap.h"
+#include "shim/test_stack.h"
+#include "types/raw_address.h"
+
+TestStack test_stack_;
+
+bluetooth::shim::IStack* bluetooth::shim::GetGabeldorscheStack() {
+ return (bluetooth::shim::IStack*)&test_stack_;
+}
+
+namespace bluetooth {
+namespace legacy {
+
+namespace {
+
+constexpr uint16_t kPsm = 123;
+constexpr uint16_t kCid = 987;
+constexpr size_t kDataBufferSize = 1024;
+
+uint8_t bt_hdr_data[] = {
+ 0x00, 0x00, /* event */
+ 0x08, 0x00, /* len */
+ 0x00, 0x00, /* offset */
+ 0x00, 0x00, /* layer specific */
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, /* data */
+ 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, /* data */
+};
+
+class L2capTest;
+L2capTest* l2cap_test_ = nullptr;
+
+class L2capTest : public ::testing::Test {
+ public:
+ static shim::L2cap* l2cap_;
+
+ struct {
+ int L2caConnectCfmCb;
+ int L2caConnectPndCb;
+ int L2caConfigIndCb;
+ int L2caConfigCfmCb;
+ int L2caDisconnectIndCb;
+ int L2caDisconnectCfmCb;
+ int L2caQosViolationIndCb;
+ int L2caDataIndCb;
+ int L2caCongestionStatusCb;
+ int L2caTxCompleteCb;
+ int L2caCreditsReceivedCb;
+ } cnt_{
+ .L2caConnectCfmCb = 0,
+ .L2caConnectPndCb = 0,
+ .L2caConfigIndCb = 0,
+ .L2caConfigCfmCb = 0,
+ .L2caDisconnectIndCb = 0,
+ .L2caDisconnectCfmCb = 0,
+ .L2caQosViolationIndCb = 0,
+ .L2caDataIndCb = 0,
+ .L2caCongestionStatusCb = 0,
+ .L2caTxCompleteCb = 0,
+ .L2caCreditsReceivedCb = 0,
+ };
+
+ protected:
+ void SetUp() override {
+ l2cap_ = new shim::L2cap();
+ l2cap_test_ = this;
+ }
+
+ void TearDown() override {
+ delete l2cap_;
+ l2cap_ = nullptr;
+ }
+
+ uint8_t data_buffer_[kDataBufferSize];
+};
+
+shim::L2cap* L2capTest::l2cap_ = nullptr;
+// Indication of remotely initiated connection response sent
+void L2caConnectIndCb(const RawAddress& raw_address, uint16_t a, uint16_t b,
+ uint8_t c) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+// Confirms locally initiated connection request completed
+void L2caConnectCfmCb(uint16_t cid, uint16_t result) {
+ l2cap_test_->cnt_.L2caConnectCfmCb++;
+ LOG_INFO(LOG_TAG, "%s cid:%hd result:%hd", __func__, cid, result);
+}
+
+void L2caConnectPndCb(uint16_t cid) {
+ l2cap_test_->cnt_.L2caConnectPndCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+// Indication of remotely initiated configuration response sent
+void L2caConfigIndCb(uint16_t cid, tL2CAP_CFG_INFO* callbacks) {
+ l2cap_test_->cnt_.L2caConfigIndCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+// Confirms locally initiated config request completed
+void L2caConfigCfmCb(uint16_t cid, tL2CAP_CFG_INFO* callbacks) {
+ l2cap_test_->cnt_.L2caConfigCfmCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+// Indication of remotely initiated disconnection response sent
+void L2caDisconnectIndCb(uint16_t cid, bool needs_ack) {
+ l2cap_test_->cnt_.L2caDisconnectIndCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+// Confirms locally initiated disconnect request completed
+void L2caDisconnectCfmCb(uint16_t cid, uint16_t result) {
+ l2cap_test_->cnt_.L2caDisconnectCfmCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+void L2caQosViolationIndCb(const RawAddress& raw_address) {
+ l2cap_test_->cnt_.L2caQosViolationIndCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+void L2caDataIndCb(uint16_t cid, BT_HDR* bt_hdr) {
+ l2cap_test_->cnt_.L2caDataIndCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+void L2caCongestionStatusCb(uint16_t cid, bool is_congested) {
+ l2cap_test_->cnt_.L2caCongestionStatusCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+void L2caTxCompleteCb(uint16_t cid, uint16_t sdu_cnt) {
+ l2cap_test_->cnt_.L2caTxCompleteCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+void L2caCreditsReceivedCb(uint16_t cid, uint16_t credits_received,
+ uint16_t credit_count) {
+ l2cap_test_->cnt_.L2caCreditsReceivedCb++;
+ LOG_INFO(LOG_TAG, "%s", __func__);
+}
+
+tL2CAP_APPL_INFO test_callbacks{
+ .pL2CA_ConnectInd_Cb = L2caConnectIndCb,
+ .pL2CA_ConnectCfm_Cb = L2caConnectCfmCb,
+ .pL2CA_ConnectPnd_Cb = L2caConnectPndCb,
+ .pL2CA_ConfigInd_Cb = L2caConfigIndCb,
+ .pL2CA_ConfigCfm_Cb = L2caConfigCfmCb,
+ .pL2CA_DisconnectInd_Cb = L2caDisconnectIndCb,
+ .pL2CA_DisconnectCfm_Cb = L2caDisconnectCfmCb,
+ .pL2CA_QoSViolationInd_Cb = L2caQosViolationIndCb,
+ .pL2CA_DataInd_Cb = L2caDataIndCb,
+ .pL2CA_CongestionStatus_Cb = L2caCongestionStatusCb,
+ .pL2CA_TxComplete_Cb = L2caTxCompleteCb,
+ .pL2CA_CreditsReceived_Cb = L2caCreditsReceivedCb,
+};
+
+TEST_F(L2capTest, Base) { LOG_INFO(LOG_TAG, "Got test %p", &test_callbacks); }
+
+TEST_F(L2capTest, Callbacks) {
+ bool rc = l2cap_->SetCallbacks(kPsm, &test_callbacks);
+ CHECK(rc == true);
+}
+
+TEST_F(L2capTest, RegisterService) {
+ l2cap_->RegisterService(123, &test_callbacks, false);
+}
+
+TEST_F(L2capTest, CreateConnection_NotRegistered) {
+ RawAddress raw_address;
+ std::string string_address("11:22:33:44:55:66");
+ RawAddress::FromString(string_address, raw_address);
+ uint16_t cid = l2cap_->CreateConnection(123, raw_address);
+ CHECK(cid == 0);
+}
+
+TEST_F(L2capTest, CreateConnection_Registered) {
+ test_stack_.test_l2cap_.cid_ = kCid;
+ l2cap_->RegisterService(123, &test_callbacks, false);
+
+ RawAddress raw_address;
+ std::string string_address("11:22:33:44:55:66");
+ RawAddress::FromString(string_address, raw_address);
+ uint16_t cid = l2cap_->CreateConnection(123, raw_address);
+ CHECK(cid != 0);
+}
+
+TEST_F(L2capTest, CreateConnection_WithHandshake) {
+ test_stack_.test_l2cap_.cid_ = kCid;
+ l2cap_->RegisterService(kPsm, &test_callbacks, false);
+
+ RawAddress raw_address;
+ std::string string_address("11:22:33:44:55:66");
+ RawAddress::FromString(string_address, raw_address);
+ uint16_t cid = l2cap_->CreateConnection(kPsm, raw_address);
+ CHECK(cid != 0);
+
+ {
+ // Simulate a successful connection response
+ l2cap_->OnConnectionReady(kPsm, kCid,
+ [&cid](std::function<void(uint16_t)> func) {
+ LOG_INFO(LOG_TAG, "In closure cid:%d", cid);
+ func(cid);
+ });
+ }
+ CHECK(cnt_.L2caConnectCfmCb == 1);
+
+ CHECK(l2cap_->ConfigRequest(cid, nullptr) == true);
+ CHECK(cnt_.L2caConfigCfmCb == 1);
+
+ BT_HDR* bt_hdr = (BT_HDR*)bt_hdr_data;
+
+ test_stack_.test_l2cap_.data_buffer_ = data_buffer_;
+ test_stack_.test_l2cap_.data_buffer_size_ = kDataBufferSize;
+
+ l2cap_->Write(cid, bt_hdr);
+
+ CHECK(data_buffer_[0] == 0x11);
+ CHECK(data_buffer_[1] == 0x22);
+ CHECK(data_buffer_[2] == 0x33);
+ CHECK(data_buffer_[3] == 0x44);
+ CHECK(data_buffer_[4] == 0x55);
+ CHECK(data_buffer_[5] == 0x66);
+ CHECK(data_buffer_[6] == 0x77);
+ CHECK(data_buffer_[7] == 0x88);
+ CHECK(data_buffer_[8] == 0x00);
+}
+
+} // namespace
+} // namespace legacy
+} // namespace bluetooth
diff --git a/main/shim/test_stack.cc b/main/shim/test_stack.cc
new file mode 100644
index 000000000..7769fa0b0
--- /dev/null
+++ b/main/shim/test_stack.cc
@@ -0,0 +1,91 @@
+/*
+ * 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 <cstdint>
+#include <future>
+
+#include "gd/shim/only_include_this_file_into_legacy_stack___ever.h"
+#include "main/shim/entry.h"
+#include "main/shim/test_stack.h"
+#include "osi/include/log.h"
+
+#define ASSERT(condition) \
+ do { \
+ if (!(condition)) { \
+ LOG_ALWAYS_FATAL("assertion '" #condition "' failed"); \
+ } \
+ } while (false)
+
+void TestGdShimL2cap::RegisterService(
+ uint16_t psm, bluetooth::shim::ConnectionOpenCallback on_open,
+ std::promise<void> completed) {
+ completed.set_value();
+}
+
+void TestGdShimL2cap::UnregisterService(uint16_t psm) {}
+
+void TestGdShimL2cap::CreateConnection(uint16_t psm, const std::string address,
+ std::promise<uint16_t> completed) {
+ completed.set_value(cid_);
+}
+
+void TestGdShimL2cap::CloseConnection(uint16_t cid) {}
+
+void TestGdShimL2cap::SetReadDataReadyCallback(
+ uint16_t cid, bluetooth::shim::ReadDataReadyCallback on_data_ready) {}
+
+void TestGdShimL2cap::SetConnectionClosedCallback(
+ uint16_t cid, bluetooth::shim::ConnectionClosedCallback on_closed) {}
+
+bool TestGdShimL2cap::Write(uint16_t cid, const uint8_t* data, size_t len) {
+ ASSERT(data_buffer_ != nullptr);
+ ASSERT(data_buffer_size_ > len);
+ memcpy(data_buffer_, data, len);
+ return write_success_;
+}
+
+bool TestGdShimL2cap::WriteFlushable(uint16_t cid, const uint8_t* data,
+ size_t len) {
+ return write_success_;
+}
+
+bool TestGdShimL2cap::WriteNonFlushable(uint16_t cid, const uint8_t* data,
+ size_t len) {
+ return write_success_;
+}
+
+bool TestGdShimL2cap::IsCongested(uint16_t cid) { return is_congested_; }
+
+void TestStack::Start() {}
+
+void TestStack::Stop() {}
+
+bluetooth::shim::IController* TestStack::GetController() { return nullptr; }
+
+bluetooth::shim::IConnectability* TestStack::GetConnectability() {
+ return nullptr;
+}
+
+bluetooth::shim::IDiscoverability* TestStack::GetDiscoverability() {
+ return nullptr;
+}
+
+bluetooth::shim::IHciLayer* TestStack::GetHciLayer() { return nullptr; }
+
+bluetooth::shim::IInquiry* TestStack::GetInquiry() { return nullptr; }
+
+bluetooth::shim::IL2cap* TestStack::GetL2cap() { return &test_l2cap_; }
+
+bluetooth::shim::IPage* TestStack::GetPage() { return nullptr; }
diff --git a/main/shim/test_stack.h b/main/shim/test_stack.h
new file mode 100644
index 000000000..9f90199e1
--- /dev/null
+++ b/main/shim/test_stack.h
@@ -0,0 +1,66 @@
+/*
+ * 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 <cstdint>
+#include <future>
+
+#include "gd/shim/only_include_this_file_into_legacy_stack___ever.h"
+#include "main/shim/entry.h"
+
+class TestGdShimL2cap : public bluetooth::shim::IL2cap {
+ public:
+ uint16_t cid_{0};
+ bool write_success_{false};
+ bool is_congested_{false};
+ uint8_t* data_buffer_{nullptr};
+ size_t data_buffer_size_{0};
+
+ void RegisterService(uint16_t psm,
+ bluetooth::shim::ConnectionOpenCallback on_open,
+ std::promise<void> completed) override;
+ void UnregisterService(uint16_t psm);
+ void CreateConnection(uint16_t psm, const std::string address,
+ std::promise<uint16_t> completed) override;
+ void CloseConnection(uint16_t cid);
+ void SetReadDataReadyCallback(
+ uint16_t cid,
+ bluetooth::shim::ReadDataReadyCallback on_data_ready) override;
+ void SetConnectionClosedCallback(
+ uint16_t cid,
+ bluetooth::shim::ConnectionClosedCallback on_closed) override;
+ bool Write(uint16_t cid, const uint8_t* data, size_t len) override;
+ bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
+ bool WriteNonFlushable(uint16_t cid, const uint8_t* data,
+ size_t len) override;
+ bool IsCongested(uint16_t cid) override;
+};
+
+class TestStack : public bluetooth::shim::IStack {
+ public:
+ TestStack() = default;
+
+ bluetooth::shim::IController* GetController();
+ bluetooth::shim::IConnectability* GetConnectability();
+ bluetooth::shim::IDiscoverability* GetDiscoverability();
+ bluetooth::shim::IHciLayer* GetHciLayer();
+ bluetooth::shim::IInquiry* GetInquiry();
+ bluetooth::shim::IL2cap* GetL2cap();
+ bluetooth::shim::IPage* GetPage();
+
+ TestGdShimL2cap test_l2cap_;
+
+ void Start();
+ void Stop();
+};
diff --git a/profile/avrcp/Android.bp b/profile/avrcp/Android.bp
index d73a5fb91..515f513e1 100644
--- a/profile/avrcp/Android.bp
+++ b/profile/avrcp/Android.bp
@@ -62,3 +62,35 @@ cc_test {
cflags: ["-DBUILDCFG"],
}
+
+cc_fuzz {
+ name: "avrcp_device_fuzz",
+ host_supported: true,
+ defaults: [
+ "fluoride_defaults_fuzzable",
+ ],
+ srcs: [
+ "tests/avrcp_device_fuzz/avrcp_device_fuzz.cc",
+ ],
+ include_dirs: [
+ "system/bt",
+ "system/bt/packet/tests",
+ "system/bt/btcore/include",
+ "system/bt/internal_include",
+ "system/bt/stack/include",
+ ],
+ static_libs: [
+ "avrcp-target-service",
+ "lib-bt-packets",
+ "libbase",
+ "libchrome",
+ "libcutils",
+ "libevent",
+ "liblog",
+ "libstatslog",
+ ],
+ header_libs: ["libbluetooth_headers"],
+ corpus: [
+ "tests/avrcp_device_fuzz/corpus/*",
+ ],
+}
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc b/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc
new file mode 100644
index 000000000..24a794dfb
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc
@@ -0,0 +1,86 @@
+#include <cstddef>
+#include <cstdint>
+
+#include "avrcp_packet.h"
+#include "device.h"
+#include "packet_test_helper.h"
+#include "stack_config.h"
+
+namespace bluetooth {
+namespace avrcp {
+class FakeMediaInterface : public MediaInterface {
+ public:
+ virtual void SendKeyEvent(uint8_t key, KeyState state) {}
+ using SongInfoCallback = base::Callback<void(SongInfo)>;
+ virtual void GetSongInfo(SongInfoCallback info_cb) {}
+ using PlayStatusCallback = base::Callback<void(PlayStatus)>;
+ virtual void GetPlayStatus(PlayStatusCallback status_cb) {}
+ using NowPlayingCallback =
+ base::Callback<void(std::string, std::vector<SongInfo>)>;
+ virtual void GetNowPlayingList(NowPlayingCallback now_playing_cb) {}
+ using MediaListCallback =
+ base::Callback<void(uint16_t curr_player, std::vector<MediaPlayerInfo>)>;
+ virtual void GetMediaPlayerList(MediaListCallback list_cb) {}
+ using FolderItemsCallback = base::Callback<void(std::vector<ListItem>)>;
+ virtual void GetFolderItems(uint16_t player_id, std::string media_id,
+ FolderItemsCallback folder_cb) {}
+ using SetBrowsedPlayerCallback = base::Callback<void(
+ bool success, std::string root_id, uint32_t num_items)>;
+ virtual void SetBrowsedPlayer(uint16_t player_id,
+ SetBrowsedPlayerCallback browse_cb) {}
+ virtual void PlayItem(uint16_t player_id, bool now_playing,
+ std::string media_id) {}
+ virtual void SetActiveDevice(const RawAddress& address) {}
+ virtual void RegisterUpdateCallback(MediaCallbacks* callback) {}
+ virtual void UnregisterUpdateCallback(MediaCallbacks* callback) {}
+};
+
+class FakeVolumeInterface : public VolumeInterface {
+ public:
+ virtual void DeviceConnected(const RawAddress& bdaddr) {}
+ virtual void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) {}
+ virtual void DeviceDisconnected(const RawAddress& bdaddr) {}
+ virtual void SetVolume(int8_t volume) {}
+};
+
+class FakeA2dpInterface : public A2dpInterface {
+ public:
+ virtual RawAddress active_peer() { return RawAddress(); }
+ virtual bool is_peer_in_silence_mode(const RawAddress& peer_address) {
+ return false;
+ }
+};
+
+bool get_pts_avrcp_test(void) { return false; }
+
+const stack_config_t interface = {
+ nullptr, get_pts_avrcp_test, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr};
+
+void Callback(uint8_t, bool, std::unique_ptr<::bluetooth::PacketBuilder>) {}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
+ FakeMediaInterface fmi;
+ FakeVolumeInterface fvi;
+ FakeA2dpInterface fai;
+
+ std::vector<uint8_t> Packet(Data, Data + Size);
+ Device device(RawAddress::kAny, true,
+ base::Bind([](uint8_t, bool,
+ std::unique_ptr<::bluetooth::PacketBuilder>) {}),
+ 0xFFFF, 0xFFFF);
+ device.RegisterInterfaces(&fmi, &fai, &fvi);
+
+ auto browse_request = TestPacketType<BrowsePacket>::Make(Packet);
+ device.BrowseMessageReceived(1, browse_request);
+
+ auto avrcp_request = TestPacketType<avrcp::Packet>::Make(Packet);
+ device.MessageReceived(1, avrcp_request);
+ return 0;
+}
+} // namespace avrcp
+} // namespace bluetooth
+
+const stack_config_t* stack_config_get_interface(void) {
+ return &bluetooth::avrcp::interface;
+} \ No newline at end of file
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_error_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_error_response
new file mode 100644
index 000000000..f5f982ce9
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_error_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_request
new file mode 100644
index 000000000..581327a4e
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_response
new file mode 100644
index 000000000..10c757667
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_up_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_up_request
new file mode 100644
index 000000000..a2226572d
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/change_path_up_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_play_pos_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_play_pos_notification
new file mode 100644
index 000000000..6ee7661bd
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_play_pos_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_volume_changed_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_volume_changed_notification
new file mode 100644
index 000000000..31d50fb54
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/changed_volume_changed_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/general_reject_invalid_command_packet b/profile/avrcp/tests/avrcp_device_fuzz/corpus/general_reject_invalid_command_packet
new file mode 100644
index 000000000..83fa4271f
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/general_reject_invalid_command_packet
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request
new file mode 100644
index 000000000..3968c03c8
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_company_id b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_company_id
new file mode 100644
index 000000000..f3966ed8b
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_company_id
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_unknown b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_unknown
new file mode 100644
index 000000000..eada547a4
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_request_unknown
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_company_id b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_company_id
new file mode 100644
index 000000000..21889cafe
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_company_id
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_events_supported b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_events_supported
new file mode 100644
index 000000000..d2cf8a8f0
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_capabilities_response_events_supported
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_full b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_full
new file mode 100644
index 000000000..d79c1d3bf
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_full
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_partial b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_partial
new file mode 100644
index 000000000..c37c9b696
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_element_attributes_request_partial
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_elements_attributes_response_full b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_elements_attributes_response_full
new file mode 100644
index 000000000..2e63febb8
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_elements_attributes_response_full
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_error_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_error_response
new file mode 100644
index 000000000..a09361bff
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_error_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_folder_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_folder_response
new file mode 100644
index 000000000..f58889a51
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_folder_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_media_player_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_media_player_response
new file mode 100644
index 000000000..ed25c8c1d
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_media_player_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request
new file mode 100644
index 000000000..098fa05d4
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_no_attrs b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_no_attrs
new file mode 100644
index 000000000..7e27ff9b4
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_no_attrs
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_now_playing b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_now_playing
new file mode 100644
index 000000000..9eaa35594
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_now_playing
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_title b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_title
new file mode 100644
index 000000000..0108fc760
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_title
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_vfs b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_vfs
new file mode 100644
index 000000000..e8cc8675a
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_request_vfs
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_song_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_song_response
new file mode 100644
index 000000000..f7472e05d
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_folder_items_song_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes
new file mode 100644
index 000000000..7d706b8f0
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes_invalid b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes_invalid
new file mode 100644
index 000000000..d55d0c4cc
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_request_all_attributes_invalid
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_song_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_song_response
new file mode 100644
index 000000000..3553664b7
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_item_attributes_song_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_request
new file mode 100644
index 000000000..2311a4775
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_response
new file mode 100644
index 000000000..240136fae
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_play_status_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_media_players b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_media_players
new file mode 100644
index 000000000..a5b85b78c
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_media_players
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_now_playing b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_now_playing
new file mode 100644
index 000000000..a4a6654bd
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_now_playing
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_vfs b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_vfs
new file mode 100644
index 000000000..0f9ad75e8
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_request_vfs
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_response
new file mode 100644
index 000000000..742da96da
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/get_total_number_of_items_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_addressed_player_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_addressed_player_notification
new file mode 100644
index 000000000..2f6044b3d
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_addressed_player_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_available_players_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_available_players_notification
new file mode 100644
index 000000000..b643cf47e
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_available_players_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_now_playing_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_now_playing_notification
new file mode 100644
index 000000000..ea6675ea3
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_now_playing_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_play_status_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_play_status_notification
new file mode 100644
index 000000000..0fb233db6
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_play_status_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_track_changed_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_track_changed_notification
new file mode 100644
index 000000000..b23cf6eb6
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_track_changed_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_uids_notificaiton b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_uids_notificaiton
new file mode 100644
index 000000000..cac9b4ab4
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_uids_notificaiton
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_volume_changed_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_volume_changed_notification
new file mode 100644
index 000000000..101bae681
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/interim_volume_changed_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_pushed b/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_pushed
new file mode 100644
index 000000000..9e002d211
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_pushed
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_released b/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_released
new file mode 100644
index 000000000..5c100e85e
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/pass_through_command_play_released
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_request
new file mode 100644
index 000000000..538a7c046
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_response
new file mode 100644
index 000000000..1180bcc19
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/play_item_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_notification_invalid b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_notification_invalid
new file mode 100644
index 000000000..2a213f0f2
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_notification_invalid
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_play_status_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_play_status_notification
new file mode 100644
index 000000000..fa40de4f0
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_play_status_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_volume_changed_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_volume_changed_notification
new file mode 100644
index 000000000..3e7209b37
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/register_volume_changed_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/reject_player_app_settings_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/reject_player_app_settings_response
new file mode 100644
index 000000000..82cc04731
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/reject_player_app_settings_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/rejected_volume_changed_notification b/profile/avrcp/tests/avrcp_device_fuzz/corpus/rejected_volume_changed_notification
new file mode 100644
index 000000000..5119a2d73
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/rejected_volume_changed_notification
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_request
new file mode 100644
index 000000000..5403b843d
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_response
new file mode 100644
index 000000000..b30cde20f
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_absolute_volume_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_id_1_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_id_1_request
new file mode 100644
index 000000000..ebe224eba
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_id_1_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_request
new file mode 100644
index 000000000..a38cfb7ff
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_response
new file mode 100644
index 000000000..42305244c
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_addressed_player_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_request
new file mode 100644
index 000000000..667137b52
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_response b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_response
new file mode 100644
index 000000000..c3a3c9380
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/set_browsed_player_response
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_browse_packet b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_browse_packet
new file mode 100644
index 000000000..b866ef0f3
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_browse_packet
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_change_path_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_change_path_request
new file mode 100644
index 000000000..365d337c9
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_change_path_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_capabilities_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_capabilities_request
new file mode 100644
index 000000000..c7c5b3372
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_capabilities_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_element_attributes_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_element_attributes_request
new file mode 100644
index 000000000..102d788c6
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_element_attributes_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_folder_items_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_folder_items_request
new file mode 100644
index 000000000..4ab0aa80b
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_folder_items_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_item_attributes_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_item_attributes_request
new file mode 100644
index 000000000..746755510
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_item_attributes_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_total_number_of_items_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_total_number_of_items_request
new file mode 100644
index 000000000..bc634e2b3
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_get_total_number_of_items_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_play_item_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_play_item_request
new file mode 100644
index 000000000..a138dc490
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_play_item_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_set_addressed_player_request b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_set_addressed_player_request
new file mode 100644
index 000000000..4872d6b05
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_set_addressed_player_request
Binary files differ
diff --git a/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_vendor_packet b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_vendor_packet
new file mode 100644
index 000000000..0c2a66e27
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_fuzz/corpus/short_vendor_packet
Binary files differ
diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc
index 868a2a440..8f8e49794 100644
--- a/stack/btm/btm_acl.cc
+++ b/stack/btm/btm_acl.cc
@@ -50,6 +50,7 @@
#include "device/include/interop.h"
#include "hcidefs.h"
#include "hcimsgs.h"
+#include "log/log.h"
#include "l2c_int.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -1084,7 +1085,7 @@ void btm_read_remote_features_complete(uint8_t* p) {
* Returns void
*
******************************************************************************/
-void btm_read_remote_ext_features_complete(uint8_t* p) {
+void btm_read_remote_ext_features_complete(uint8_t* p, uint8_t evt_len) {
tACL_CONN* p_acl_cb;
uint8_t page_num, max_page;
uint16_t handle;
@@ -1092,6 +1093,14 @@ void btm_read_remote_ext_features_complete(uint8_t* p) {
BTM_TRACE_DEBUG("btm_read_remote_ext_features_complete");
+ if (evt_len < HCI_EXT_FEATURES_SUCCESS_EVT_LEN) {
+ android_errorWriteLog(0x534e4554, "141552859");
+ BTM_TRACE_ERROR(
+ "btm_read_remote_ext_features_complete evt length too short. length=%d",
+ evt_len);
+ return;
+ }
+
++p;
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT8(page_num, p);
@@ -1111,6 +1120,13 @@ void btm_read_remote_ext_features_complete(uint8_t* p) {
return;
}
+ if (page_num > max_page) {
+ android_errorWriteLog(0x534e4554, "141552859");
+ BTM_TRACE_ERROR("btm_read_remote_ext_features_complete num_page=%d invalid",
+ page_num);
+ return;
+ }
+
p_acl_cb = &btm_cb.acl_db[acl_idx];
/* Copy the received features page */
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 6b80717c0..ee1d6554a 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -119,7 +119,7 @@ extern uint16_t btm_get_acl_disc_reason_code(void);
extern tBTM_STATUS btm_remove_acl(const RawAddress& bd_addr,
tBT_TRANSPORT transport);
extern void btm_read_remote_features_complete(uint8_t* p);
-extern void btm_read_remote_ext_features_complete(uint8_t* p);
+extern void btm_read_remote_ext_features_complete(uint8_t* p, uint8_t evt_len);
extern void btm_read_remote_ext_features_failed(uint8_t status,
uint16_t handle);
extern void btm_read_remote_version_complete(uint8_t* p);
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index 2035cc676..17fde3bfe 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -76,7 +76,8 @@ static void btu_hcif_authentication_comp_evt(uint8_t* p);
static void btu_hcif_rmt_name_request_comp_evt(uint8_t* p, uint16_t evt_len);
static void btu_hcif_encryption_change_evt(uint8_t* p);
static void btu_hcif_read_rmt_features_comp_evt(uint8_t* p);
-static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p);
+static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
+ uint8_t evt_len);
static void btu_hcif_read_rmt_version_comp_evt(uint8_t* p);
static void btu_hcif_qos_setup_comp_evt(uint8_t* p);
static void btu_hcif_command_complete_evt(BT_HDR* response, void* context);
@@ -296,7 +297,7 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) {
btu_hcif_read_rmt_features_comp_evt(p);
break;
case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
- btu_hcif_read_rmt_ext_features_comp_evt(p);
+ btu_hcif_read_rmt_ext_features_comp_evt(p, hci_evt_len);
break;
case HCI_READ_RMT_VERSION_COMP_EVT:
btu_hcif_read_rmt_version_comp_evt(p);
@@ -1212,7 +1213,8 @@ static void btu_hcif_read_rmt_features_comp_evt(uint8_t* p) {
* Returns void
*
******************************************************************************/
-static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p) {
+static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p,
+ uint8_t evt_len) {
uint8_t* p_cur = p;
uint8_t status;
uint16_t handle;
@@ -1220,7 +1222,7 @@ static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p) {
STREAM_TO_UINT8(status, p_cur);
if (status == HCI_SUCCESS)
- btm_read_remote_ext_features_complete(p);
+ btm_read_remote_ext_features_complete(p, evt_len);
else {
STREAM_TO_UINT16(handle, p_cur);
btm_read_remote_ext_features_failed(status, handle);
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 22df8af3b..088f2b36a 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -1323,6 +1323,8 @@ typedef struct {
#define HCI_FEATURE_BYTES_PER_PAGE 8
+#define HCI_EXT_FEATURES_SUCCESS_EVT_LEN 13
+
#define HCI_FEATURES_KNOWN(x) \
(((x)[0] | (x)[1] | (x)[2] | (x)[3] | (x)[4] | (x)[5] | (x)[6] | (x)[7]) != 0)
diff --git a/test/rootcanal/Android.bp b/test/rootcanal/Android.bp
index 3a1871bae..206f3631f 100644
--- a/test/rootcanal/Android.bp
+++ b/test/rootcanal/Android.bp
@@ -39,9 +39,6 @@ cc_binary {
"-Werror",
"-DHAS_NO_BDROID_BUILDCFG",
],
- generated_headers: [
- "RootCanalGeneratedPackets_h",
- ],
static_libs: [
"android.hardware.bluetooth-async",
"android.hardware.bluetooth-hci",
@@ -82,9 +79,6 @@ cc_library_shared {
"-Werror",
"-DHAS_NO_BDROID_BUILDCFG",
],
- generated_headers: [
- "RootCanalGeneratedPackets_h",
- ],
static_libs: [
"android.hardware.bluetooth-async",
"android.hardware.bluetooth-hci",
diff --git a/types/class_of_device.h b/types/class_of_device.h
index 4c37ebf26..8c2ab37e8 100644
--- a/types/class_of_device.h
+++ b/types/class_of_device.h
@@ -20,9 +20,6 @@
#include <string>
-namespace bluetooth {
-namespace types {
-
/** Bluetooth Class of Device */
class ClassOfDevice final {
public:
@@ -55,8 +52,3 @@ inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) {
os << c.ToString();
return os;
}
-
-} // namespace types
-} // namespace bluetooth
-
-using ::bluetooth::types::ClassOfDevice; // TODO, remove \ No newline at end of file
diff --git a/vendor_libs/test_vendor_lib/Android.bp b/vendor_libs/test_vendor_lib/Android.bp
index d53f20190..d4d554d95 100644
--- a/vendor_libs/test_vendor_lib/Android.bp
+++ b/vendor_libs/test_vendor_lib/Android.bp
@@ -35,7 +35,6 @@ cc_library_static {
"model/setup/test_channel_transport.cc",
"model/setup/test_command_handler.cc",
"model/setup/test_model.cc",
- ":BluetoothPacketSources",
],
cflags: [
"-fvisibility=hidden",
@@ -48,9 +47,6 @@ cc_library_static {
"include",
".",
],
- generated_headers: [
- "RootCanalGeneratedPackets_h",
- ],
include_dirs: [
"system/bt",
"system/bt/gd",
@@ -124,9 +120,6 @@ cc_test_host {
"system/bt",
"system/bt/gd",
],
- generated_headers: [
- "RootCanalGeneratedPackets_h",
- ],
shared_libs: [
"liblog",
],
@@ -135,17 +128,3 @@ cc_test_host {
"libbt-rootcanal",
],
}
-
-genrule {
- name: "RootCanalGeneratedPackets_h",
- tools: [
- "bluetooth_packetgen",
- ],
- cmd: "$(location bluetooth_packetgen) --root_namespace=model --include=system/bt/vendor_libs/test_vendor_lib --out=$(genDir) $(in)",
- srcs: [
- "packets/link_layer_packets.pdl",
- ],
- out: [
- "packets/link_layer_packets.h",
- ],
-}
diff --git a/vendor_libs/test_vendor_lib/include/link.h b/vendor_libs/test_vendor_lib/include/link.h
new file mode 100644
index 000000000..798bba7ac
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/link.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+namespace test_vendor_lib {
+class Link {
+ public:
+ static constexpr size_t kSizeBytes = sizeof(uint32_t);
+ static constexpr size_t kTypeBytes = sizeof(uint8_t);
+
+ enum class PacketType : uint8_t {
+ UNKNOWN,
+ ACL,
+ COMMAND,
+ DISCONNECT,
+ ENCRYPT_CONNECTION,
+ ENCRYPT_CONNECTION_RESPONSE,
+ EVENT,
+ INQUIRY,
+ INQUIRY_RESPONSE,
+ IO_CAPABILITY_REQUEST,
+ IO_CAPABILITY_RESPONSE,
+ IO_CAPABILITY_NEGATIVE_RESPONSE,
+ LE_ADVERTISEMENT,
+ LE_CONNECT,
+ LE_CONNECT_COMPLETE,
+ LE_SCAN,
+ LE_SCAN_RESPONSE,
+ PAGE,
+ PAGE_RESPONSE,
+ PAGE_REJECT,
+ RESPONSE,
+ SCO,
+ };
+};
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
index 21b6eb31b..6e9e77597 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
@@ -67,8 +67,7 @@ std::string DualModeController::GetTypeString() const {
return "Simulated Bluetooth Controller";
}
-void DualModeController::IncomingPacket(
- model::packets::LinkLayerPacketView incoming) {
+void DualModeController::IncomingPacket(packets::LinkLayerPacketView incoming) {
link_layer_controller_.IncomingPacket(incoming);
}
@@ -112,8 +111,7 @@ DualModeController::DualModeController(const std::string& properties_filename, u
properties_.SetAddress(public_address);
link_layer_controller_.RegisterRemoteChannel(
- [this](std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
- Phy::Type phy_type) {
+ [this](std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type) {
DualModeController::SendLinkLayerPacket(packet, phy_type);
});
@@ -209,6 +207,12 @@ DualModeController::DualModeController(const std::string& properties_filename, u
SET_HANDLER(OpCode::READ_REMOTE_VERSION_INFORMATION, HciReadRemoteVersionInformation);
SET_HANDLER(OpCode::LE_CONNECTION_UPDATE, HciLeConnectionUpdate);
SET_HANDLER(OpCode::LE_START_ENCRYPTION, HciLeStartEncryption);
+ SET_HANDLER(OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST,
+ HciLeAddDeviceToResolvingList);
+ SET_HANDLER(OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST,
+ HciLeRemoveDeviceFromResolvingList);
+ SET_HANDLER(OpCode::LE_CLEAR_RESOLVING_LIST, HciLeClearResolvingList);
+ SET_HANDLER(OpCode::LE_SET_PRIVACY_MODE, HciLeSetPrivacyMode);
// Testing Commands
SET_HANDLER(OpCode::READ_LOOPBACK_MODE, HciReadLoopbackMode);
SET_HANDLER(OpCode::WRITE_LOOPBACK_MODE, HciWriteLoopbackMode);
@@ -1085,6 +1089,70 @@ void DualModeController::HciLeRemoveDeviceFromWhiteList(packets::PacketView<true
SendCommandCompleteSuccess(OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST);
}
+void DualModeController::HciLeClearResolvingList(
+ packets::PacketView<true> args) {
+ ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
+ link_layer_controller_.LeResolvingListClear();
+ SendCommandCompleteSuccess(OpCode::LE_CLEAR_RESOLVING_LIST);
+}
+
+void DualModeController::HciLeAddDeviceToResolvingList(
+ packets::PacketView<true> args) {
+ ASSERT_LOG(args.size() == 39, "%s size=%zu", __func__, args.size());
+
+ if (link_layer_controller_.LeResolvingListFull()) {
+ SendCommandCompleteOnlyStatus(OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST,
+ hci::Status::MEMORY_CAPACITY_EXCEEDED);
+ return;
+ }
+ auto args_itr = args.begin();
+ uint8_t addr_type = args_itr.extract<uint8_t>();
+ Address address = args_itr.extract<Address>();
+ std::array<uint8_t, LinkLayerController::kIrk_size> peerIrk;
+ std::array<uint8_t, LinkLayerController::kIrk_size> localIrk;
+ for (size_t irk_ind = 0; irk_ind < LinkLayerController::kIrk_size;
+ irk_ind++) {
+ peerIrk[irk_ind] = args_itr.extract<uint8_t>();
+ }
+
+ for (size_t irk_ind = 0; irk_ind < LinkLayerController::kIrk_size;
+ irk_ind++) {
+ localIrk[irk_ind] = args_itr.extract<uint8_t>();
+ }
+
+ link_layer_controller_.LeResolvingListAddDevice(address, addr_type, peerIrk,
+ localIrk);
+ SendCommandCompleteSuccess(OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST);
+}
+
+void DualModeController::HciLeRemoveDeviceFromResolvingList(
+ packets::PacketView<true> args) {
+ ASSERT_LOG(args.size() == 7, "%s size=%zu", __func__, args.size());
+
+ auto args_itr = args.begin();
+ uint8_t addr_type = args_itr.extract<uint8_t>();
+ Address address = args_itr.extract<Address>();
+ link_layer_controller_.LeResolvingListRemoveDevice(address, addr_type);
+ SendCommandCompleteSuccess(OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST);
+}
+
+void DualModeController::HciLeSetPrivacyMode(packets::PacketView<true> args) {
+ ASSERT_LOG(args.size() == 8, "%s size=%zu", __func__, args.size());
+
+ auto args_itr = args.begin();
+ uint8_t peer_identity_address_type = args_itr.extract<uint8_t>();
+ Address peer_identity_address = args_itr.extract<Address>();
+ uint8_t privacy_mode = args_itr.extract<uint8_t>();
+
+ if (link_layer_controller_.LeResolvingListContainsDevice(
+ peer_identity_address, peer_identity_address_type)) {
+ link_layer_controller_.LeSetPrivacyMode(
+ peer_identity_address_type, peer_identity_address, privacy_mode);
+ }
+
+ SendCommandCompleteSuccess(OpCode::LE_SET_PRIVACY_MODE);
+}
+
/*
void DualModeController::HciLeReadRemoteUsedFeaturesRsp(uint16_t handle,
uint64_t features) {
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
index 865b446b3..cd3dcfc67 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
@@ -60,8 +60,7 @@ class DualModeController : public Device {
virtual std::string GetTypeString() const override;
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView incoming) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView incoming) override;
virtual void TimerTick() override;
@@ -380,6 +379,18 @@ class DualModeController : public Device {
// 7.8.27
void HciLeReadSupportedStates(packets::PacketView<true> args);
+ // 7.8.38
+ void HciLeAddDeviceToResolvingList(packets::PacketView<true> args);
+
+ // 7.8.39
+ void HciLeRemoveDeviceFromResolvingList(packets::PacketView<true> args);
+
+ // 7.8.40
+ void HciLeClearResolvingList(packets::PacketView<true> args);
+
+ // 7.8.77
+ void HciLeSetPrivacyMode(packets::PacketView<true> args);
+
// Vendor-specific Commands
void HciLeVendorSleepMode(packets::PacketView<true> args);
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index 3ddb19bbc..93b06ddd8 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -22,9 +22,20 @@
#include "packets/hci/command_packet_view.h"
#include "packets/hci/event_packet_builder.h"
#include "packets/hci/sco_packet_builder.h"
-
-#include "packet/raw_builder.h"
-#include "packets/link_layer_packets.h"
+#include "packets/link_layer/command_builder.h"
+#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/disconnect_view.h"
+#include "packets/link_layer/encrypt_connection_view.h"
+#include "packets/link_layer/inquiry_response_view.h"
+#include "packets/link_layer/inquiry_view.h"
+#include "packets/link_layer/io_capability_view.h"
+#include "packets/link_layer/le_advertisement_view.h"
+#include "packets/link_layer/le_connect_complete_view.h"
+#include "packets/link_layer/le_connect_view.h"
+#include "packets/link_layer/page_reject_view.h"
+#include "packets/link_layer/page_response_view.h"
+#include "packets/link_layer/page_view.h"
+#include "packets/link_layer/response_view.h"
using std::vector;
using namespace std::chrono;
@@ -42,42 +53,25 @@ static uint8_t GetRssi() {
return -(rssi);
}
-void LinkLayerController::SendLeLinkLayerPacket(
- std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet) {
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> shared_packet =
- std::move(packet);
- ScheduleTask(milliseconds(50), [this, shared_packet]() {
- send_to_remote_(std::move(shared_packet), Phy::Type::LOW_ENERGY);
- });
+void LinkLayerController::SendLeLinkLayerPacket(std::shared_ptr<LinkLayerPacketBuilder> packet) {
+ ScheduleTask(milliseconds(50), [this, packet]() { send_to_remote_(packet, Phy::Type::LOW_ENERGY); });
}
-void LinkLayerController::SendLinkLayerPacket(
- std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet) {
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> shared_packet =
- std::move(packet);
- ScheduleTask(milliseconds(50), [this, shared_packet]() {
- send_to_remote_(std::move(shared_packet), Phy::Type::BR_EDR);
- });
+void LinkLayerController::SendLinkLayerPacket(std::shared_ptr<LinkLayerPacketBuilder> packet) {
+ ScheduleTask(milliseconds(50), [this, packet]() { send_to_remote_(packet, Phy::Type::BR_EDR); });
}
hci::Status LinkLayerController::SendCommandToRemoteByAddress(hci::OpCode opcode, PacketView<true> args,
const Address& remote, bool use_public_address) {
+ std::shared_ptr<LinkLayerPacketBuilder> command;
Address local_address;
if (use_public_address) {
local_address = properties_.GetAddress();
} else {
local_address = properties_.GetLeAddress();
}
-
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- std::vector<uint8_t> payload_bytes(args.begin(), args.end());
- raw_builder_ptr->AddOctets2(static_cast<uint16_t>(opcode));
- raw_builder_ptr->AddOctets(payload_bytes);
-
- auto command = model::packets::CommandBuilder::Create(
- local_address, remote, std::move(raw_builder_ptr));
-
+ command = LinkLayerPacketBuilder::WrapCommand(CommandBuilder::Create(static_cast<uint16_t>(opcode), args),
+ local_address, remote);
SendLinkLayerPacket(std::move(command));
return hci::Status::SUCCESS;
}
@@ -98,11 +92,15 @@ hci::Status LinkLayerController::SendAclToRemote(AclPacketView acl_packet) {
return hci::Status::UNKNOWN_CONNECTION;
}
+ std::unique_ptr<ViewForwarderBuilder> acl_builder = ViewForwarderBuilder::Create(acl_packet);
+
Address my_address = properties_.GetAddress();
Address destination = connections_.GetAddress(handle);
if (connections_.GetOwnAddressType(handle) != 0) { // If it's not public, it must be LE
my_address = properties_.GetLeAddress();
}
+ std::shared_ptr<LinkLayerPacketBuilder> acl =
+ LinkLayerPacketBuilder::WrapAcl(std::move(acl_builder), my_address, destination);
LOG_INFO("%s(%s): handle 0x%x size %d", __func__, properties_.GetAddress().ToString().c_str(), handle,
static_cast<int>(acl_packet.size()));
@@ -110,32 +108,11 @@ hci::Status LinkLayerController::SendAclToRemote(AclPacketView acl_packet) {
ScheduleTask(milliseconds(5), [this, handle]() {
send_event_(EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, 1)->ToVector());
});
-
- auto acl_payload = acl_packet.GetPayload();
-
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- std::vector<uint8_t> payload_bytes(acl_payload.begin(), acl_payload.end());
-
- uint16_t first_two_bytes =
- static_cast<uint16_t>(acl_packet.GetHandle()) +
- (static_cast<uint16_t>(acl_packet.GetPacketBoundaryFlags()) << 12) +
- (static_cast<uint16_t>(acl_packet.GetBroadcastFlags()) << 14);
- raw_builder_ptr->AddOctets2(first_two_bytes);
- raw_builder_ptr->AddOctets2(static_cast<uint16_t>(payload_bytes.size()));
- raw_builder_ptr->AddOctets(payload_bytes);
-
- auto acl = model::packets::AclPacketBuilder::Create(
- my_address, destination, std::move(raw_builder_ptr));
-
- SendLinkLayerPacket(std::move(acl));
+ SendLinkLayerPacket(acl);
return hci::Status::SUCCESS;
}
-void LinkLayerController::IncomingPacket(
- model::packets::LinkLayerPacketView incoming) {
- ASSERT(incoming.IsValid());
-
+void LinkLayerController::IncomingPacket(LinkLayerPacketView incoming) {
// TODO: Resolvable private addresses?
if (incoming.GetDestinationAddress() != properties_.GetAddress() &&
incoming.GetDestinationAddress() != properties_.GetLeAddress() &&
@@ -145,67 +122,70 @@ void LinkLayerController::IncomingPacket(
}
switch (incoming.GetType()) {
- case model::packets::PacketType::ACL:
+ case Link::PacketType::ACL:
IncomingAclPacket(incoming);
break;
- case model::packets::PacketType::COMMAND:
+ case Link::PacketType::COMMAND:
IncomingCommandPacket(incoming);
break;
- case model::packets::PacketType::DISCONNECT:
+ case Link::PacketType::DISCONNECT:
IncomingDisconnectPacket(incoming);
break;
- case model::packets::PacketType::ENCRYPT_CONNECTION:
+ case Link::PacketType::ENCRYPT_CONNECTION:
IncomingEncryptConnection(incoming);
break;
- case model::packets::PacketType::ENCRYPT_CONNECTION_RESPONSE:
+ case Link::PacketType::ENCRYPT_CONNECTION_RESPONSE:
IncomingEncryptConnectionResponse(incoming);
break;
- case model::packets::PacketType::INQUIRY:
+ case Link::PacketType::INQUIRY:
if (inquiry_scans_enabled_) {
IncomingInquiryPacket(incoming);
}
break;
- case model::packets::PacketType::INQUIRY_RESPONSE:
+ case Link::PacketType::INQUIRY_RESPONSE:
IncomingInquiryResponsePacket(incoming);
break;
- case model::packets::PacketType::IO_CAPABILITY_REQUEST:
+ case Link::PacketType::IO_CAPABILITY_REQUEST:
IncomingIoCapabilityRequestPacket(incoming);
break;
- case model::packets::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE:
+ case Link::PacketType::IO_CAPABILITY_RESPONSE:
+ IncomingIoCapabilityResponsePacket(incoming);
+ break;
+ case Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE:
IncomingIoCapabilityNegativeResponsePacket(incoming);
break;
- case model::packets::PacketType::LE_ADVERTISEMENT:
+ case Link::PacketType::LE_ADVERTISEMENT:
if (le_scan_enable_ || le_connect_) {
IncomingLeAdvertisementPacket(incoming);
}
break;
- case model::packets::PacketType::LE_CONNECT:
+ case Link::PacketType::LE_CONNECT:
IncomingLeConnectPacket(incoming);
break;
- case model::packets::PacketType::LE_CONNECT_COMPLETE:
+ case Link::PacketType::LE_CONNECT_COMPLETE:
IncomingLeConnectCompletePacket(incoming);
break;
- case model::packets::PacketType::LE_SCAN:
+ case Link::PacketType::LE_SCAN:
// TODO: Check Advertising flags and see if we are scannable.
IncomingLeScanPacket(incoming);
break;
- case model::packets::PacketType::LE_SCAN_RESPONSE:
+ case Link::PacketType::LE_SCAN_RESPONSE:
if (le_scan_enable_ && le_scan_type_ == 1) {
IncomingLeScanResponsePacket(incoming);
}
break;
- case model::packets::PacketType::PAGE:
+ case Link::PacketType::PAGE:
if (page_scans_enabled_) {
IncomingPagePacket(incoming);
}
break;
- case model::packets::PacketType::PAGE_RESPONSE:
- IncomingPageResponsePacket(incoming);
- break;
- case model::packets::PacketType::PAGE_REJECT:
+ case Link::PacketType::PAGE_REJECT:
IncomingPageRejectPacket(incoming);
break;
- case model::packets::PacketType::RESPONSE:
+ case Link::PacketType::PAGE_RESPONSE:
+ IncomingPageResponsePacket(incoming);
+ break;
+ case Link::PacketType::RESPONSE:
IncomingResponsePacket(incoming);
break;
default:
@@ -213,40 +193,26 @@ void LinkLayerController::IncomingPacket(
}
}
-void LinkLayerController::IncomingAclPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingAclPacket(LinkLayerPacketView incoming) {
LOG_INFO("Acl Packet %s -> %s", incoming.GetSourceAddress().ToString().c_str(),
incoming.GetDestinationAddress().ToString().c_str());
-
- auto acl = model::packets::AclPacketView::Create(incoming);
- ASSERT(acl.IsValid());
- auto payload = acl.GetPayload();
- std::shared_ptr<std::vector<uint8_t>> payload_bytes =
- std::make_shared<std::vector<uint8_t>>(payload.begin(), payload.end());
-
- AclPacketView acl_view = AclPacketView::Create(payload_bytes);
+ AclPacketView acl_view = AclPacketView::Create(incoming.GetPayload());
LOG_INFO("%s: remote handle 0x%x size %d", __func__, acl_view.GetHandle(), static_cast<int>(acl_view.size()));
uint16_t local_handle = connections_.GetHandle(incoming.GetSourceAddress());
LOG_INFO("%s: local handle 0x%x", __func__, local_handle);
acl::PacketBoundaryFlagsType boundary_flags = acl_view.GetPacketBoundaryFlags();
acl::BroadcastFlagsType broadcast_flags = acl_view.GetBroadcastFlags();
- std::unique_ptr<RawBuilder> builder = std::make_unique<RawBuilder>();
- std::vector<uint8_t> raw_data(acl_view.GetPayload().begin(),
- acl_view.GetPayload().end());
- builder->AddOctets(raw_data);
+ std::unique_ptr<ViewForwarderBuilder> builder = ViewForwarderBuilder::Create(acl_view.GetPayload());
send_acl_(AclPacketBuilder::Create(local_handle, boundary_flags, broadcast_flags, std::move(builder))->ToVector());
}
-void LinkLayerController::IncomingCommandPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingCommandPacket(LinkLayerPacketView incoming) {
// TODO: Check the destination address to see if this packet is for me.
- auto command = model::packets::CommandView::Create(incoming);
- ASSERT(command.IsValid());
-
- auto args = command.GetPayload().begin();
+ CommandView command = CommandView::GetCommand(incoming);
+ hci::OpCode opcode = static_cast<hci::OpCode>(command.GetOpcode());
+ auto args = command.GetData();
std::vector<uint64_t> response_data;
- hci::OpCode opcode = static_cast<hci::OpCode>(args.extract<uint16_t>());
switch (opcode) {
case (hci::OpCode::REMOTE_NAME_REQUEST): {
@@ -302,26 +268,14 @@ void LinkLayerController::IncomingCommandPacket(
LOG_INFO("Dropping unhandled command 0x%04x", static_cast<uint16_t>(opcode));
return;
}
-
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- for (uint64_t data : response_data) {
- raw_builder_ptr->AddOctets8(data);
- }
-
- auto response = model::packets::ResponseBuilder::Create(
- properties_.GetAddress(), incoming.GetSourceAddress(),
- static_cast<uint16_t>(opcode), std::move(raw_builder_ptr));
-
- SendLinkLayerPacket(std::move(response));
+ SendLinkLayerPacket(
+ LinkLayerPacketBuilder::WrapResponse(ResponseBuilder::Create(static_cast<uint16_t>(opcode), response_data),
+ properties_.GetAddress(), incoming.GetSourceAddress()));
}
-void LinkLayerController::IncomingDisconnectPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingDisconnectPacket(LinkLayerPacketView incoming) {
LOG_INFO("Disconnect Packet");
- auto disconnect = model::packets::DisconnectView::Create(incoming);
- ASSERT(disconnect.IsValid());
-
+ DisconnectView disconnect = DisconnectView::GetDisconnect(incoming);
Address peer = incoming.GetSourceAddress();
uint16_t handle = connections_.GetHandle(peer);
if (handle == acl::kReservedHandle) {
@@ -334,10 +288,8 @@ void LinkLayerController::IncomingDisconnectPacket(
ScheduleTask(milliseconds(20), [this, handle, reason]() { DisconnectCleanup(handle, reason); });
}
-void LinkLayerController::IncomingEncryptConnection(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingEncryptConnection(LinkLayerPacketView incoming) {
LOG_INFO("%s", __func__);
-
// TODO: Check keys
Address peer = incoming.GetSourceAddress();
uint16_t handle = connections_.GetHandle(peer);
@@ -346,13 +298,11 @@ void LinkLayerController::IncomingEncryptConnection(
return;
}
send_event_(EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, 1)->ToVector());
- auto response = model::packets::EncryptConnectionResponseBuilder::Create(
- properties_.GetAddress(), peer, security_manager_.GetKey(peer));
- SendLinkLayerPacket(std::move(response));
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapEncryptConnectionResponse(
+ EncryptConnectionBuilder::Create(security_manager_.GetKey(peer)), properties_.GetAddress(), peer));
}
-void LinkLayerController::IncomingEncryptConnectionResponse(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingEncryptConnectionResponse(LinkLayerPacketView incoming) {
LOG_INFO("%s", __func__);
// TODO: Check keys
uint16_t handle = connections_.GetHandle(incoming.GetSourceAddress());
@@ -363,119 +313,86 @@ void LinkLayerController::IncomingEncryptConnectionResponse(
send_event_(EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, 1)->ToVector());
}
-void LinkLayerController::IncomingInquiryPacket(
- model::packets::LinkLayerPacketView incoming) {
- auto inquiry = model::packets::InquiryView::Create(incoming);
- ASSERT(inquiry.IsValid());
-
- Address peer = incoming.GetSourceAddress();
+void LinkLayerController::IncomingInquiryPacket(LinkLayerPacketView incoming) {
+ InquiryView inquiry = InquiryView::GetInquiry(incoming);
+ std::unique_ptr<InquiryResponseBuilder> inquiry_response;
+ switch (inquiry.GetType()) {
+ case (Inquiry::InquiryType::STANDARD):
+ inquiry_response = InquiryResponseBuilder::CreateStandard(
+ properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset());
+ break;
- switch (inquiry.GetInquiryType()) {
- case (model::packets::InquiryType::STANDARD): {
- auto inquiry_response = model::packets::InquiryResponseBuilder::Create(
- properties_.GetAddress(), peer,
- properties_.GetPageScanRepetitionMode(),
- properties_.GetClassOfDevice(), properties_.GetClockOffset());
- SendLinkLayerPacket(std::move(inquiry_response));
- } break;
- case (model::packets::InquiryType::RSSI): {
- auto inquiry_response =
- model::packets::InquiryResponseWithRssiBuilder::Create(
- properties_.GetAddress(), peer,
- properties_.GetPageScanRepetitionMode(),
- properties_.GetClassOfDevice(), properties_.GetClockOffset(),
- GetRssi());
- SendLinkLayerPacket(std::move(inquiry_response));
- } break;
- case (model::packets::InquiryType::EXTENDED): {
- auto inquiry_response =
- model::packets::ExtendedInquiryResponseBuilder::Create(
- properties_.GetAddress(), peer,
- properties_.GetPageScanRepetitionMode(),
- properties_.GetClassOfDevice(), properties_.GetClockOffset(),
- GetRssi(), properties_.GetExtendedInquiryData());
- SendLinkLayerPacket(std::move(inquiry_response));
+ case (Inquiry::InquiryType::RSSI):
+ inquiry_response =
+ InquiryResponseBuilder::CreateRssi(properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(),
+ properties_.GetClockOffset(), GetRssi());
+ break;
- } break;
+ case (Inquiry::InquiryType::EXTENDED):
+ inquiry_response = InquiryResponseBuilder::CreateExtended(
+ properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset(),
+ GetRssi(), properties_.GetExtendedInquiryData());
+ break;
default:
LOG_WARN("Unhandled Incoming Inquiry of type %d", static_cast<int>(inquiry.GetType()));
return;
}
- // TODO: Send an Inquiry Response Notification Event 7.7.74
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response), properties_.GetAddress(),
+ incoming.GetSourceAddress()));
+ // TODO: Send an Inquriy Response Notification Event 7.7.74
}
-void LinkLayerController::IncomingInquiryResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto basic_inquiry_response =
- model::packets::BasicInquiryResponseView::Create(incoming);
- ASSERT(basic_inquiry_response.IsValid());
+void LinkLayerController::IncomingInquiryResponsePacket(LinkLayerPacketView incoming) {
+ InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(incoming);
std::vector<uint8_t> eir;
- switch (basic_inquiry_response.GetInquiryType()) {
- case (model::packets::InquiryType::STANDARD): {
+ switch (inquiry_response.GetType()) {
+ case (Inquiry::InquiryType::STANDARD): {
LOG_WARN("Incoming Standard Inquiry Response");
// TODO: Support multiple inquiries in the same packet.
- auto inquiry_response =
- model::packets::InquiryResponseView::Create(basic_inquiry_response);
- ASSERT(inquiry_response.IsValid());
- std::unique_ptr<EventPacketBuilder> inquiry_result =
- EventPacketBuilder::CreateInquiryResultEvent();
- bool result_added = inquiry_result->AddInquiryResult(
- inquiry_response.GetSourceAddress(),
- inquiry_response.GetPageScanRepetitionMode(),
- inquiry_response.GetClassOfDevice(),
- inquiry_response.GetClockOffset());
- CHECK(result_added);
+ std::unique_ptr<EventPacketBuilder> inquiry_result = EventPacketBuilder::CreateInquiryResultEvent();
+ bool result_added =
+ inquiry_result->AddInquiryResult(incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+ inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset());
+ ASSERT(result_added);
send_event_(inquiry_result->ToVector());
} break;
- case (model::packets::InquiryType::RSSI): {
+ case (Inquiry::InquiryType::RSSI):
LOG_WARN("Incoming RSSI Inquiry Response");
- auto inquiry_response =
- model::packets::InquiryResponseWithRssiView::Create(
- basic_inquiry_response);
- ASSERT(inquiry_response.IsValid());
send_event_(EventPacketBuilder::CreateExtendedInquiryResultEvent(
- incoming.GetSourceAddress(),
- inquiry_response.GetPageScanRepetitionMode(),
- inquiry_response.GetClassOfDevice(),
- inquiry_response.GetClockOffset(),
- inquiry_response.GetRssi(), eir)
+ incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+ inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset(), GetRssi(), eir)
->ToVector());
- } break;
+ break;
- case (model::packets::InquiryType::EXTENDED): {
+ case (Inquiry::InquiryType::EXTENDED): {
LOG_WARN("Incoming Extended Inquiry Response");
- auto inquiry_response =
- model::packets::ExtendedInquiryResponseView::Create(
- basic_inquiry_response);
- ASSERT(inquiry_response.IsValid());
- eir = inquiry_response.GetExtendedData();
+ auto eir_itr = inquiry_response.GetExtendedData();
+ size_t eir_bytes = eir_itr.NumBytesRemaining();
+ LOG_WARN("Payload size = %d", static_cast<int>(eir_bytes));
+ for (size_t i = 0; i < eir_bytes; i++) {
+ eir.push_back(eir_itr.extract<uint8_t>());
+ }
send_event_(EventPacketBuilder::CreateExtendedInquiryResultEvent(
- incoming.GetSourceAddress(),
- inquiry_response.GetPageScanRepetitionMode(),
- inquiry_response.GetClassOfDevice(),
- inquiry_response.GetClockOffset(), GetRssi(), eir)
+ incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+ inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset(), GetRssi(), eir)
->ToVector());
} break;
default:
- LOG_WARN("Unhandled Incoming Inquiry Response of type %d",
- static_cast<int>(basic_inquiry_response.GetInquiryType()));
+ LOG_WARN("Unhandled Incoming Inquiry Response of type %d", static_cast<int>(inquiry_response.GetType()));
}
}
-void LinkLayerController::IncomingIoCapabilityRequestPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingIoCapabilityRequestPacket(LinkLayerPacketView incoming) {
LOG_DEBUG("%s", __func__);
if (!simple_pairing_mode_enabled_) {
LOG_WARN("%s: Only simple pairing mode is implemented", __func__);
return;
}
-
- auto request = model::packets::IoCapabilityRequestView::Create(incoming);
- ASSERT(request.IsValid());
-
+ auto request = IoCapabilityView::GetIoCapability(incoming);
Address peer = incoming.GetSourceAddress();
+
uint8_t io_capability = request.GetIoCapability();
uint8_t oob_data_present = request.GetOobDataPresent();
uint8_t authentication_requirements = request.GetAuthenticationRequirements();
@@ -497,38 +414,29 @@ void LinkLayerController::IncomingIoCapabilityRequestPacket(
StartSimplePairing(peer);
}
-void LinkLayerController::IncomingIoCapabilityResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingIoCapabilityResponsePacket(LinkLayerPacketView incoming) {
LOG_DEBUG("%s", __func__);
-
- auto response = model::packets::IoCapabilityResponseView::Create(incoming);
- ASSERT(response.IsValid());
-
+ auto response = IoCapabilityView::GetIoCapability(incoming);
Address peer = incoming.GetSourceAddress();
uint8_t io_capability = response.GetIoCapability();
uint8_t oob_data_present = response.GetOobDataPresent();
uint8_t authentication_requirements = response.GetAuthenticationRequirements();
- security_manager_.SetPeerIoCapability(peer, io_capability, oob_data_present,
- authentication_requirements);
+ security_manager_.SetPeerIoCapability(peer, io_capability, oob_data_present, authentication_requirements);
- send_event_(
- EventPacketBuilder::CreateIoCapabilityResponseEvent(
- peer, io_capability, oob_data_present, authentication_requirements)
- ->ToVector());
+ send_event_(EventPacketBuilder::CreateIoCapabilityResponseEvent(peer, io_capability, oob_data_present,
+ authentication_requirements)
+ ->ToVector());
PairingType pairing_type = security_manager_.GetSimplePairingType();
if (pairing_type != PairingType::INVALID) {
- ScheduleTask(milliseconds(5), [this, peer, pairing_type]() {
- AuthenticateRemoteStage1(peer, pairing_type);
- });
+ ScheduleTask(milliseconds(5), [this, peer, pairing_type]() { AuthenticateRemoteStage1(peer, pairing_type); });
} else {
LOG_INFO("%s: Security Manager returned INVALID", __func__);
}
}
-void LinkLayerController::IncomingIoCapabilityNegativeResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingIoCapabilityNegativeResponsePacket(LinkLayerPacketView incoming) {
LOG_DEBUG("%s", __func__);
Address peer = incoming.GetSourceAddress();
@@ -537,21 +445,21 @@ void LinkLayerController::IncomingIoCapabilityNegativeResponsePacket(
security_manager_.InvalidateIoCapabilities();
}
-void LinkLayerController::IncomingLeAdvertisementPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingLeAdvertisementPacket(LinkLayerPacketView incoming) {
// TODO: Handle multiple advertisements per packet.
Address address = incoming.GetSourceAddress();
- auto advertisement = model::packets::LeAdvertisementView::Create(incoming);
- ASSERT(advertisement.IsValid());
- auto adv_type = static_cast<LeAdvertisement::AdvertisementType>(
- advertisement.GetAdvertisementType());
- auto address_type =
- static_cast<LeAdvertisement::AddressType>(advertisement.GetAddressType());
+ LeAdvertisementView advertisement = LeAdvertisementView::GetLeAdvertisementView(incoming);
+ LeAdvertisement::AdvertisementType adv_type = advertisement.GetAdvertisementType();
+ LeAdvertisement::AddressType address_type = advertisement.GetAddressType();
if (le_scan_enable_) {
- vector<uint8_t> ad = advertisement.GetData();
-
+ vector<uint8_t> ad;
+ auto itr = advertisement.GetData();
+ size_t ad_size = itr.NumBytesRemaining();
+ for (size_t i = 0; i < ad_size; i++) {
+ ad.push_back(itr.extract<uint8_t>());
+ }
std::unique_ptr<EventPacketBuilder> le_adverts = EventPacketBuilder::CreateLeAdvertisingReportEvent();
if (!le_adverts->AddLeAdvertisingReport(adv_type, address_type, address, ad, GetRssi())) {
@@ -563,9 +471,9 @@ void LinkLayerController::IncomingLeAdvertisementPacket(
// Active scanning
if (le_scan_enable_ && le_scan_type_ == 1) {
- auto to_send = model::packets::LeScanBuilder::Create(
- properties_.GetLeAddress(), address);
- SendLeLinkLayerPacket(std::move(to_send));
+ std::shared_ptr<LinkLayerPacketBuilder> to_send =
+ LinkLayerPacketBuilder::WrapLeScan(properties_.GetLeAddress(), address);
+ SendLeLinkLayerPacket(to_send);
}
// Connect
@@ -582,13 +490,11 @@ void LinkLayerController::IncomingLeAdvertisementPacket(
le_connect_ = false;
le_scan_enable_ = false;
- auto to_send = model::packets::LeConnectBuilder::Create(
- properties_.GetLeAddress(), incoming.GetSourceAddress(),
- le_connection_interval_min_, le_connection_interval_max_,
- le_connection_latency_, le_connection_supervision_timeout_,
- static_cast<uint8_t>(le_address_type_));
-
- SendLeLinkLayerPacket(std::move(to_send));
+ std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapLeConnect(
+ LeConnectBuilder::Create(le_connection_interval_min_, le_connection_interval_max_, le_connection_latency_,
+ le_connection_supervision_timeout_, static_cast<uint8_t>(le_address_type_)),
+ properties_.GetLeAddress(), incoming.GetSourceAddress());
+ SendLeLinkLayerPacket(to_send);
}
}
@@ -608,10 +514,8 @@ void LinkLayerController::HandleLeConnection(Address address, uint8_t address_ty
->ToVector());
}
-void LinkLayerController::IncomingLeConnectPacket(
- model::packets::LinkLayerPacketView incoming) {
- auto connect = model::packets::LeConnectView::Create(incoming);
- ASSERT(connect.IsValid());
+void LinkLayerController::IncomingLeConnectPacket(LinkLayerPacketView incoming) {
+ auto connect = LeConnectView::GetLeConnect(incoming);
uint16_t connection_interval = (connect.GetLeConnectionIntervalMax() + connect.GetLeConnectionIntervalMin()) / 2;
if (!connections_.CreatePendingLeConnection(incoming.GetSourceAddress(),
static_cast<uint8_t>(connect.GetAddressType()))) {
@@ -623,63 +527,54 @@ void LinkLayerController::IncomingLeConnectPacket(
static_cast<uint8_t>(properties_.GetLeAdvertisingOwnAddressType()),
static_cast<uint8_t>(hci::Role::SLAVE), connection_interval, connect.GetLeConnectionLatency(),
connect.GetLeConnectionSupervisionTimeout());
-
- auto to_send = model::packets::LeConnectCompleteBuilder::Create(
- incoming.GetDestinationAddress(), incoming.GetSourceAddress(),
- connection_interval, connect.GetLeConnectionLatency(),
- connect.GetLeConnectionSupervisionTimeout(),
- properties_.GetLeAdvertisingOwnAddressType());
- SendLeLinkLayerPacket(std::move(to_send));
+ std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapLeConnectComplete(
+ LeConnectCompleteBuilder::Create(connection_interval, connect.GetLeConnectionLatency(),
+ connect.GetLeConnectionSupervisionTimeout(),
+ properties_.GetLeAdvertisingOwnAddressType()),
+ incoming.GetDestinationAddress(), incoming.GetSourceAddress());
+ SendLeLinkLayerPacket(to_send);
}
-void LinkLayerController::IncomingLeConnectCompletePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto complete = model::packets::LeConnectCompleteView::Create(incoming);
- ASSERT(complete.IsValid());
+void LinkLayerController::IncomingLeConnectCompletePacket(LinkLayerPacketView incoming) {
+ auto complete = LeConnectCompleteView::GetLeConnectComplete(incoming);
HandleLeConnection(incoming.GetSourceAddress(), static_cast<uint8_t>(complete.GetAddressType()),
static_cast<uint8_t>(le_address_type_), static_cast<uint8_t>(hci::Role::MASTER),
complete.GetLeConnectionInterval(), complete.GetLeConnectionLatency(),
complete.GetLeConnectionSupervisionTimeout());
}
-void LinkLayerController::IncomingLeScanPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingLeScanPacket(LinkLayerPacketView incoming) {
LOG_INFO("LE Scan Packet");
-
- auto to_send = model::packets::LeScanResponseBuilder::Create(
- properties_.GetLeAddress(), incoming.GetSourceAddress(),
- static_cast<model::packets::AddressType>(properties_.GetLeAddressType()),
- static_cast<model::packets::AdvertisementType>(
- properties_.GetLeAdvertisementType()),
+ std::unique_ptr<LeAdvertisementBuilder> response = LeAdvertisementBuilder::Create(
+ static_cast<LeAdvertisement::AddressType>(properties_.GetLeAddressType()),
+ static_cast<LeAdvertisement::AdvertisementType>(properties_.GetLeAdvertisementType()),
properties_.GetLeScanResponse());
-
- SendLeLinkLayerPacket(std::move(to_send));
+ std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapLeScanResponse(
+ std::move(response), properties_.GetLeAddress(), incoming.GetSourceAddress());
+ SendLeLinkLayerPacket(to_send);
}
-void LinkLayerController::IncomingLeScanResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto scan_response = model::packets::LeScanResponseView::Create(incoming);
- ASSERT(scan_response.IsValid());
- vector<uint8_t> ad = scan_response.GetData();
- auto adv_type = static_cast<LeAdvertisement::AdvertisementType>(
- scan_response.GetAdvertisementType());
- auto address_type =
- static_cast<LeAdvertisement::AddressType>(scan_response.GetAddressType());
+void LinkLayerController::IncomingLeScanResponsePacket(LinkLayerPacketView incoming) {
+ LeAdvertisementView scan_response = LeAdvertisementView::GetLeAdvertisementView(incoming);
+ vector<uint8_t> ad;
+ auto itr = scan_response.GetData();
+ size_t scan_size = itr.NumBytesRemaining();
+ for (size_t i = 0; i < scan_size; i++) {
+ ad.push_back(itr.extract<uint8_t>());
+ }
std::unique_ptr<EventPacketBuilder> le_adverts = EventPacketBuilder::CreateLeAdvertisingReportEvent();
- if (!le_adverts->AddLeAdvertisingReport(
- adv_type, address_type, incoming.GetSourceAddress(), ad, GetRssi())) {
+ if (!le_adverts->AddLeAdvertisingReport(scan_response.GetAdvertisementType(), scan_response.GetAddressType(),
+ incoming.GetSourceAddress(), ad, GetRssi())) {
LOG_INFO("Couldn't add the scan response.");
} else {
send_event_(le_adverts->ToVector());
}
}
-void LinkLayerController::IncomingPagePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto page = model::packets::PageView::Create(incoming);
- ASSERT(page.IsValid());
+void LinkLayerController::IncomingPagePacket(LinkLayerPacketView incoming) {
+ PageView page = PageView::GetPage(incoming);
LOG_INFO("%s from %s", __func__, incoming.GetSourceAddress().ToString().c_str());
if (!connections_.CreatePendingConnection(incoming.GetSourceAddress())) {
@@ -693,19 +588,16 @@ void LinkLayerController::IncomingPagePacket(
->ToVector());
}
-void LinkLayerController::IncomingPageRejectPacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingPageRejectPacket(LinkLayerPacketView incoming) {
LOG_INFO("%s: %s", __func__, incoming.GetSourceAddress().ToString().c_str());
- auto reject = model::packets::PageRejectView::Create(incoming);
- ASSERT(reject.IsValid());
+ PageRejectView reject = PageRejectView::GetPageReject(incoming);
LOG_INFO("%s: Sending CreateConnectionComplete", __func__);
send_event_(EventPacketBuilder::CreateConnectionCompleteEvent(static_cast<hci::Status>(reject.GetReason()), 0x0eff,
incoming.GetSourceAddress(), hci::LinkType::ACL, false)
->ToVector());
}
-void LinkLayerController::IncomingPageResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
+void LinkLayerController::IncomingPageResponsePacket(LinkLayerPacketView incoming) {
LOG_INFO("%s: %s", __func__, incoming.GetSourceAddress().ToString().c_str());
uint16_t handle = connections_.CreateConnection(incoming.GetSourceAddress());
if (handle == acl::kReservedHandle) {
@@ -717,15 +609,13 @@ void LinkLayerController::IncomingPageResponsePacket(
->ToVector());
}
-void LinkLayerController::IncomingResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto response = model::packets::ResponseView::Create(incoming);
- ASSERT(response.IsValid());
+void LinkLayerController::IncomingResponsePacket(LinkLayerPacketView incoming) {
+ ResponseView response = ResponseView::GetResponse(incoming);
// TODO: Check to see if I'm expecting this response.
hci::OpCode opcode = static_cast<hci::OpCode>(response.GetOpcode());
- auto args = response.GetPayload().begin();
+ auto args = response.GetResponseData();
hci::Status status = static_cast<hci::Status>(args.extract<uint64_t>());
uint16_t handle = connections_.GetHandle(incoming.GetSourceAddress());
@@ -788,21 +678,24 @@ void LinkLayerController::LeAdvertising() {
if (duration_cast<milliseconds>(now - last_le_advertisement_) < milliseconds(200)) {
return;
}
+ last_le_advertisement_ = now;
- auto own_address_type = static_cast<model::packets::AddressType>(
- properties_.GetLeAdvertisingOwnAddressType());
+ LeAdvertisement::AddressType own_address_type =
+ static_cast<LeAdvertisement::AddressType>(properties_.GetLeAdvertisingOwnAddressType());
+ std::shared_ptr<packets::LinkLayerPacketBuilder> to_send;
+ std::unique_ptr<packets::LeAdvertisementBuilder> ad;
Address advertising_address = Address::kEmpty;
- if (own_address_type == model::packets::AddressType::PUBLIC) {
+ if (own_address_type == LeAdvertisement::AddressType::PUBLIC) {
advertising_address = properties_.GetAddress();
- } else if (own_address_type == model::packets::AddressType::RANDOM) {
+ } else if (own_address_type == LeAdvertisement::AddressType::RANDOM) {
advertising_address = properties_.GetLeAddress();
}
ASSERT(advertising_address != Address::kEmpty);
- auto to_send = model::packets::LeAdvertisementBuilder::Create(
- advertising_address, Address::kEmpty, own_address_type,
- static_cast<model::packets::AdvertisementType>(own_address_type),
- properties_.GetLeAdvertisement());
- SendLeLinkLayerPacket(std::move(to_send));
+ ad = packets::LeAdvertisementBuilder::Create(own_address_type,
+ static_cast<LeAdvertisement::AdvertisementType>(own_address_type),
+ properties_.GetLeAdvertisement());
+ to_send = packets::LinkLayerPacketBuilder::WrapLeAdvertisement(std::move(ad), advertising_address);
+ SendLeLinkLayerPacket(to_send);
}
void LinkLayerController::Connections() {
@@ -825,9 +718,7 @@ void LinkLayerController::RegisterScoChannel(
}
void LinkLayerController::RegisterRemoteChannel(
- const std::function<void(
- std::shared_ptr<model::packets::LinkLayerPacketBuilder>, Phy::Type)>&
- callback) {
+ const std::function<void(std::shared_ptr<LinkLayerPacketBuilder>, Phy::Type)>& callback) {
send_to_remote_ = callback;
}
@@ -944,21 +835,16 @@ hci::Status LinkLayerController::IoCapabilityRequestReply(const Address& peer, u
security_manager_.SetLocalIoCapability(peer, io_capability, oob_data_present_flag, authentication_requirements);
PairingType pairing_type = security_manager_.GetSimplePairingType();
-
if (pairing_type != PairingType::INVALID) {
ScheduleTask(milliseconds(5), [this, peer, pairing_type]() { AuthenticateRemoteStage1(peer, pairing_type); });
- auto packet = model::packets::IoCapabilityResponseBuilder::Create(
- properties_.GetAddress(), peer, io_capability, oob_data_present_flag,
- authentication_requirements);
- SendLinkLayerPacket(std::move(packet));
-
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityResponse(
+ IoCapabilityBuilder::Create(io_capability, oob_data_present_flag, authentication_requirements),
+ properties_.GetAddress(), peer));
} else {
LOG_INFO("%s: Requesting remote capability", __func__);
-
- auto packet = model::packets::IoCapabilityRequestBuilder::Create(
- properties_.GetAddress(), peer, io_capability, oob_data_present_flag,
- authentication_requirements);
- SendLinkLayerPacket(std::move(packet));
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityRequest(
+ IoCapabilityBuilder::Create(io_capability, oob_data_present_flag, authentication_requirements),
+ properties_.GetAddress(), peer));
}
return hci::Status::SUCCESS;
@@ -971,9 +857,8 @@ hci::Status LinkLayerController::IoCapabilityRequestNegativeReply(const Address&
security_manager_.InvalidateIoCapabilities();
- auto packet = model::packets::IoCapabilityNegativeResponseBuilder::Create(
- properties_.GetAddress(), peer, static_cast<uint8_t>(reason));
- SendLinkLayerPacket(std::move(packet));
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+ IoCapabilityNegativeResponseBuilder::Create(static_cast<uint8_t>(reason)), properties_.GetAddress(), peer));
return hci::Status::SUCCESS;
}
@@ -1064,9 +949,8 @@ void LinkLayerController::HandleSetConnectionEncryption(const Address& peer, uin
return;
}
- auto packet = model::packets::EncryptConnectionBuilder::Create(
- properties_.GetAddress(), peer, security_manager_.GetKey(peer));
- SendLinkLayerPacket(std::move(packet));
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapEncryptConnection(
+ EncryptConnectionBuilder::Create(security_manager_.GetKey(peer)), properties_.GetAddress(), peer));
}
hci::Status LinkLayerController::SetConnectionEncryption(uint16_t handle, uint8_t encryption_enable) {
@@ -1106,10 +990,10 @@ hci::Status LinkLayerController::AcceptConnectionRequest(const Address& addr, bo
}
void LinkLayerController::MakeSlaveConnection(const Address& addr, bool try_role_switch) {
+ std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapPageResponse(
+ PageResponseBuilder::Create(try_role_switch), properties_.GetAddress(), addr);
LOG_INFO("%s sending page response to %s", __func__, addr.ToString().c_str());
- auto to_send = model::packets::PageResponseBuilder::Create(
- properties_.GetAddress(), addr, try_role_switch);
- SendLinkLayerPacket(std::move(to_send));
+ SendLinkLayerPacket(to_send);
uint16_t handle = connections_.CreateConnection(addr);
if (handle == acl::kReservedHandle) {
@@ -1138,10 +1022,10 @@ hci::Status LinkLayerController::RejectConnectionRequest(const Address& addr, ui
}
void LinkLayerController::RejectSlaveConnection(const Address& addr, uint8_t reason) {
- auto to_send = model::packets::PageRejectBuilder::Create(
- properties_.GetAddress(), addr, reason);
+ std::shared_ptr<LinkLayerPacketBuilder> to_send =
+ LinkLayerPacketBuilder::WrapPageReject(PageRejectBuilder::Create(reason), properties_.GetAddress(), addr);
LOG_INFO("%s sending page reject to %s", __func__, addr.ToString().c_str());
- SendLinkLayerPacket(std::move(to_send));
+ SendLinkLayerPacket(to_send);
ASSERT(reason >= 0x0d && reason <= 0x0f);
send_event_(EventPacketBuilder::CreateConnectionCompleteEvent(static_cast<hci::Status>(reason), 0xeff, addr,
@@ -1155,10 +1039,8 @@ hci::Status LinkLayerController::CreateConnection(const Address& addr, uint16_t,
return hci::Status::CONTROLLER_BUSY;
}
- auto page = model::packets::PageBuilder::Create(
- properties_.GetAddress(), addr, properties_.GetClassOfDevice(),
- allow_role_switch);
- SendLinkLayerPacket(std::move(page));
+ std::unique_ptr<PageBuilder> page = PageBuilder::Create(properties_.GetClassOfDevice(), allow_role_switch);
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapPage(std::move(page), properties_.GetAddress(), addr));
return hci::Status::SUCCESS;
}
@@ -1177,9 +1059,9 @@ hci::Status LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) {
}
const Address& remote = connections_.GetAddress(handle);
- auto packet = model::packets::DisconnectBuilder::Create(
- properties_.GetAddress(), remote, reason);
- SendLinkLayerPacket(std::move(packet));
+ std::shared_ptr<LinkLayerPacketBuilder> to_send =
+ LinkLayerPacketBuilder::WrapDisconnect(DisconnectBuilder::Create(reason), properties_.GetAddress(), remote);
+ SendLinkLayerPacket(to_send);
ASSERT_LOG(connections_.Disconnect(handle), "Disconnecting %hx", handle);
ScheduleTask(milliseconds(20), [this, handle]() {
@@ -1311,6 +1193,8 @@ void LinkLayerController::LeWhiteListClear() {
le_white_list_.clear();
}
+void LinkLayerController::LeResolvingListClear() { le_resolving_list_.clear(); }
+
void LinkLayerController::LeWhiteListAddDevice(Address addr, uint8_t addr_type) {
std::tuple<Address, uint8_t> new_tuple = std::make_tuple(addr, addr_type);
for (auto dev : le_white_list_) {
@@ -1321,6 +1205,30 @@ void LinkLayerController::LeWhiteListAddDevice(Address addr, uint8_t addr_type)
le_white_list_.emplace_back(new_tuple);
}
+void LinkLayerController::LeResolvingListAddDevice(
+ Address addr, uint8_t addr_type, std::array<uint8_t, kIrk_size> peerIrk,
+ std::array<uint8_t, kIrk_size> localIrk) {
+ std::tuple<Address, uint8_t, std::array<uint8_t, kIrk_size>,
+ std::array<uint8_t, kIrk_size>>
+ new_tuple = std::make_tuple(addr, addr_type, peerIrk, localIrk);
+ for (size_t i = 0; i < le_white_list_.size(); i++) {
+ auto curr = le_white_list_[i];
+ if (std::get<0>(curr) == addr && std::get<1>(curr) == addr_type) {
+ le_resolving_list_[i] = new_tuple;
+ return;
+ }
+ }
+ le_resolving_list_.emplace_back(new_tuple);
+}
+
+void LinkLayerController::LeSetPrivacyMode(uint8_t address_type, Address addr,
+ uint8_t mode) {
+ // set mode for addr
+ LOG_INFO("address type = %d ", address_type);
+ LOG_INFO("address = %s ", addr.ToString().c_str());
+ LOG_INFO("mode = %d ", mode);
+}
+
void LinkLayerController::LeWhiteListRemoveDevice(Address addr, uint8_t addr_type) {
// TODO: Add checks to see if advertising, scanning, or a connection request
// with the white list is ongoing.
@@ -1332,6 +1240,18 @@ void LinkLayerController::LeWhiteListRemoveDevice(Address addr, uint8_t addr_typ
}
}
+void LinkLayerController::LeResolvingListRemoveDevice(Address addr,
+ uint8_t addr_type) {
+ // TODO: Add checks to see if advertising, scanning, or a connection request
+ // with the white list is ongoing.
+ for (size_t i = 0; i < le_white_list_.size(); i++) {
+ auto curr = le_white_list_[i];
+ if (std::get<0>(curr) == addr && std::get<1>(curr) == addr_type) {
+ le_resolving_list_.erase(le_resolving_list_.begin() + i);
+ }
+ }
+}
+
bool LinkLayerController::LeWhiteListContainsDevice(Address addr, uint8_t addr_type) {
std::tuple<Address, uint8_t> sought_tuple = std::make_tuple(addr, addr_type);
for (size_t i = 0; i < le_white_list_.size(); i++) {
@@ -1342,10 +1262,25 @@ bool LinkLayerController::LeWhiteListContainsDevice(Address addr, uint8_t addr_t
return false;
}
+bool LinkLayerController::LeResolvingListContainsDevice(Address addr,
+ uint8_t addr_type) {
+ for (size_t i = 0; i < le_white_list_.size(); i++) {
+ auto curr = le_white_list_[i];
+ if (std::get<0>(curr) == addr && std::get<1>(curr) == addr_type) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool LinkLayerController::LeWhiteListFull() {
return le_white_list_.size() >= properties_.GetLeWhiteListSize();
}
+bool LinkLayerController::LeResolvingListFull() {
+ return le_resolving_list_.size() >= properties_.GetLeResolvingListSize();
+}
+
void LinkLayerController::Reset() {
inquiry_state_ = Inquiry::InquiryState::STANDBY;
last_inquiry_ = steady_clock::now();
@@ -1375,7 +1310,7 @@ void LinkLayerController::InquiryTimeout() {
}
void LinkLayerController::SetInquiryMode(uint8_t mode) {
- inquiry_mode_ = static_cast<model::packets::InquiryType>(mode);
+ inquiry_mode_ = static_cast<Inquiry::InquiryType>(mode);
}
void LinkLayerController::SetInquiryLAP(uint64_t lap) {
@@ -1392,10 +1327,10 @@ void LinkLayerController::Inquiry() {
return;
}
LOG_INFO("Inquiry ");
-
- auto packet = model::packets::InquiryBuilder::Create(
- properties_.GetAddress(), Address::kEmpty, inquiry_mode_);
- SendLinkLayerPacket(std::move(packet));
+ std::unique_ptr<InquiryBuilder> inquiry = InquiryBuilder::Create(inquiry_mode_);
+ std::shared_ptr<LinkLayerPacketBuilder> to_send =
+ LinkLayerPacketBuilder::WrapInquiry(std::move(inquiry), properties_.GetAddress());
+ SendLinkLayerPacket(to_send);
last_inquiry_ = now;
}
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
index ab7f39342..9adb71463 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
@@ -19,12 +19,14 @@
#include "acl_connection_handler.h"
#include "include/hci.h"
#include "include/inquiry.h"
+#include "include/link.h"
#include "include/phy.h"
#include "model/devices/device_properties.h"
#include "model/setup/async_manager.h"
#include "packets/hci/acl_packet_view.h"
#include "packets/hci/sco_packet_view.h"
-#include "packets/link_layer_packets.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "security_manager.h"
#include "types/address.h"
@@ -32,6 +34,8 @@ namespace test_vendor_lib {
class LinkLayerController {
public:
+ static constexpr size_t kIrk_size = 16;
+
LinkLayerController(const DeviceProperties& properties) : properties_(properties) {}
hci::Status SendCommandToRemoteByAddress(hci::OpCode opcode, packets::PacketView<true> args, const Address& remote,
bool use_public_address);
@@ -73,7 +77,7 @@ class LinkLayerController {
void DisconnectCleanup(uint16_t handle, uint8_t reason);
public:
- void IncomingPacket(model::packets::LinkLayerPacketView incoming);
+ void IncomingPacket(packets::LinkLayerPacketView incoming);
void TimerTick();
@@ -89,9 +93,7 @@ class LinkLayerController {
void RegisterScoChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_sco);
void RegisterRemoteChannel(
- const std::function<void(
- std::shared_ptr<model::packets::LinkLayerPacketBuilder>, Phy::Type)>&
- send_to_remote);
+ const std::function<void(std::shared_ptr<packets::LinkLayerPacketBuilder>, Phy::Type)>& send_to_remote);
// Set the callbacks for scheduling tasks.
void RegisterTaskScheduler(
@@ -118,6 +120,14 @@ class LinkLayerController {
void LeWhiteListRemoveDevice(Address addr, uint8_t addr_type);
bool LeWhiteListContainsDevice(Address addr, uint8_t addr_type);
bool LeWhiteListFull();
+ void LeResolvingListClear();
+ void LeResolvingListAddDevice(Address addr, uint8_t addr_type,
+ std::array<uint8_t, kIrk_size> peerIrk,
+ std::array<uint8_t, kIrk_size> localIrk);
+ void LeResolvingListRemoveDevice(Address addr, uint8_t addr_type);
+ bool LeResolvingListContainsDevice(Address addr, uint8_t addr_type);
+ bool LeResolvingListFull();
+ void LeSetPrivacyMode(uint8_t address_type, Address addr, uint8_t mode);
hci::Status SetLeAdvertisingEnable(uint8_t le_advertising_enable) {
le_advertising_enable_ = le_advertising_enable;
@@ -206,46 +216,35 @@ class LinkLayerController {
hci::Status WriteLinkSupervisionTimeout(uint16_t handle, uint16_t timeout);
protected:
- void SendLeLinkLayerPacket(
- std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet);
- void SendLinkLayerPacket(
- std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet);
- void IncomingAclPacket(model::packets::LinkLayerPacketView packet);
- void IncomingAclAckPacket(model::packets::LinkLayerPacketView packet);
- void IncomingCommandPacket(model::packets::LinkLayerPacketView packet);
- void IncomingCreateConnectionPacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingDisconnectPacket(model::packets::LinkLayerPacketView packet);
- void IncomingEncryptConnection(model::packets::LinkLayerPacketView packet);
- void IncomingEncryptConnectionResponse(
- model::packets::LinkLayerPacketView packet);
- void IncomingInquiryPacket(model::packets::LinkLayerPacketView packet);
- void IncomingInquiryResponsePacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingIoCapabilityRequestPacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingIoCapabilityResponsePacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingIoCapabilityNegativeResponsePacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingLeAdvertisementPacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingLeConnectPacket(model::packets::LinkLayerPacketView packet);
- void IncomingLeConnectCompletePacket(
- model::packets::LinkLayerPacketView packet);
- void IncomingLeScanPacket(model::packets::LinkLayerPacketView packet);
- void IncomingLeScanResponsePacket(model::packets::LinkLayerPacketView packet);
- void IncomingPagePacket(model::packets::LinkLayerPacketView packet);
- void IncomingPageRejectPacket(model::packets::LinkLayerPacketView packet);
- void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet);
- void IncomingResponsePacket(model::packets::LinkLayerPacketView packet);
+ void SendLeLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet);
+ void SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet);
+ void IncomingAclPacket(packets::LinkLayerPacketView packet);
+ void IncomingAclAckPacket(packets::LinkLayerPacketView packet);
+ void IncomingCommandPacket(packets::LinkLayerPacketView packet);
+ void IncomingCreateConnectionPacket(packets::LinkLayerPacketView packet);
+ void IncomingDisconnectPacket(packets::LinkLayerPacketView packet);
+ void IncomingEncryptConnection(packets::LinkLayerPacketView packet);
+ void IncomingEncryptConnectionResponse(packets::LinkLayerPacketView packet);
+ void IncomingInquiryPacket(packets::LinkLayerPacketView packet);
+ void IncomingInquiryResponsePacket(packets::LinkLayerPacketView packet);
+ void IncomingIoCapabilityRequestPacket(packets::LinkLayerPacketView packet);
+ void IncomingIoCapabilityResponsePacket(packets::LinkLayerPacketView packet);
+ void IncomingIoCapabilityNegativeResponsePacket(packets::LinkLayerPacketView packet);
+ void IncomingLeAdvertisementPacket(packets::LinkLayerPacketView packet);
+ void IncomingLeConnectPacket(packets::LinkLayerPacketView packet);
+ void IncomingLeConnectCompletePacket(packets::LinkLayerPacketView packet);
+ void IncomingLeScanPacket(packets::LinkLayerPacketView packet);
+ void IncomingLeScanResponsePacket(packets::LinkLayerPacketView packet);
+ void IncomingPagePacket(packets::LinkLayerPacketView packet);
+ void IncomingPageRejectPacket(packets::LinkLayerPacketView packet);
+ void IncomingPageResponsePacket(packets::LinkLayerPacketView packet);
+ void IncomingResponsePacket(packets::LinkLayerPacketView packet);
private:
const DeviceProperties& properties_;
AclConnectionHandler connections_;
// Add timestamps?
- std::vector<std::shared_ptr<model::packets::LinkLayerPacketBuilder>>
- commands_awaiting_responses_;
+ std::vector<std::shared_ptr<packets::LinkLayerPacketBuilder>> commands_awaiting_responses_;
// Timing related state
std::vector<AsyncTaskId> controller_events_;
@@ -264,14 +263,15 @@ class LinkLayerController {
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
// Callback to send packets to remote devices.
- std::function<void(std::shared_ptr<model::packets::LinkLayerPacketBuilder>,
- Phy::Type phy_type)>
- send_to_remote_;
+ std::function<void(std::shared_ptr<packets::LinkLayerPacketBuilder>, Phy::Type phy_type)> send_to_remote_;
// LE state
std::vector<uint8_t> le_event_mask_;
std::vector<std::tuple<Address, uint8_t>> le_white_list_;
+ std::vector<std::tuple<Address, uint8_t, std::array<uint8_t, kIrk_size>,
+ std::array<uint8_t, kIrk_size>>>
+ le_resolving_list_;
uint8_t le_advertising_enable_{false};
std::chrono::steady_clock::time_point last_le_advertisement_;
@@ -300,7 +300,7 @@ class LinkLayerController {
SecurityManager security_manager_{10};
std::chrono::steady_clock::time_point last_inquiry_;
- model::packets::InquiryType inquiry_mode_;
+ Inquiry::InquiryType inquiry_mode_;
Inquiry::InquiryState inquiry_state_;
uint64_t inquiry_lap_;
uint8_t inquiry_max_responses_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon.cc b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
index 9c948f91b..46f306968 100644
--- a/vendor_libs/test_vendor_lib/model/devices/beacon.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
@@ -60,15 +60,12 @@ void Beacon::Initialize(const vector<std::string>& args) {
void Beacon::TimerTick() {
if (IsAdvertisementAvailable(std::chrono::milliseconds(5000))) {
- auto ad = model::packets::LeAdvertisementBuilder::Create(
- properties_.GetLeAddress(), Address::kEmpty,
- model::packets::AddressType::PUBLIC,
- static_cast<model::packets::AdvertisementType>(
- properties_.GetLeAdvertisementType()),
+ std::unique_ptr<packets::LeAdvertisementBuilder> ad = packets::LeAdvertisementBuilder::Create(
+ LeAdvertisement::AddressType::PUBLIC,
+ static_cast<LeAdvertisement::AdvertisementType>(properties_.GetLeAdvertisementType()),
properties_.GetLeAdvertisement());
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
- std::move(ad);
-
+ std::shared_ptr<packets::LinkLayerPacketBuilder> to_send =
+ packets::LinkLayerPacketBuilder::WrapLeAdvertisement(std::move(ad), properties_.GetLeAddress());
std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
for (std::shared_ptr<PhyLayer> phy : le_phys) {
phy->Send(to_send);
@@ -76,17 +73,13 @@ void Beacon::TimerTick() {
}
}
-void Beacon::IncomingPacket(model::packets::LinkLayerPacketView packet) {
- if (packet.GetDestinationAddress() == properties_.GetLeAddress() &&
- packet.GetType() == model::packets::PacketType::LE_SCAN) {
- auto scan_response = model::packets::LeAdvertisementBuilder::Create(
- properties_.GetLeAddress(), packet.GetSourceAddress(),
- model::packets::AddressType::PUBLIC,
- model::packets::AdvertisementType::SCAN_RESPONSE,
+void Beacon::IncomingPacket(packets::LinkLayerPacketView packet) {
+ if (packet.GetDestinationAddress() == properties_.GetLeAddress() && packet.GetType() == Link::PacketType::LE_SCAN) {
+ std::unique_ptr<packets::LeAdvertisementBuilder> scan_response = packets::LeAdvertisementBuilder::Create(
+ LeAdvertisement::AddressType::PUBLIC, LeAdvertisement::AdvertisementType::SCAN_RESPONSE,
properties_.GetLeScanResponse());
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
- std::move(scan_response);
-
+ std::shared_ptr<packets::LinkLayerPacketBuilder> to_send = packets::LinkLayerPacketBuilder::WrapLeScanResponse(
+ std::move(scan_response), properties_.GetLeAddress(), packet.GetSourceAddress());
std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
for (auto phy : le_phys) {
phy->Send(to_send);
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon.h b/vendor_libs/test_vendor_lib/model/devices/beacon.h
index 87bb22861..8499ab8d3 100644
--- a/vendor_libs/test_vendor_lib/model/devices/beacon.h
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.h
@@ -42,8 +42,7 @@ class Beacon : public Device {
// Set the address and advertising interval from string args.
virtual void Initialize(const std::vector<std::string>& args) override;
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
index 9f325a477..dcf977f7e 100644
--- a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
@@ -35,8 +35,7 @@ CarKit::CarKit() : Device(kCarKitPropertiesFile) {
link_layer_controller_.RegisterEventChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
link_layer_controller_.RegisterScoChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
link_layer_controller_.RegisterRemoteChannel(
- [this](std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
- Phy::Type phy_type) {
+ [this](std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type) {
CarKit::SendLinkLayerPacket(packet, phy_type);
});
@@ -91,7 +90,7 @@ void CarKit::TimerTick() {
link_layer_controller_.TimerTick();
}
-void CarKit::IncomingPacket(model::packets::LinkLayerPacketView packet) {
+void CarKit::IncomingPacket(packets::LinkLayerPacketView packet) {
LOG_WARN("Incoming Packet");
link_layer_controller_.IncomingPacket(packet);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/car_kit.h b/vendor_libs/test_vendor_lib/model/devices/car_kit.h
index 6822f27c4..94057ad1a 100644
--- a/vendor_libs/test_vendor_lib/model/devices/car_kit.h
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.h
@@ -45,8 +45,7 @@ class CarKit : public Device {
return "car_kit";
}
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.cc b/vendor_libs/test_vendor_lib/model/devices/device.cc
index 30753d47a..cd7368c8c 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/device.cc
@@ -63,16 +63,7 @@ bool Device::IsAdvertisementAvailable(std::chrono::milliseconds scan_time) const
return ((now + scan_time) >= next_interval);
}
-void Device::SendLinkLayerPacket(
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send,
- Phy::Type phy_type) {
- for (auto phy : phy_layers_[phy_type]) {
- phy->Send(to_send);
- }
-}
-
-void Device::SendLinkLayerPacket(model::packets::LinkLayerPacketView to_send,
- Phy::Type phy_type) {
+void Device::SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> to_send, Phy::Type phy_type) {
for (auto phy : phy_layers_[phy_type]) {
phy->Send(to_send);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.h b/vendor_libs/test_vendor_lib/model/devices/device.h
index 59e547eb7..277ebe13a 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device.h
+++ b/vendor_libs/test_vendor_lib/model/devices/device.h
@@ -24,10 +24,10 @@
#include "model/devices/device_properties.h"
#include "model/setup/phy_layer.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "types/address.h"
-#include "packets/link_layer_packets.h"
-
namespace test_vendor_lib {
// Represent a Bluetooth Device
@@ -73,13 +73,9 @@ class Device {
void UnregisterPhyLayer(Phy::Type phy_type, uint32_t factory_id);
- virtual void IncomingPacket(model::packets::LinkLayerPacketView){};
+ virtual void IncomingPacket(packets::LinkLayerPacketView){};
- virtual void SendLinkLayerPacket(
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
- Phy::Type phy_type);
- virtual void SendLinkLayerPacket(model::packets::LinkLayerPacketView packet,
- Phy::Type phy_type);
+ virtual void SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type);
protected:
std::map<Phy::Type, std::vector<std::shared_ptr<PhyLayer>>> phy_layers_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/device_properties.cc b/vendor_libs/test_vendor_lib/model/devices/device_properties.cc
index 6cb71e3a8..2a4a970fd 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device_properties.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.cc
@@ -45,10 +45,19 @@ bool ParseUint16t(base::StringPiece value, uint16_t* field) {
namespace test_vendor_lib {
DeviceProperties::DeviceProperties(const std::string& file_name)
- : acl_data_packet_size_(1024), sco_data_packet_size_(255), num_acl_data_packets_(10), num_sco_data_packets_(10),
- version_(static_cast<uint8_t>(hci::Version::V4_1)), revision_(0),
- lmp_pal_version_(static_cast<uint8_t>(hci::Version::V4_1)), manufacturer_name_(0), lmp_pal_subversion_(0),
- le_data_packet_length_(27), num_le_data_packets_(15), le_white_list_size_(15) {
+ : acl_data_packet_size_(1024),
+ sco_data_packet_size_(255),
+ num_acl_data_packets_(10),
+ num_sco_data_packets_(10),
+ version_(static_cast<uint8_t>(hci::Version::V4_1)),
+ revision_(0),
+ lmp_pal_version_(static_cast<uint8_t>(hci::Version::V4_1)),
+ manufacturer_name_(0),
+ lmp_pal_subversion_(0),
+ le_data_packet_length_(27),
+ num_le_data_packets_(15),
+ le_white_list_size_(15),
+ le_resolving_list_size_(15) {
std::string properties_raw;
ASSERT(Address::FromString("BB:BB:BB:BB:BB:AD", address_));
diff --git a/vendor_libs/test_vendor_lib/model/devices/device_properties.h b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
index 5f4fe6a94..fed710a32 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device_properties.h
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
@@ -282,6 +282,9 @@ class DeviceProperties {
return le_supported_states_;
}
+ // Specification Version 4.2, Volume 2, Part E, Section 7.8.41
+ uint8_t GetLeResolvingListSize() const { return le_resolving_list_size_; }
+
// Vendor-specific commands
const std::vector<uint8_t>& GetLeVendorCap() const {
return le_vendor_cap_;
@@ -318,6 +321,7 @@ class DeviceProperties {
uint16_t le_data_packet_length_;
uint8_t num_le_data_packets_;
uint8_t le_white_list_size_;
+ uint8_t le_resolving_list_size_;
uint64_t le_supported_features_{0x075b3fd8fe8ffeff};
uint64_t le_supported_states_;
std::vector<uint8_t> le_vendor_cap_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/keyboard.cc b/vendor_libs/test_vendor_lib/model/devices/keyboard.cc
index 1244d3ede..1daa05d0a 100644
--- a/vendor_libs/test_vendor_lib/model/devices/keyboard.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/keyboard.cc
@@ -80,7 +80,7 @@ void Keyboard::TimerTick() {
}
}
-void Keyboard::IncomingPacket(model::packets::LinkLayerPacketView packet) {
+void Keyboard::IncomingPacket(packets::LinkLayerPacketView packet) {
if (!connected_) {
Beacon::IncomingPacket(packet);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/keyboard.h b/vendor_libs/test_vendor_lib/model/devices/keyboard.h
index cf00dfeff..871fa529f 100644
--- a/vendor_libs/test_vendor_lib/model/devices/keyboard.h
+++ b/vendor_libs/test_vendor_lib/model/devices/keyboard.h
@@ -40,8 +40,7 @@ class Keyboard : public Beacon {
// Initialize the device based on the values of |args|.
virtual void Initialize(const std::vector<std::string>& args) override;
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc
index ab2c5f1dc..99f0c9def 100644
--- a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc
@@ -18,6 +18,8 @@
#include <unistd.h>
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "packets/packet_view.h"
#include "packets/view.h"
@@ -30,18 +32,16 @@ LinkLayerSocketDevice::LinkLayerSocketDevice(int socket_fd, Phy::Type phy_type)
void LinkLayerSocketDevice::TimerTick() {
if (bytes_left_ == 0) {
- size_t size_bytes = sizeof(uint32_t);
- received_ = std::make_shared<std::vector<uint8_t>>(size_bytes);
- size_t bytes_received = socket_.TryReceive(size_bytes, received_->data());
+ received_ = std::make_shared<std::vector<uint8_t>>(Link::kSizeBytes);
+ size_t bytes_received = socket_.TryReceive(Link::kSizeBytes, received_->data());
if (bytes_received == 0) {
return;
}
- ASSERT_LOG(bytes_received == size_bytes, "bytes_received == %d",
- static_cast<int>(bytes_received));
- packets::PacketView<true> size({packets::View(received_, 0, size_bytes)});
+ ASSERT_LOG(bytes_received == Link::kSizeBytes, "bytes_received == %d", static_cast<int>(bytes_received));
+ packets::PacketView<true> size({packets::View(received_, 0, Link::kSizeBytes)});
bytes_left_ = size.begin().extract<uint32_t>();
- received_->resize(size_bytes + bytes_left_);
- offset_ = size_bytes;
+ received_->resize(Link::kSizeBytes + bytes_left_);
+ offset_ = Link::kSizeBytes;
}
size_t bytes_received = socket_.TryReceive(bytes_left_, received_->data() + offset_);
if (bytes_received == 0) {
@@ -50,23 +50,14 @@ void LinkLayerSocketDevice::TimerTick() {
bytes_left_ -= bytes_received;
offset_ += bytes_received;
if (bytes_left_ == 0) {
- bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet_view(
- received_);
- auto packet = model::packets::LinkLayerPacketView::Create(packet_view);
- ASSERT(packet.IsValid());
- SendLinkLayerPacket(packet, phy_type_);
+ SendLinkLayerPacket(packets::LinkLayerPacketBuilder::ReWrap(received_), phy_type_);
offset_ = 0;
received_.reset();
}
}
-void LinkLayerSocketDevice::IncomingPacket(
- model::packets::LinkLayerPacketView packet) {
- std::shared_ptr<std::vector<uint8_t>> payload_bytes =
- std::make_shared<std::vector<uint8_t>>(packet.begin(), packet.end());
- packets::PacketView<true> packet_view(payload_bytes);
-
- socket_.TrySend(packet_view);
+void LinkLayerSocketDevice::IncomingPacket(packets::LinkLayerPacketView packet) {
+ socket_.TrySend(packet);
}
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h
index 2b662d184..d3bbb2e54 100644
--- a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h
+++ b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h
@@ -20,8 +20,9 @@
#include <vector>
#include "device.h"
+#include "include/link.h"
#include "include/phy.h"
-#include "packets/link_layer_packets.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "polled_socket.h"
namespace test_vendor_lib {
@@ -42,8 +43,7 @@ class LinkLayerSocketDevice : public Device {
virtual void Initialize(const std::vector<std::string>&) override {}
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
@@ -53,7 +53,7 @@ class LinkLayerSocketDevice : public Device {
size_t bytes_left_{0};
size_t offset_;
std::shared_ptr<std::vector<uint8_t>> received_;
- std::vector<model::packets::LinkLayerPacketView> packet_queue_;
+ std::vector<packets::LinkLayerPacketView> packet_queue_;
};
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/loopback.cc b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
index e0b9f35b0..18af1c10e 100644
--- a/vendor_libs/test_vendor_lib/model/devices/loopback.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
@@ -66,20 +66,15 @@ void Loopback::Initialize(const vector<std::string>& args) {
void Loopback::TimerTick() {}
-void Loopback::IncomingPacket(model::packets::LinkLayerPacketView packet) {
+void Loopback::IncomingPacket(packets::LinkLayerPacketView packet) {
LOG_INFO("Got a packet of type %d", static_cast<int>(packet.GetType()));
- if (packet.GetDestinationAddress() == properties_.GetLeAddress() &&
- packet.GetType() == model::packets::PacketType::LE_SCAN) {
+ if (packet.GetDestinationAddress() == properties_.GetLeAddress() && packet.GetType() == Link::PacketType::LE_SCAN) {
LOG_INFO("Got a scan");
-
- auto scan_response = model::packets::LeAdvertisementBuilder::Create(
- properties_.GetLeAddress(), packet.GetSourceAddress(),
- model::packets::AddressType::PUBLIC,
- model::packets::AdvertisementType::SCAN_RESPONSE,
+ std::unique_ptr<packets::LeAdvertisementBuilder> scan_response = packets::LeAdvertisementBuilder::Create(
+ LeAdvertisement::AddressType::PUBLIC, LeAdvertisement::AdvertisementType::SCAN_RESPONSE,
properties_.GetLeScanResponse());
- std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
- std::move(scan_response);
-
+ std::shared_ptr<packets::LinkLayerPacketBuilder> to_send = packets::LinkLayerPacketBuilder::WrapLeScanResponse(
+ std::move(scan_response), properties_.GetLeAddress(), packet.GetSourceAddress());
std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
for (auto phy : le_phys) {
LOG_INFO("Sending a Scan Response on a Phy");
diff --git a/vendor_libs/test_vendor_lib/model/devices/loopback.h b/vendor_libs/test_vendor_lib/model/devices/loopback.h
index dd5c06945..31dd1cdeb 100644
--- a/vendor_libs/test_vendor_lib/model/devices/loopback.h
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.h
@@ -42,8 +42,7 @@ class Loopback : public Device {
// Set the address and advertising interval from string args.
virtual void Initialize(const std::vector<std::string>& args) override;
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc
index db87028e3..82cf04fdd 100644
--- a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc
@@ -18,14 +18,16 @@
#include "model/setup/device_boutique.h"
#include "os/log.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
using std::vector;
namespace test_vendor_lib {
-using model::packets::LinkLayerPacketBuilder;
-using model::packets::LinkLayerPacketView;
-using model::packets::PageResponseBuilder;
+using packets::LinkLayerPacketBuilder;
+using packets::LinkLayerPacketView;
+using packets::PageResponseBuilder;
bool RemoteLoopbackDevice::registered_ = DeviceBoutique::Register("remote_loopback", &RemoteLoopbackDevice::Create);
@@ -42,23 +44,27 @@ void RemoteLoopbackDevice::Initialize(const std::vector<std::string>& args) {
if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
}
-void RemoteLoopbackDevice::IncomingPacket(
- model::packets::LinkLayerPacketView packet) {
+void RemoteLoopbackDevice::IncomingPacket(LinkLayerPacketView packet) {
// TODO: Check sender?
// TODO: Handle other packet types
Phy::Type phy_type = Phy::Type::BR_EDR;
- model::packets::PacketType type = packet.GetType();
+ Link::PacketType type = packet.GetType();
switch (type) {
- case model::packets::PacketType::PAGE:
- SendLinkLayerPacket(
- PageResponseBuilder::Create(packet.GetSourceAddress(),
- packet.GetSourceAddress(), true),
- Phy::Type::BR_EDR);
+ case Link::PacketType::PAGE:
+ SendLinkLayerPacket(LinkLayerPacketBuilder::WrapPageResponse(
+ PageResponseBuilder::Create(true), packet.GetSourceAddress(), packet.GetSourceAddress()),
+ Phy::Type::BR_EDR);
break;
default: {
LOG_WARN("Resend = %d", static_cast<int>(packet.size()));
- SendLinkLayerPacket(packet, phy_type);
+ std::shared_ptr<std::vector<uint8_t>> extracted_packet = std::make_shared<std::vector<uint8_t>>();
+ extracted_packet->reserve(packet.size());
+ for (const auto byte : packet) {
+ extracted_packet->push_back(byte);
+ }
+
+ SendLinkLayerPacket(LinkLayerPacketBuilder::ReWrap(extracted_packet), phy_type);
}
}
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h
index 98c9a835b..55136779c 100644
--- a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h
+++ b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h
@@ -20,6 +20,7 @@
#include <vector>
#include "device.h"
+#include "packets/link_layer/link_layer_packet_view.h"
namespace test_vendor_lib {
@@ -40,8 +41,7 @@ class RemoteLoopbackDevice : public Device {
virtual void Initialize(const std::vector<std::string>& args) override;
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
private:
static bool registered_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/sniffer.cc b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
index c4586d19d..ba4789304 100644
--- a/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
@@ -39,7 +39,7 @@ void Sniffer::Initialize(const vector<std::string>& args) {
void Sniffer::TimerTick() {}
-void Sniffer::IncomingPacket(model::packets::LinkLayerPacketView packet) {
+void Sniffer::IncomingPacket(packets::LinkLayerPacketView packet) {
Address source = packet.GetSourceAddress();
Address dest = packet.GetDestinationAddress();
bool match_source = device_to_sniff_ == source;
diff --git a/vendor_libs/test_vendor_lib/model/devices/sniffer.h b/vendor_libs/test_vendor_lib/model/devices/sniffer.h
index 162a401cb..3e0cfef48 100644
--- a/vendor_libs/test_vendor_lib/model/devices/sniffer.h
+++ b/vendor_libs/test_vendor_lib/model/devices/sniffer.h
@@ -20,7 +20,7 @@
#include <vector>
#include "device.h"
-#include "packets/link_layer_packets.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "types/address.h"
namespace test_vendor_lib {
@@ -42,8 +42,7 @@ class Sniffer : public Device {
return "sniffer";
}
- virtual void IncomingPacket(
- model::packets::LinkLayerPacketView packet) override;
+ virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
index 9f2bc7a38..e49c412b7 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
@@ -17,22 +17,19 @@
#pragma once
#include "include/phy.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
-#include "packets/link_layer_packets.h"
namespace test_vendor_lib {
class PhyLayer {
public:
- PhyLayer(Phy::Type phy_type, uint32_t id,
- const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive)
+ PhyLayer(Phy::Type phy_type, uint32_t id, const std::function<void(packets::LinkLayerPacketView)>& device_receive)
: phy_type_(phy_type), id_(id), transmit_to_device_(device_receive) {}
- virtual void Send(
- const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet) = 0;
- virtual void Send(model::packets::LinkLayerPacketView packet) = 0;
+ virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) = 0;
- virtual void Receive(model::packets::LinkLayerPacketView packet) = 0;
+ virtual void Receive(packets::LinkLayerPacketView packet) = 0;
virtual void TimerTick() = 0;
@@ -55,8 +52,7 @@ class PhyLayer {
uint32_t id_;
protected:
- const std::function<void(model::packets::LinkLayerPacketView)>
- transmit_to_device_;
+ const std::function<void(packets::LinkLayerPacketView)> transmit_to_device_;
};
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
index e1da9f377..654962eda 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
@@ -30,11 +30,9 @@ uint32_t PhyLayerFactory::GetFactoryId() {
}
std::shared_ptr<PhyLayer> PhyLayerFactory::GetPhyLayer(
- const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive) {
+ const std::function<void(packets::LinkLayerPacketView)>& device_receive) {
std::shared_ptr<PhyLayer> new_phy =
- std::make_shared<PhyLayerImpl>(phy_type_, next_id_++, device_receive,
- std::shared_ptr<PhyLayerFactory>(this));
+ std::make_shared<PhyLayerImpl>(phy_type_, next_id_++, device_receive, std::shared_ptr<PhyLayerFactory>(this));
phy_layers_.push_back(new_phy);
return new_phy;
}
@@ -49,32 +47,18 @@ void PhyLayerFactory::UnregisterPhyLayer(uint32_t id) {
}
}
-void PhyLayerFactory::Send(
- const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
- uint32_t id) {
+void PhyLayerFactory::Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet, uint32_t id) {
// Convert from a Builder to a View
- auto bytes = std::make_shared<std::vector<uint8_t>>();
- bluetooth::packet::BitInserter i(*bytes);
- bytes->reserve(packet->size());
- packet->Serialize(i);
- auto packet_view =
- bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian>(bytes);
- auto link_layer_packet_view =
- model::packets::LinkLayerPacketView::Create(packet_view);
- ASSERT(link_layer_packet_view.IsValid());
+ std::shared_ptr<std::vector<uint8_t>> serialized_packet =
+ std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+ std::back_insert_iterator<std::vector<uint8_t>> itr(*serialized_packet);
+ serialized_packet->reserve(packet->size());
+ packet->Serialize(itr);
+ packets::LinkLayerPacketView packet_view = packets::LinkLayerPacketView::Create(serialized_packet);
for (const auto phy : phy_layers_) {
if (id != phy->GetId()) {
- phy->Receive(link_layer_packet_view);
- }
- }
-}
-
-void PhyLayerFactory::Send(model::packets::LinkLayerPacketView packet,
- uint32_t id) {
- for (const auto phy : phy_layers_) {
- if (id != phy->GetId()) {
- phy->Receive(packet);
+ phy->Receive(packet_view);
}
}
}
@@ -98,23 +82,16 @@ std::string PhyLayerFactory::ToString() const {
}
}
-PhyLayerImpl::PhyLayerImpl(
- Phy::Type phy_type, uint32_t id,
- const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive,
- const std::shared_ptr<PhyLayerFactory>& factory)
+PhyLayerImpl::PhyLayerImpl(Phy::Type phy_type, uint32_t id,
+ const std::function<void(packets::LinkLayerPacketView)>& device_receive,
+ const std::shared_ptr<PhyLayerFactory>& factory)
: PhyLayer(phy_type, id, device_receive), factory_(factory) {}
PhyLayerImpl::~PhyLayerImpl() {
Unregister();
}
-void PhyLayerImpl::Send(
- const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet) {
- factory_->Send(packet, GetId());
-}
-
-void PhyLayerImpl::Send(model::packets::LinkLayerPacketView packet) {
+void PhyLayerImpl::Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) {
factory_->Send(packet, GetId());
}
@@ -126,7 +103,7 @@ bool PhyLayerImpl::IsFactoryId(uint32_t id) {
return factory_->GetFactoryId() == id;
}
-void PhyLayerImpl::Receive(model::packets::LinkLayerPacketView packet) {
+void PhyLayerImpl::Receive(packets::LinkLayerPacketView packet) {
transmit_to_device_(packet);
}
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
index 003236a8c..aaf14f832 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
@@ -20,7 +20,8 @@
#include <vector>
#include "include/phy.h"
-#include "packets/link_layer_packets.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
#include "phy_layer.h"
namespace test_vendor_lib {
@@ -37,9 +38,7 @@ class PhyLayerFactory {
uint32_t GetFactoryId();
- std::shared_ptr<PhyLayer> GetPhyLayer(
- const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive);
+ std::shared_ptr<PhyLayer> GetPhyLayer(const std::function<void(packets::LinkLayerPacketView)>& device_receive);
void UnregisterPhyLayer(uint32_t id);
@@ -48,10 +47,7 @@ class PhyLayerFactory {
virtual std::string ToString() const;
protected:
- virtual void Send(
- const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
- uint32_t id);
- virtual void Send(model::packets::LinkLayerPacketView packet, uint32_t id);
+ virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet, uint32_t id);
private:
Phy::Type phy_type_;
@@ -62,17 +58,12 @@ class PhyLayerFactory {
class PhyLayerImpl : public PhyLayer {
public:
- PhyLayerImpl(Phy::Type phy_type, uint32_t id,
- const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive,
+ PhyLayerImpl(Phy::Type phy_type, uint32_t id, const std::function<void(packets::LinkLayerPacketView)>& device_receive,
const std::shared_ptr<PhyLayerFactory>& factory);
virtual ~PhyLayerImpl() override;
- virtual void Send(
- const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet)
- override;
- virtual void Send(model::packets::LinkLayerPacketView packet) override;
- virtual void Receive(model::packets::LinkLayerPacketView packet) override;
+ virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) override;
+ virtual void Receive(packets::LinkLayerPacketView packet) override;
virtual void Unregister() override;
virtual bool IsFactoryId(uint32_t factory_id) override;
virtual void TimerTick() override;
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_model.cc b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
index ebd5fb94a..05500a11a 100644
--- a/vendor_libs/test_vendor_lib/model/setup/test_model.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
@@ -131,10 +131,8 @@ void TestModel::AddDeviceToPhy(size_t dev_index, size_t phy_index) {
return;
}
auto dev = device->second;
- dev->RegisterPhyLayer(phy->second->GetPhyLayer(
- [dev](model::packets::LinkLayerPacketView packet) {
- dev->IncomingPacket(packet);
- }));
+ dev->RegisterPhyLayer(
+ phy->second->GetPhyLayer([dev](packets::LinkLayerPacketView packet) { dev->IncomingPacket(packet); }));
}
void TestModel::DelDeviceFromPhy(size_t dev_index, size_t phy_index) {
diff --git a/vendor_libs/test_vendor_lib/packets/Android.bp b/vendor_libs/test_vendor_lib/packets/Android.bp
index 69a7b00a0..937849273 100644
--- a/vendor_libs/test_vendor_lib/packets/Android.bp
+++ b/vendor_libs/test_vendor_lib/packets/Android.bp
@@ -24,6 +24,8 @@ cc_library_static {
"hci/le_meta_event_builder.cc",
"hci/sco_packet_builder.cc",
"hci/sco_packet_view.cc",
+ "link_layer/link_layer_packet_builder.cc",
+ "link_layer/link_layer_packet_view.cc",
],
cflags: [
"-fvisibility=hidden",
@@ -54,6 +56,7 @@ cc_test_host {
"clang_coverage_bin",
],
srcs: [
+ "test/link_layer_packet_builder_test.cc",
"test/packet_builder_test.cc",
"test/packet_view_test.cc",
"hci/test/acl_builder_test.cc",
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h
new file mode 100644
index 000000000..ea3a1a2a1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CommandBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~CommandBuilder() = default;
+
+ static std::unique_ptr<CommandBuilder> Create(uint16_t opcode, PacketView<true> args) {
+ return std::unique_ptr<CommandBuilder>(new CommandBuilder(opcode, args));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(opcode_) + args_.size();
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(opcode_, it);
+ for (const auto&& byte : args_) {
+ insert(byte, it);
+ }
+ }
+
+ private:
+ explicit CommandBuilder(uint16_t opcode, PacketView<true> args) : opcode_(opcode), args_(args) {}
+ uint16_t opcode_;
+ PacketView<true> args_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h
new file mode 100644
index 000000000..6e83051eb
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "os/log.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CommandView : public PacketView<true> {
+ public:
+ CommandView(const CommandView&) = default;
+ virtual ~CommandView() = default;
+
+ static CommandView GetCommand(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::COMMAND);
+ return CommandView(view.GetPayload());
+ }
+
+ uint16_t GetOpcode() {
+ return begin().extract<uint16_t>();
+ }
+
+ Iterator<true> GetData() {
+ return begin() + sizeof(uint16_t);
+ }
+
+ private:
+ CommandView() = delete;
+ CommandView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h
new file mode 100644
index 000000000..8083c8587
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class DisconnectBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~DisconnectBuilder() = default;
+
+ static std::unique_ptr<DisconnectBuilder> Create(uint8_t reason) {
+ return std::unique_ptr<DisconnectBuilder>(new DisconnectBuilder(reason));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(reason_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ *it++ = reason_;
+ }
+
+ private:
+ explicit DisconnectBuilder(uint8_t reason) : reason_(reason) {}
+ uint8_t reason_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h
new file mode 100644
index 000000000..3e7251398
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class DisconnectView : public PacketView<true> {
+ public:
+ DisconnectView(const DisconnectView&) = default;
+ virtual ~DisconnectView() = default;
+
+ static DisconnectView GetDisconnect(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::DISCONNECT);
+ return DisconnectView(view.GetPayload());
+ }
+
+ uint8_t GetReason() {
+ return at(0);
+ }
+
+ private:
+ DisconnectView() = delete;
+ DisconnectView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h
new file mode 100644
index 000000000..702d2b4b1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EncryptConnectionBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~EncryptConnectionBuilder() = default;
+
+ static std::unique_ptr<EncryptConnectionBuilder> Create(const std::vector<uint8_t>& key) {
+ return std::unique_ptr<EncryptConnectionBuilder>(new EncryptConnectionBuilder(key));
+ }
+
+ virtual size_t size() const override {
+ return key_.size();
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert_vector(key_, it);
+ }
+
+ private:
+ explicit EncryptConnectionBuilder(const std::vector<uint8_t>& key) : key_(key.begin(), key.begin() + 16) {}
+ std::vector<uint8_t> key_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h
new file mode 100644
index 000000000..22006d05f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EncryptConnectionView : public PacketView<true> {
+ public:
+ EncryptConnectionView(const EncryptConnectionView&) = default;
+ virtual ~EncryptConnectionView() = default;
+
+ static EncryptConnectionView GetEncryptConnection(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::ENCRYPT_CONNECTION ||
+ view.GetType() == Link::PacketType::ENCRYPT_CONNECTION_RESPONSE);
+ return EncryptConnectionView(view.GetPayload());
+ }
+
+ Iterator<true> GetKey() {
+ return begin();
+ }
+
+ private:
+ EncryptConnectionView() = delete;
+ EncryptConnectionView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h
new file mode 100644
index 000000000..4c60ce066
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "inquiry.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~InquiryBuilder() = default;
+
+ static std::unique_ptr<InquiryBuilder> Create(Inquiry::InquiryType inquiry_type) {
+ return std::unique_ptr<InquiryBuilder>(new InquiryBuilder(inquiry_type));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(uint8_t);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(static_cast<uint8_t>(inquiry_type_), it);
+ }
+
+ private:
+ explicit InquiryBuilder(Inquiry::InquiryType inquiry_type) : inquiry_type_(inquiry_type) {}
+ Inquiry::InquiryType inquiry_type_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h
new file mode 100644
index 000000000..5db0be5fd
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "include/inquiry.h"
+#include "packets/packet_builder.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryResponseBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~InquiryResponseBuilder() = default;
+
+ static std::unique_ptr<InquiryResponseBuilder> CreateStandard(uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device,
+ uint16_t clock_offset) {
+ return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+ Inquiry::InquiryType::STANDARD, page_scan_repetition_mode, class_of_device, clock_offset));
+ }
+ static std::unique_ptr<InquiryResponseBuilder> CreateRssi(uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device, uint16_t clock_offset,
+ uint8_t rssi) {
+ return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+ Inquiry::InquiryType::RSSI, page_scan_repetition_mode, class_of_device, clock_offset, rssi));
+ }
+ static std::unique_ptr<InquiryResponseBuilder> CreateExtended(uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device,
+ uint16_t clock_offset, uint8_t rssi,
+ const std::vector<uint8_t>& extended_data) {
+ return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+ Inquiry::InquiryType::EXTENDED, page_scan_repetition_mode, class_of_device, clock_offset, rssi, extended_data));
+ }
+
+ virtual size_t size() const override {
+ size_t inquiry_size =
+ sizeof(inquiry_type_) + sizeof(page_scan_repetition_mode_) + sizeof(class_of_device_) + sizeof(clock_offset_);
+ if (inquiry_type_ == Inquiry::InquiryType::STANDARD) {
+ return inquiry_size;
+ }
+ inquiry_size += sizeof(rssi_);
+ if (inquiry_type_ == Inquiry::InquiryType::RSSI) {
+ return inquiry_size;
+ }
+
+ return inquiry_size + extended_data_.size();
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(static_cast<uint8_t>(inquiry_type_), it);
+ insert(page_scan_repetition_mode_, it);
+ insert_class_of_device(class_of_device_, it);
+ insert(clock_offset_, it);
+ if (inquiry_type_ == Inquiry::InquiryType::STANDARD) {
+ return;
+ }
+ insert(rssi_, it);
+ if (inquiry_type_ == Inquiry::InquiryType::RSSI) {
+ return;
+ }
+ insert_vector(extended_data_, it);
+ }
+
+ private:
+ Inquiry::InquiryType inquiry_type_;
+ uint8_t page_scan_repetition_mode_;
+ ClassOfDevice class_of_device_;
+ uint16_t clock_offset_;
+ uint8_t rssi_{0xff};
+ std::vector<uint8_t> extended_data_;
+ explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device, uint16_t clock_offset)
+ : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+ class_of_device_(class_of_device), clock_offset_(clock_offset) {}
+ explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device, uint16_t clock_offset, uint8_t rssi)
+ : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+ class_of_device_(class_of_device), clock_offset_(clock_offset), rssi_(rssi) {}
+ explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+ const ClassOfDevice& class_of_device, uint16_t clock_offset, uint8_t rssi,
+ const std::vector<uint8_t>& extended_data)
+ : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+ class_of_device_(class_of_device), clock_offset_(clock_offset), rssi_(rssi), extended_data_(extended_data) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h
new file mode 100644
index 000000000..f963134eb
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "include/inquiry.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryResponseView : public PacketView<true> {
+ public:
+ InquiryResponseView(const InquiryResponseView&) = default;
+ virtual ~InquiryResponseView() = default;
+
+ static InquiryResponseView GetInquiryResponse(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::INQUIRY_RESPONSE);
+ return InquiryResponseView(view.GetPayload());
+ }
+
+ Inquiry::InquiryType GetType() {
+ return static_cast<Inquiry::InquiryType>(at(0));
+ }
+
+ uint8_t GetPageScanRepetitionMode() {
+ return at(1);
+ }
+
+ ClassOfDevice GetClassOfDevice() {
+ size_t offset = 2 * sizeof(uint8_t);
+ return (begin() + offset).extract<ClassOfDevice>();
+ }
+
+ uint16_t GetClockOffset() {
+ size_t offset = 2 * sizeof(uint8_t) + 3;
+ return (begin() + offset).extract<uint16_t>();
+ }
+
+ uint8_t GetRssi() {
+ size_t offset = 2 * sizeof(uint8_t) + 3 + sizeof(uint16_t);
+ return at(offset);
+ }
+
+ Iterator<true> GetExtendedData() {
+ size_t offset = 2 * sizeof(uint8_t) + 3 + sizeof(uint16_t) + sizeof(uint8_t);
+ return begin() + offset;
+ }
+
+ private:
+ InquiryResponseView() = delete;
+ InquiryResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h
new file mode 100644
index 000000000..ea8fac968
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "inquiry.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryView : public PacketView<true> {
+ public:
+ InquiryView(const InquiryView&) = default;
+ virtual ~InquiryView() = default;
+
+ static InquiryView GetInquiry(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::INQUIRY);
+ return InquiryView(view.GetPayload());
+ }
+
+ Inquiry::InquiryType GetType() {
+ return static_cast<Inquiry::InquiryType>(at(0));
+ }
+
+ private:
+ InquiryView() = delete;
+ InquiryView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h
new file mode 100644
index 000000000..16843d127
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~IoCapabilityBuilder() = default;
+
+ static std::unique_ptr<IoCapabilityBuilder> Create(uint8_t io_capability, uint8_t oob_data_present,
+ uint8_t authentication_requirements) {
+ return std::unique_ptr<IoCapabilityBuilder>(
+ new IoCapabilityBuilder(io_capability, oob_data_present, authentication_requirements));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(io_capability_) + sizeof(oob_data_present_) + sizeof(authentication_requirements_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(io_capability_, it);
+ insert(oob_data_present_, it);
+ insert(authentication_requirements_, it);
+ }
+
+ private:
+ explicit IoCapabilityBuilder(uint8_t io_capability, uint8_t oob_data_present, uint8_t authentication_requirements)
+ : io_capability_(io_capability), oob_data_present_(oob_data_present),
+ authentication_requirements_(authentication_requirements) {}
+ uint8_t io_capability_;
+ uint8_t oob_data_present_;
+ uint8_t authentication_requirements_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h
new file mode 100644
index 000000000..cd8631426
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityNegativeResponseBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~IoCapabilityNegativeResponseBuilder() = default;
+
+ static std::unique_ptr<IoCapabilityNegativeResponseBuilder> Create(uint8_t reason) {
+ return std::unique_ptr<IoCapabilityNegativeResponseBuilder>(new IoCapabilityNegativeResponseBuilder(reason));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(reason_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(reason_, it);
+ }
+
+ private:
+ explicit IoCapabilityNegativeResponseBuilder(uint8_t reason) : reason_(reason) {}
+ uint8_t reason_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h
new file mode 100644
index 000000000..59978141b
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityNegativeResponseView : public PacketView<true> {
+ public:
+ IoCapabilityNegativeResponseView(const IoCapabilityNegativeResponseView&) = default;
+ virtual ~IoCapabilityNegativeResponseView() = default;
+
+ static IoCapabilityNegativeResponseView GetIoCapabilityNegativeResponse(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE);
+ return IoCapabilityNegativeResponseView(view.GetPayload());
+ }
+
+ uint8_t GetReason() {
+ return at(0);
+ }
+
+ private:
+ IoCapabilityNegativeResponseView() = delete;
+ IoCapabilityNegativeResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h
new file mode 100644
index 000000000..90a162c0a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityView : public PacketView<true> {
+ public:
+ IoCapabilityView(const IoCapabilityView&) = default;
+ virtual ~IoCapabilityView() = default;
+
+ static IoCapabilityView GetIoCapability(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::IO_CAPABILITY_RESPONSE ||
+ view.GetType() == Link::PacketType::IO_CAPABILITY_REQUEST);
+ return IoCapabilityView(view.GetPayload());
+ }
+
+ uint8_t GetIoCapability() {
+ return at(0);
+ }
+ uint8_t GetOobDataPresent() {
+ return at(1);
+ }
+ uint8_t GetAuthenticationRequirements() {
+ return at(2);
+ }
+
+ private:
+ IoCapabilityView() = delete;
+ IoCapabilityView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h
new file mode 100644
index 000000000..8c0e71bad
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "include/le_advertisement.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeAdvertisementBuilder : public PacketBuilder<true>, public LeAdvertisement {
+ public:
+ virtual ~LeAdvertisementBuilder() = default;
+
+ static std::unique_ptr<LeAdvertisementBuilder> Create(AddressType address_type, AdvertisementType advertisement_type,
+ const std::vector<uint8_t>& advertisement) {
+ return std::unique_ptr<LeAdvertisementBuilder>(
+ new LeAdvertisementBuilder(address_type, advertisement_type, advertisement));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(address_type_) + sizeof(advertisement_type_) + advertisement_.size();
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(static_cast<uint8_t>(address_type_), it);
+ insert(static_cast<uint8_t>(advertisement_type_), it);
+ insert_vector(advertisement_, it);
+ }
+
+ private:
+ LeAdvertisementBuilder() = delete;
+ explicit LeAdvertisementBuilder(AddressType address_type, AdvertisementType advertisement_type,
+ const std::vector<uint8_t>& advertisement)
+ : address_type_(address_type), advertisement_type_(advertisement_type), advertisement_(advertisement) {}
+ AddressType address_type_;
+ AdvertisementType advertisement_type_;
+ std::vector<uint8_t> advertisement_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h
new file mode 100644
index 000000000..574af2839
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "include/link.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeAdvertisementView : public PacketView<true>, public LeAdvertisement {
+ public:
+ LeAdvertisementView(const LeAdvertisementView&) = default;
+ virtual ~LeAdvertisementView() = default;
+
+ static LeAdvertisementView GetLeAdvertisementView(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::LE_ADVERTISEMENT ||
+ view.GetType() == Link::PacketType::LE_SCAN_RESPONSE);
+ return LeAdvertisementView(view.GetPayload());
+ }
+
+ AddressType GetAddressType() {
+ return static_cast<AddressType>(at(0));
+ }
+ AdvertisementType GetAdvertisementType() {
+ return static_cast<AdvertisementType>(at(1));
+ }
+ Iterator<true> GetData() {
+ return begin() + 2 * sizeof(uint8_t);
+ }
+
+ private:
+ LeAdvertisementView() = delete;
+ LeAdvertisementView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_builder.h
new file mode 100644
index 000000000..f33fc4264
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_builder.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeConnectBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~LeConnectBuilder() = default;
+
+ static std::unique_ptr<LeConnectBuilder> Create(uint16_t le_connection_interval_min,
+ uint16_t le_connection_interval_max, uint16_t le_connection_latency,
+ uint16_t le_connection_supervision_timeout,
+ uint8_t peer_address_type) {
+ return std::unique_ptr<LeConnectBuilder>(
+ new LeConnectBuilder(le_connection_interval_min, le_connection_interval_max, le_connection_latency,
+ le_connection_supervision_timeout, peer_address_type));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(le_connection_interval_min_) + sizeof(le_connection_interval_max_) + sizeof(le_connection_latency_) +
+ sizeof(le_connection_supervision_timeout_) + sizeof(peer_address_type_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(le_connection_interval_min_, it);
+ insert(le_connection_interval_max_, it);
+ insert(le_connection_latency_, it);
+ insert(le_connection_supervision_timeout_, it);
+ insert(peer_address_type_, it);
+ }
+
+ private:
+ explicit LeConnectBuilder(uint16_t le_connection_interval_min, uint16_t le_connection_interval_max,
+ uint16_t le_connection_latency, uint16_t le_connection_supervision_timeout,
+ uint8_t peer_address_type)
+ : le_connection_interval_min_(le_connection_interval_min),
+ le_connection_interval_max_(le_connection_interval_max), le_connection_latency_(le_connection_latency),
+ le_connection_supervision_timeout_(le_connection_supervision_timeout), peer_address_type_(peer_address_type)
+
+ {}
+ uint16_t le_connection_interval_min_;
+ uint16_t le_connection_interval_max_;
+ uint16_t le_connection_latency_;
+ uint16_t le_connection_supervision_timeout_;
+ uint8_t peer_address_type_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_builder.h
new file mode 100644
index 000000000..379c3d444
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_builder.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeConnectCompleteBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~LeConnectCompleteBuilder() = default;
+
+ static std::unique_ptr<LeConnectCompleteBuilder> Create(uint16_t le_connection_interval,
+ uint16_t le_connection_latency,
+ uint16_t le_connection_supervision_timeout,
+ uint8_t peer_address_type) {
+ return std::unique_ptr<LeConnectCompleteBuilder>(new LeConnectCompleteBuilder(
+ le_connection_interval, le_connection_latency, le_connection_supervision_timeout, peer_address_type));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(le_connection_interval_) + sizeof(le_connection_latency_) +
+ sizeof(le_connection_supervision_timeout_) + sizeof(peer_address_type_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(le_connection_interval_, it);
+ insert(le_connection_latency_, it);
+ insert(le_connection_supervision_timeout_, it);
+ insert(peer_address_type_, it);
+ }
+
+ private:
+ explicit LeConnectCompleteBuilder(uint16_t le_connection_interval, uint16_t le_connection_latency,
+ uint16_t le_connection_supervision_timeout, uint8_t peer_address_type)
+ : le_connection_interval_(le_connection_interval), le_connection_latency_(le_connection_latency),
+ le_connection_supervision_timeout_(le_connection_supervision_timeout), peer_address_type_(peer_address_type)
+
+ {}
+ uint16_t le_connection_interval_;
+ uint16_t le_connection_latency_;
+ uint16_t le_connection_supervision_timeout_;
+ uint8_t peer_address_type_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_view.h
new file mode 100644
index 000000000..88f5075cc
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_complete_view.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeConnectCompleteView : public PacketView<true> {
+ public:
+ LeConnectCompleteView(const LeConnectCompleteView&) = default;
+ virtual ~LeConnectCompleteView() = default;
+
+ static LeConnectCompleteView GetLeConnectComplete(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::LE_CONNECT_COMPLETE);
+ return LeConnectCompleteView(view.GetPayload());
+ }
+
+ uint16_t GetLeConnectionInterval() {
+ return begin().extract<uint16_t>();
+ }
+
+ uint16_t GetLeConnectionLatency() {
+ return (begin() + 2).extract<uint16_t>();
+ }
+
+ uint16_t GetLeConnectionSupervisionTimeout() {
+ return (begin() + 4).extract<uint16_t>();
+ }
+
+ uint8_t GetAddressType() {
+ return (begin() + 6).extract<uint8_t>();
+ }
+
+ private:
+ LeConnectCompleteView() = delete;
+ LeConnectCompleteView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_view.h
new file mode 100644
index 000000000..3fca36e99
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_connect_view.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeConnectView : public PacketView<true> {
+ public:
+ LeConnectView(const LeConnectView&) = default;
+ virtual ~LeConnectView() = default;
+
+ static LeConnectView GetLeConnect(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::LE_CONNECT);
+ return LeConnectView(view.GetPayload());
+ }
+
+ uint16_t GetLeConnectionIntervalMin() {
+ return begin().extract<uint16_t>();
+ }
+
+ uint16_t GetLeConnectionIntervalMax() {
+ return (begin() + 2).extract<uint16_t>();
+ }
+
+ uint16_t GetLeConnectionLatency() {
+ return (begin() + 4).extract<uint16_t>();
+ }
+
+ uint16_t GetLeConnectionSupervisionTimeout() {
+ return (begin() + 6).extract<uint16_t>();
+ }
+
+ uint8_t GetAddressType() {
+ return (begin() + 8).extract<uint8_t>();
+ }
+
+ private:
+ LeConnectView() = delete;
+ LeConnectView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc
new file mode 100644
index 000000000..816e44411
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2018 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 "link_layer_packet_builder.h"
+#include "link_layer_packet_view.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+namespace packets {
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, const Address& source, const Address& dest)
+ : type_(type), source_addr_(source), dest_addr_(dest) {}
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> packet,
+ const Address& source)
+ : type_(type), source_addr_(source), dest_addr_(Address::kEmpty), builder_(std::move(packet)) {}
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> packet,
+ const Address& source, const Address& dest)
+ : type_(type), source_addr_(source), dest_addr_(dest), builder_(std::move(packet)) {}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapAcl(std::unique_ptr<ViewForwarderBuilder> acl,
+ const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::ACL, std::move(acl), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapCommand(std::unique_ptr<CommandBuilder> command,
+ const Address& source,
+ const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::COMMAND, std::move(command), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapDisconnect(
+ std::unique_ptr<DisconnectBuilder> disconnect, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::DISCONNECT, std::move(disconnect), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapEncryptConnection(
+ std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::ENCRYPT_CONNECTION, std::move(encrypt_connection), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapEncryptConnectionResponse(
+ std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(
+ Link::PacketType::ENCRYPT_CONNECTION_RESPONSE, std::move(encrypt_connection), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapInquiry(std::unique_ptr<InquiryBuilder> inquiry,
+ const Address& source) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::INQUIRY, std::move(inquiry), source));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapInquiryResponse(
+ std::unique_ptr<InquiryResponseBuilder> inquiry_response, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::INQUIRY_RESPONSE, std::move(inquiry_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityRequest(
+ std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::IO_CAPABILITY_REQUEST, std::move(io_capability), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityResponse(
+ std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::IO_CAPABILITY_RESPONSE, std::move(io_capability), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+ std::unique_ptr<IoCapabilityNegativeResponseBuilder> io_capability_negative_response, const Address& source,
+ const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(
+ Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE, std::move(io_capability_negative_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeAdvertisement(
+ std::unique_ptr<LeAdvertisementBuilder> advertisement, const Address& source) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::LE_ADVERTISEMENT, std::move(advertisement), source));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeConnect(std::unique_ptr<LeConnectBuilder> connect,
+ const Address& source,
+ const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::LE_CONNECT, std::move(connect), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeConnectComplete(
+ std::unique_ptr<LeConnectCompleteBuilder> connect_complete, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::LE_CONNECT_COMPLETE, std::move(connect_complete), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeScan(const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(Link::PacketType::LE_SCAN, source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeScanResponse(
+ std::unique_ptr<LeAdvertisementBuilder> scan_response, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::LE_SCAN_RESPONSE, std ::move(scan_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapPage(std::unique_ptr<PageBuilder> page,
+ const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::PAGE, std::move(page), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapPageReject(
+ std::unique_ptr<PageRejectBuilder> page_reject, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::PAGE_REJECT, std::move(page_reject), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapPageResponse(
+ std::unique_ptr<PageResponseBuilder> page_response, const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::PAGE_RESPONSE, std::move(page_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapResponse(std::unique_ptr<ResponseBuilder> response,
+ const Address& source,
+ const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::RESPONSE, std::move(response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapSco(std::unique_ptr<ViewForwarderBuilder> sco,
+ const Address& source, const Address& dest) {
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(Link::PacketType::SCO, std::move(sco), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::ReWrap(
+ const std::shared_ptr<std::vector<uint8_t>> raw_packet) {
+ LinkLayerPacketView received = LinkLayerPacketView::Create(raw_packet);
+ Link::PacketType packet_type = received.GetType();
+ Address source = received.GetSourceAddress();
+ Address dest = received.GetDestinationAddress();
+ PacketView<true> payload = received.GetPayload();
+ std::unique_ptr<PacketBuilder> builder = ViewForwarderBuilder::Create(payload);
+ return std::shared_ptr<LinkLayerPacketBuilder>(
+ new LinkLayerPacketBuilder(packet_type, std::move(builder), source, dest));
+}
+
+size_t LinkLayerPacketBuilder::size() const {
+ size_t builder_size = (builder_ ? builder_->size() : 0);
+ return Link::kTypeBytes + Link::kSizeBytes + 2 * Address::kLength + builder_size;
+}
+
+void LinkLayerPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+ insert(static_cast<uint32_t>(size() - Link::kSizeBytes), it);
+ insert(static_cast<uint8_t>(type_), it);
+ insert_address(source_addr_.address, it);
+ insert_address(dest_addr_.address, it);
+ if (builder_) {
+ builder_->Serialize(it);
+ }
+}
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h
new file mode 100644
index 000000000..310115512
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "link.h"
+#include "packets/link_layer/command_builder.h"
+#include "packets/link_layer/disconnect_builder.h"
+#include "packets/link_layer/encrypt_connection_builder.h"
+#include "packets/link_layer/inquiry_builder.h"
+#include "packets/link_layer/inquiry_response_builder.h"
+#include "packets/link_layer/io_capability_builder.h"
+#include "packets/link_layer/io_capability_negative_response_builder.h"
+#include "packets/link_layer/le_advertisement_builder.h"
+#include "packets/link_layer/le_connect_builder.h"
+#include "packets/link_layer/le_connect_complete_builder.h"
+#include "packets/link_layer/page_builder.h"
+#include "packets/link_layer/page_reject_builder.h"
+#include "packets/link_layer/page_response_builder.h"
+#include "packets/link_layer/response_builder.h"
+#include "packets/link_layer/view_forwarder_builder.h"
+#include "packets/packet_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Link-layer packets are an abstraction of LMP PDUs.
+class LinkLayerPacketBuilder : PacketBuilder<true> {
+ public:
+ virtual ~LinkLayerPacketBuilder() = default;
+
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapAcl(std::unique_ptr<ViewForwarderBuilder> acl,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapCommand(std::unique_ptr<CommandBuilder> command,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapDisconnect(std::unique_ptr<DisconnectBuilder> disconnect,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapEncryptConnection(
+ std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapEncryptConnectionResponse(
+ std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapInquiry(std::unique_ptr<InquiryBuilder> inquiry,
+ const Address& source);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapInquiryResponse(
+ std::unique_ptr<InquiryResponseBuilder> inquiry_response, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityRequest(
+ std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityResponse(
+ std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityNegativeResponse(
+ std::unique_ptr<IoCapabilityNegativeResponseBuilder> io_capability_negative_response, const Address& source,
+ const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapLeAdvertisement(
+ std::unique_ptr<LeAdvertisementBuilder> advertisement, const Address& source);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapLeConnect(std::unique_ptr<LeConnectBuilder> connect,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapLeConnectComplete(
+ std::unique_ptr<LeConnectCompleteBuilder> connect_complete, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapLeScan(const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapLeScanResponse(
+ std::unique_ptr<LeAdvertisementBuilder> scan_response, const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapPage(std::unique_ptr<PageBuilder> page, const Address& source,
+ const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapPageReject(std::unique_ptr<PageRejectBuilder> page_response,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapPageResponse(std::unique_ptr<PageResponseBuilder> page_response,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapResponse(const std::unique_ptr<ResponseBuilder> response,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> WrapSco(std::unique_ptr<ViewForwarderBuilder> sco,
+ const Address& source, const Address& dest);
+ static std::shared_ptr<LinkLayerPacketBuilder> ReWrap(const std::shared_ptr<std::vector<uint8_t>> raw_packet);
+
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+ virtual size_t size() const override;
+
+ private:
+ LinkLayerPacketBuilder(const LinkLayerPacketBuilder&) = delete;
+ LinkLayerPacketBuilder() = delete;
+ LinkLayerPacketBuilder(Link::PacketType type, const Address& source, const Address& dest);
+ LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> builder, const Address& source,
+ const Address& dest);
+ LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> builder, const Address& source);
+ Link::PacketType type_;
+ Address source_addr_;
+ Address dest_addr_;
+ std::unique_ptr<PacketBuilder> builder_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc
new file mode 100644
index 000000000..31cbdbfc7
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 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 "link_layer_packet_view.h"
+
+#include "os/log.h"
+
+namespace test_vendor_lib {
+constexpr size_t Link::kSizeBytes;
+constexpr size_t Link::kTypeBytes;
+
+namespace packets {
+LinkLayerPacketView::LinkLayerPacketView(std::shared_ptr<std::vector<uint8_t>> raw) : PacketView<true>(raw) {}
+
+LinkLayerPacketView LinkLayerPacketView::Create(std::shared_ptr<std::vector<uint8_t>> raw) {
+ ASSERT(raw->size() >= Link::kSizeBytes + Link::kTypeBytes + 2 * Address::kLength);
+ return LinkLayerPacketView(raw);
+}
+
+Link::PacketType LinkLayerPacketView::GetType() const {
+ return static_cast<Link::PacketType>(at(Link::kSizeBytes));
+}
+
+Address LinkLayerPacketView::GetSourceAddress() const {
+ size_t offset = Link::kSizeBytes + Link::kTypeBytes;
+ return (begin() + offset).extract<Address>();
+}
+
+Address LinkLayerPacketView::GetDestinationAddress() const {
+ size_t offset = Link::kSizeBytes + Link::kTypeBytes + Address::kLength;
+ return (begin() + offset).extract<Address>();
+}
+
+PacketView<true> LinkLayerPacketView::GetPayload() const {
+ return SubViewLittleEndian(Link::kSizeBytes + Link::kTypeBytes + 2 * Address::kLength, size());
+}
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h
new file mode 100644
index 000000000..bdbfaa705
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "include/link.h"
+#include "packets/packet_view.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Link-layer packets are an abstraction of LMP PDUs.
+class LinkLayerPacketView : public PacketView<true> {
+ public:
+ LinkLayerPacketView(const LinkLayerPacketView&) = default;
+ virtual ~LinkLayerPacketView() = default;
+
+ static LinkLayerPacketView Create(std::shared_ptr<std::vector<uint8_t>> raw);
+
+ Link::PacketType GetType() const;
+ Address GetSourceAddress() const;
+ Address GetDestinationAddress() const;
+ PacketView<true> GetPayload() const;
+
+ private:
+ LinkLayerPacketView() = delete;
+ LinkLayerPacketView(std::shared_ptr<std::vector<uint8_t>> raw);
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h
new file mode 100644
index 000000000..9b219d702
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~PageBuilder() = default;
+
+ static std::unique_ptr<PageBuilder> Create(const ClassOfDevice& class_of_device, uint8_t allow_role_switch) {
+ return std::unique_ptr<PageBuilder>(new PageBuilder(class_of_device, allow_role_switch));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(class_of_device_) + sizeof(allow_role_switch_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert_class_of_device(class_of_device_, it);
+ insert(allow_role_switch_, it);
+ }
+
+ private:
+ explicit PageBuilder(const ClassOfDevice& class_of_device, uint8_t allow_role_switch)
+ : class_of_device_(class_of_device), allow_role_switch_(allow_role_switch) {}
+ ClassOfDevice class_of_device_;
+ uint8_t allow_role_switch_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_builder.h
new file mode 100644
index 000000000..ebf84d248
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_builder.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageRejectBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~PageRejectBuilder() = default;
+
+ static std::unique_ptr<PageRejectBuilder> Create(uint8_t reason) {
+ return std::unique_ptr<PageRejectBuilder>(new PageRejectBuilder(reason));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(reason_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(reason_, it);
+ }
+
+ private:
+ explicit PageRejectBuilder(uint8_t reason) : reason_(reason) {}
+ uint8_t reason_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_view.h
new file mode 100644
index 000000000..0c7611cfa
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_reject_view.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageRejectView : public PacketView<true> {
+ public:
+ PageRejectView(const PageRejectView&) = default;
+ virtual ~PageRejectView() = default;
+
+ static PageRejectView GetPageReject(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::PAGE_REJECT);
+ return PageRejectView(view.GetPayload());
+ }
+
+ uint8_t GetReason() {
+ return at(0);
+ }
+
+ private:
+ PageRejectView() = delete;
+ PageRejectView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h
new file mode 100644
index 000000000..da7c85374
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageResponseBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~PageResponseBuilder() = default;
+
+ static std::unique_ptr<PageResponseBuilder> Create(uint8_t try_role_switch) {
+ return std::unique_ptr<PageResponseBuilder>(new PageResponseBuilder(try_role_switch));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(try_role_switch_);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(try_role_switch_, it);
+ }
+
+ private:
+ explicit PageResponseBuilder(uint8_t try_role_switch) : try_role_switch_(try_role_switch) {}
+ uint8_t try_role_switch_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h
new file mode 100644
index 000000000..151052815
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageResponseView : public PacketView<true> {
+ public:
+ PageResponseView(const PageResponseView&) = default;
+ virtual ~PageResponseView() = default;
+
+ static PageResponseView GetPageResponse(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::PAGE_RESPONSE);
+ return PageResponseView(view.GetPayload());
+ }
+
+ uint8_t GetTryRoleSwitch() {
+ return at(0);
+ }
+
+ private:
+ PageResponseView() = delete;
+ PageResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h
new file mode 100644
index 000000000..7f54b8904
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageView : public PacketView<true> {
+ public:
+ PageView(const PageView&) = default;
+ virtual ~PageView() = default;
+
+ static PageView GetPage(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::PAGE);
+ return PageView(view.GetPayload());
+ }
+
+ ClassOfDevice GetClassOfDevice() {
+ return begin().extract<ClassOfDevice>();
+ }
+
+ uint8_t GetAllowRoleSwitch() {
+ return at(3);
+ }
+
+ private:
+ PageView() = delete;
+ PageView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h
new file mode 100644
index 000000000..18f765dfc
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ResponseBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~ResponseBuilder() = default;
+
+ static std::unique_ptr<ResponseBuilder> Create(uint16_t opcode, const std::vector<uint64_t>& data) {
+ return std::unique_ptr<ResponseBuilder>(new ResponseBuilder(opcode, data));
+ }
+
+ virtual size_t size() const override {
+ return sizeof(opcode_) + data_.size() * sizeof(uint64_t);
+ }
+
+ protected:
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ insert(opcode_, it);
+ insert_vector(data_, it);
+ }
+
+ private:
+ explicit ResponseBuilder(uint16_t opcode, const std::vector<uint64_t> data) : opcode_(opcode), data_(data) {}
+ uint16_t opcode_;
+ std::vector<uint64_t> data_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h
new file mode 100644
index 000000000..60316a80b
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ResponseView : public PacketView<true> {
+ public:
+ ResponseView(const ResponseView&) = default;
+ virtual ~ResponseView() = default;
+
+ static ResponseView GetResponse(const LinkLayerPacketView& view) {
+ ASSERT(view.GetType() == Link::PacketType::RESPONSE);
+ return ResponseView(view.GetPayload());
+ }
+
+ uint16_t GetOpcode() {
+ return begin().extract<uint16_t>();
+ }
+
+ Iterator<true> GetResponseData() {
+ return begin() + sizeof(uint16_t);
+ }
+
+ private:
+ ResponseView() = delete;
+ ResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h
new file mode 100644
index 000000000..81f7b5b82
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ViewForwarderBuilder : public PacketBuilder<true> {
+ public:
+ virtual ~ViewForwarderBuilder() = default;
+
+ static std::unique_ptr<ViewForwarderBuilder> Create(PacketView<true> view) {
+ return std::unique_ptr<ViewForwarderBuilder>(new ViewForwarderBuilder(view));
+ }
+
+ virtual size_t size() const override {
+ return view_.size();
+ }
+
+ virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ for (size_t i = 0; i < view_.size(); i++) {
+ insert(view_[i], it);
+ }
+ }
+
+ private:
+ explicit ViewForwarderBuilder(PacketView<true> view) : view_(view) {}
+ PacketView<true> view_;
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl b/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl
deleted file mode 100644
index 0194ab3e3..000000000
--- a/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl
+++ /dev/null
@@ -1,171 +0,0 @@
-little_endian_packets
-
-custom_field Address : 48 "types/"
-custom_field ClassOfDevice : 24 "types/"
-
-enum PacketType : 8 {
- UNKNOWN = 0x00,
- ACL = 0x01,
- COMMAND = 0x02,
- DISCONNECT = 0x03,
- ENCRYPT_CONNECTION = 0x04,
- ENCRYPT_CONNECTION_RESPONSE = 0x05,
- EVENT = 0x06,
- INQUIRY = 0x07,
- INQUIRY_RESPONSE = 0x08,
- IO_CAPABILITY_REQUEST = 0x09,
- IO_CAPABILITY_RESPONSE = 0x0A,
- IO_CAPABILITY_NEGATIVE_RESPONSE = 0x0B,
- LE_ADVERTISEMENT = 0x0C,
- LE_CONNECT = 0x0D,
- LE_CONNECT_COMPLETE = 0x0E,
- LE_SCAN = 0x0F,
- LE_SCAN_RESPONSE = 0x10,
- PAGE = 0x11,
- PAGE_RESPONSE = 0x12,
- PAGE_REJECT = 0x13,
- RESPONSE = 0x14,
- SCO = 0x15,
-}
-
-packet LinkLayerPacket {
- type : PacketType,
- source_address : Address,
- destination_address : Address,
- _body_,
-}
-
-packet AclPacket : LinkLayerPacket (type = ACL) {
- _payload_,
-}
-
-packet Command : LinkLayerPacket (type = COMMAND) {
- _payload_,
-}
-
-packet Disconnect : LinkLayerPacket (type = DISCONNECT) {
- reason : 8,
-}
-
-packet EncryptConnection : LinkLayerPacket (type = ENCRYPT_CONNECTION) {
- key : 8[],
-}
-
-packet EncryptConnectionResponse : LinkLayerPacket (type = ENCRYPT_CONNECTION_RESPONSE) {
- key : 8[],
-}
-
-enum InquiryState : 8 {
- STANDBY = 0x00,
- INQUIRY = 0x01,
-}
-
-enum InquiryType : 8 {
- STANDARD = 0x00,
- RSSI = 0x01,
- EXTENDED = 0x02,
-}
-
-packet Inquiry : LinkLayerPacket (type = INQUIRY) {
- inquiry_type : InquiryType,
-}
-
-packet BasicInquiryResponse : LinkLayerPacket(type = INQUIRY_RESPONSE) {
- inquiry_type : InquiryType,
- page_scan_repetition_mode : 8,
- class_of_device : ClassOfDevice,
- clock_offset : 15,
- _reserved_ : 1,
- _body_,
-}
-
-packet InquiryResponse : BasicInquiryResponse (inquiry_type = STANDARD) {
-}
-
-packet InquiryResponseWithRssi : BasicInquiryResponse (inquiry_type = RSSI) {
- rssi: 8,
-}
-
-packet ExtendedInquiryResponse : BasicInquiryResponse (inquiry_type = EXTENDED) {
- rssi: 8,
- extended_data : 8[],
-}
-
-packet IoCapabilityRequest : LinkLayerPacket (type = IO_CAPABILITY_REQUEST) {
- io_capability : 8,
- oob_data_present : 8,
- authentication_requirements : 8,
-}
-
-packet IoCapabilityResponse : LinkLayerPacket (type = IO_CAPABILITY_RESPONSE) {
- io_capability : 8,
- oob_data_present : 8,
- authentication_requirements : 8,
-}
-
-packet IoCapabilityNegativeResponse : LinkLayerPacket (type = IO_CAPABILITY_NEGATIVE_RESPONSE) {
- reason : 8,
-}
-
-enum AddressType : 8 {
- PUBLIC = 0,
- RANDOM = 1,
- PUBLIC_IDENTITY = 2,
- RANDOM_IDENTITY = 3,
-}
-
-enum AdvertisementType : 8 {
- ADV_IND = 0, // Connectable and scannable
- ADV_DIRECT_IND = 1, // Connectable directed
- ADV_SCAN_IND = 2, // Scannable undirected
- ADV_NONCONN_IND = 3, // Non connectable undirected
- SCAN_RESPONSE = 4,
-}
-
-packet LeAdvertisement : LinkLayerPacket (type = LE_ADVERTISEMENT) {
- address_type : AddressType,
- advertisement_type : AdvertisementType,
- data : 8[],
-}
-
-packet LeConnect : LinkLayerPacket (type = LE_CONNECT) {
- le_connection_interval_min : 16,
- le_connection_interval_max : 16,
- le_connection_latency : 16,
- le_connection_supervision_timeout : 16,
- address_type : 8,
-}
-
-packet LeConnectComplete : LinkLayerPacket (type = LE_CONNECT_COMPLETE) {
- le_connection_interval : 16,
- le_connection_latency : 16,
- le_connection_supervision_timeout : 16,
- address_type : 8,
-}
-
-packet LeScan : LinkLayerPacket (type = LE_SCAN) {
-}
-
-packet LeScanResponse : LinkLayerPacket (type = LE_SCAN_RESPONSE) {
- address_type : AddressType,
- advertisement_type : AdvertisementType,
- data : 8[],
-}
-
-packet Page : LinkLayerPacket (type = PAGE) {
- class_of_device : ClassOfDevice,
- allow_role_switch : 8,
-}
-
-packet PageResponse : LinkLayerPacket (type = PAGE_RESPONSE) {
- try_role_switch : 8,
-}
-
-packet PageReject : LinkLayerPacket (type = PAGE_REJECT) {
- reason : 8,
-}
-
-packet Response : LinkLayerPacket (type = RESPONSE) {
- opcode : 16,
- _payload_,
-}
diff --git a/vendor_libs/test_vendor_lib/packets/packet_view.h b/vendor_libs/test_vendor_lib/packets/packet_view.h
index 22c530ad6..16255faaa 100644
--- a/vendor_libs/test_vendor_lib/packets/packet_view.h
+++ b/vendor_libs/test_vendor_lib/packets/packet_view.h
@@ -32,7 +32,6 @@ template <bool little_endian>
class PacketView {
public:
PacketView(const std::forward_list<class View> fragments);
- PacketView(std::shared_ptr<std::vector<uint8_t>> packet);
PacketView(const PacketView& PacketView) = default;
virtual ~PacketView() = default;
@@ -50,6 +49,9 @@ class PacketView {
PacketView<false> SubViewBigEndian(size_t begin, size_t end) const;
+ protected:
+ PacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+
private:
std::forward_list<View> fragments_;
size_t length_;
diff --git a/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc b/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc
new file mode 100644
index 000000000..3a141422c
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2018 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 "packets/link_layer/link_layer_packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "link.h"
+#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/disconnect_view.h"
+#include "packets/link_layer/encrypt_connection_view.h"
+#include "packets/link_layer/inquiry_response_view.h"
+#include "packets/link_layer/inquiry_view.h"
+#include "packets/link_layer/io_capability_negative_response_view.h"
+#include "packets/link_layer/io_capability_view.h"
+#include "packets/link_layer/le_advertisement_view.h"
+#include "packets/link_layer/page_response_view.h"
+#include "packets/link_layer/page_view.h"
+#include "packets/link_layer/response_view.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+} // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LinkLayerPacketBuilderTest : public ::testing::Test {
+ public:
+ LinkLayerPacketBuilderTest() = default;
+ ~LinkLayerPacketBuilderTest() override = default;
+
+ Address source_{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}};
+ Address dest_{{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}};
+};
+
+TEST_F(LinkLayerPacketBuilderTest, constructorTest) {
+ uint8_t reason = 0xf2;
+ auto disconnect = DisconnectBuilder::Create(reason);
+ ASSERT_EQ(disconnect->size(), sizeof(reason));
+ auto wrapped_disconnect = LinkLayerPacketBuilder::WrapDisconnect(std::move(disconnect), source_, dest_);
+
+ size_t wrapped_size = sizeof(uint8_t) + sizeof(uint32_t) + 2 * sizeof(Address) + sizeof(reason);
+ ASSERT_EQ(wrapped_disconnect->size(), wrapped_size);
+ std::vector<uint8_t> wrapped_vect;
+ std::back_insert_iterator<std::vector<uint8_t>> it(wrapped_vect);
+ wrapped_disconnect->Serialize(it);
+ ASSERT_EQ(wrapped_size, wrapped_vect.size());
+
+ std::vector<uint8_t> hand_wrapped_vect;
+ // Add the size
+ hand_wrapped_vect.push_back(sizeof(uint8_t) + 2 * sizeof(Address) + sizeof(reason));
+ hand_wrapped_vect.push_back(0);
+ hand_wrapped_vect.push_back(0);
+ hand_wrapped_vect.push_back(0);
+
+ hand_wrapped_vect.push_back(static_cast<uint8_t>(Link::PacketType::DISCONNECT));
+
+ for (auto byte : source_.address) {
+ hand_wrapped_vect.push_back(byte);
+ }
+ for (auto byte : dest_.address) {
+ hand_wrapped_vect.push_back(byte);
+ }
+ hand_wrapped_vect.push_back(reason);
+ ASSERT_EQ(wrapped_vect, hand_wrapped_vect);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, disconnectTest) {
+ uint8_t reason = 0x32;
+ auto disconnect_builder = DisconnectBuilder::Create(reason);
+ auto wrapped_disconnect = LinkLayerPacketBuilder::WrapDisconnect(std::move(disconnect_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_disconnect->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_disconnect->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::DISCONNECT);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ DisconnectView disconnect = DisconnectView::GetDisconnect(view);
+ ASSERT_EQ(disconnect.GetReason(), reason);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, encryptConnectionTest) {
+ std::vector<uint8_t> key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ auto encrypt_connection_builder = EncryptConnectionBuilder::Create(key);
+ auto wrapped_encrypt_connection =
+ LinkLayerPacketBuilder::WrapEncryptConnection(std::move(encrypt_connection_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_encrypt_connection->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_encrypt_connection->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::ENCRYPT_CONNECTION);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ EncryptConnectionView encrypt_connection = EncryptConnectionView::GetEncryptConnection(view);
+ auto key_itr = encrypt_connection.GetKey();
+ ASSERT_EQ(key_itr.NumBytesRemaining(), key.size());
+ for (size_t i = 0; i < key.size(); i++) {
+ ASSERT_EQ(key[i], key_itr.extract<uint8_t>());
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, encryptConnectionResponseTest) {
+ std::vector<uint8_t> key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ auto encrypt_connection_builder = EncryptConnectionBuilder::Create(key);
+ auto wrapped_encrypt_connection_response =
+ LinkLayerPacketBuilder::WrapEncryptConnectionResponse(std::move(encrypt_connection_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_encrypt_connection_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_encrypt_connection_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::ENCRYPT_CONNECTION_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ EncryptConnectionView encrypt_connection = EncryptConnectionView::GetEncryptConnection(view);
+ auto key_itr = encrypt_connection.GetKey();
+ ASSERT_EQ(key_itr.NumBytesRemaining(), key.size());
+ for (size_t i = 0; i < key.size(); i++) {
+ ASSERT_EQ(key[i], key_itr.extract<uint8_t>());
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, inquiryTest) {
+ Inquiry::InquiryType inquiry_type = Inquiry::InquiryType::RSSI;
+ auto inquiry_builder = InquiryBuilder::Create(inquiry_type);
+ auto wrapped_inquiry = LinkLayerPacketBuilder::WrapInquiry(std::move(inquiry_builder), source_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_inquiry->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_inquiry->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(Address::kEmpty, view.GetDestinationAddress());
+ ASSERT_EQ(InquiryView::GetInquiry(view).GetType(), inquiry_type);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, standardInquiryResponseTest) {
+ uint8_t mode = 23;
+ ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+ uint16_t offset = 0x3456;
+ auto inquiry_response_builder = InquiryResponseBuilder::CreateStandard(mode, class_of_device, offset);
+ auto wrapped_inquiry =
+ LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_inquiry->Serialize(it);
+ ASSERT_EQ(packet_ptr->size(), 24u);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_inquiry->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ ASSERT_EQ(view.GetPayload().size(), 7u);
+ InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+ ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::STANDARD);
+ ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+ ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, rssiInquiryResponseTest) {
+ uint8_t mode = 23;
+ ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+ uint16_t offset = 0x3456;
+ uint8_t rssi = 0x78;
+ auto inquiry_response_builder = InquiryResponseBuilder::CreateRssi(mode, class_of_device, offset, rssi);
+ auto wrapped_inquiry =
+ LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_inquiry->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_inquiry->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+ ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::RSSI);
+ ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+ ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+ ASSERT_EQ(inquiry_response.GetRssi(), rssi);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, extendedInquiryResponseTest) {
+ uint8_t mode = 23;
+ ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+ uint16_t offset = 0x3456;
+ uint8_t rssi = 0x78;
+ auto inquiry_response_builder = InquiryResponseBuilder::CreateExtended(mode, class_of_device, offset, rssi, count);
+ auto wrapped_inquiry =
+ LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_inquiry->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_inquiry->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+ ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::EXTENDED);
+ ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+ ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+ ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+ ASSERT_EQ(inquiry_response.GetRssi(), rssi);
+ auto ext_it = inquiry_response.GetExtendedData();
+ ASSERT_EQ(ext_it.NumBytesRemaining(), count.size());
+ for (size_t i = 0; i < count.size(); i++) {
+ ASSERT_EQ(count[i], *(ext_it++));
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityRequestTest) {
+ uint8_t io_cap = 0x2;
+ uint8_t oob_data_present = 0x1;
+ uint8_t authentication_requirements = 0x5;
+ auto io_capability_builder = IoCapabilityBuilder::Create(io_cap, oob_data_present, authentication_requirements);
+ auto wrapped_io_capability_request =
+ LinkLayerPacketBuilder::WrapIoCapabilityRequest(std::move(io_capability_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_io_capability_request->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_io_capability_request->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_REQUEST);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ IoCapabilityView io_capability = IoCapabilityView::GetIoCapability(view);
+ ASSERT_EQ(io_capability.GetIoCapability(), io_cap);
+ ASSERT_EQ(io_capability.GetOobDataPresent(), oob_data_present);
+ ASSERT_EQ(io_capability.GetAuthenticationRequirements(), authentication_requirements);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityResponseTest) {
+ uint8_t io_cap = 0x2;
+ uint8_t oob_data_present = 0x1;
+ uint8_t authentication_requirements = 0x5;
+ auto io_capability_builder = IoCapabilityBuilder::Create(io_cap, oob_data_present, authentication_requirements);
+ auto wrapped_io_capability_response =
+ LinkLayerPacketBuilder::WrapIoCapabilityResponse(std::move(io_capability_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_io_capability_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_io_capability_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ IoCapabilityView io_capability = IoCapabilityView::GetIoCapability(view);
+ ASSERT_EQ(io_capability.GetIoCapability(), io_cap);
+ ASSERT_EQ(io_capability.GetOobDataPresent(), oob_data_present);
+ ASSERT_EQ(io_capability.GetAuthenticationRequirements(), authentication_requirements);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityNegativeResponseTest) {
+ uint8_t reason = 23;
+ auto io_capability_negative_response_builder = IoCapabilityNegativeResponseBuilder::Create(reason);
+ auto wrapped_io_capability_negative_response = LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+ std::move(io_capability_negative_response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_io_capability_negative_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_io_capability_negative_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ IoCapabilityNegativeResponseView io_capability_negative_response =
+ IoCapabilityNegativeResponseView::GetIoCapabilityNegativeResponse(view);
+ ASSERT_EQ(io_capability_negative_response.GetReason(), reason);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, pageTest) {
+ uint8_t allow_role_switch = 1;
+ ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+ auto page_builder = PageBuilder::Create(class_of_device, allow_role_switch);
+ auto wrapped_page = LinkLayerPacketBuilder::WrapPage(std::move(page_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_page->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_page->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::PAGE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ PageView page = PageView::GetPage(view);
+ ASSERT_EQ(page.GetAllowRoleSwitch(), allow_role_switch);
+ ASSERT_EQ(page.GetClassOfDevice(), class_of_device);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, pageResponseTest) {
+ uint8_t try_role_switch = 2;
+ auto page_response_builder = PageResponseBuilder::Create(try_role_switch);
+ auto wrapped_page_response =
+ LinkLayerPacketBuilder::WrapPageResponse(std::move(page_response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_page_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_page_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::PAGE_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ PageResponseView page_response = PageResponseView::GetPageResponse(view);
+ ASSERT_EQ(page_response.GetTryRoleSwitch(), try_role_switch);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, responseTest) {
+ uint16_t opcode = 0x1234;
+ std::vector<uint64_t> data{
+ 0x7060504030201000, 0x7161514131211101, 0x7262524232221202, 0x7363534333231303,
+ 0x7464544434241404, 0x7565554535251505, 0x7666564636261606, 0x7767574737271707,
+ 0x7868584838281808, 0x7969594939291909, 0x7a6a5a4a3a2a1a0a, 0x7b6b5b4b3b2b1b0b,
+ 0x7c6c5c4c3c2c1c0c, 0x7d6d5d4d3d2d1d0d, 0x7e6e5e4e3e2e1e0e, 0x7f6f5f4f3f2f1f0f,
+ };
+ auto response_builder = ResponseBuilder::Create(opcode, data);
+ auto wrapped_response = LinkLayerPacketBuilder::WrapResponse(std::move(response_builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ ResponseView response = ResponseView::GetResponse(view);
+ ASSERT_EQ(opcode, response.GetOpcode());
+ auto data_it = response.GetResponseData();
+ ASSERT_EQ(data.size(), data_it.NumBytesRemaining() / sizeof(uint64_t));
+ ASSERT_EQ(0u, data_it.NumBytesRemaining() % sizeof(uint64_t));
+ for (size_t i = 0; i < data.size(); i++) {
+ ASSERT_EQ(data[i], data_it.extract<uint64_t>());
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapAclTest) {
+ std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+ View count_view(count_shared, 0, count_shared->size());
+ PacketView<true> count_packet_view({count_view});
+ auto builder = ViewForwarderBuilder::Create(count_packet_view);
+ auto wrapped_acl = LinkLayerPacketBuilder::WrapAcl(std::move(builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_acl->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_acl->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::ACL);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ auto acl_view = view.GetPayload();
+ ASSERT_EQ(acl_view.size(), count_view.size());
+ for (size_t i = 0; i < count_view.size(); i++) {
+ ASSERT_EQ(acl_view[i], count_view[i]);
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapCommandTest) {
+ uint16_t opcode = 0x0102;
+ std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+ View count_view(count_shared, 0, count_shared->size());
+ PacketView<true> args({count_view});
+ auto builder = CommandBuilder::Create(opcode, args);
+ auto wrapped_command = LinkLayerPacketBuilder::WrapCommand(std::move(builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_command->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_command->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::COMMAND);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ auto command_view = CommandView::GetCommand(view);
+ ASSERT_EQ(opcode, command_view.GetOpcode());
+ auto args_itr = command_view.GetData();
+ ASSERT_EQ(args_itr.NumBytesRemaining(), count.size());
+ for (size_t i = 0; i < count.size(); i++) {
+ ASSERT_EQ(*args_itr++, count[i]);
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeAdvertisementTest) {
+ LeAdvertisement::AddressType address_type = LeAdvertisement::AddressType::RANDOM;
+ LeAdvertisement::AdvertisementType advertisement_type = LeAdvertisement::AdvertisementType::ADV_NONCONN_IND;
+ auto builder = LeAdvertisementBuilder::Create(address_type, advertisement_type, count);
+ auto wrapped_le_advertisement = LinkLayerPacketBuilder::WrapLeAdvertisement(std::move(builder), source_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_le_advertisement->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_le_advertisement->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::LE_ADVERTISEMENT);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(Address::kEmpty, view.GetDestinationAddress());
+ LeAdvertisementView le_advertisement_view = LeAdvertisementView::GetLeAdvertisementView(view);
+ ASSERT_EQ(address_type, le_advertisement_view.GetAddressType());
+ ASSERT_EQ(advertisement_type, le_advertisement_view.GetAdvertisementType());
+ auto le_advertisement_itr = le_advertisement_view.GetData();
+ ASSERT_EQ(le_advertisement_itr.NumBytesRemaining(), count.size());
+ for (size_t i = 0; i < count.size(); i++) {
+ ASSERT_EQ(*(le_advertisement_itr++), count[i]);
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeScanTest) {
+ auto le_scan = LinkLayerPacketBuilder::WrapLeScan(source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ le_scan->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), le_scan->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::LE_SCAN);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ auto le_scan_view = view.GetPayload();
+ ASSERT_EQ(0u, le_scan_view.size());
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeScanResponseTest) {
+ LeAdvertisement::AddressType address_type = LeAdvertisement::AddressType::PUBLIC_IDENTITY;
+ LeAdvertisement::AdvertisementType advertisement_type = LeAdvertisement::AdvertisementType::SCAN_RESPONSE;
+ auto builder = LeAdvertisementBuilder::Create(address_type, advertisement_type, count);
+ auto wrapped_scan_response = LinkLayerPacketBuilder::WrapLeScanResponse(std::move(builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_scan_response->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_scan_response->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::LE_SCAN_RESPONSE);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ LeAdvertisementView le_advertisement_view = LeAdvertisementView::GetLeAdvertisementView(view);
+ ASSERT_EQ(address_type, le_advertisement_view.GetAddressType());
+ ASSERT_EQ(advertisement_type, le_advertisement_view.GetAdvertisementType());
+ auto scan_response_itr = le_advertisement_view.GetData();
+ ASSERT_EQ(scan_response_itr.NumBytesRemaining(), count.size());
+ for (size_t i = 0; i < count.size(); i++) {
+ ASSERT_EQ((*scan_response_itr++), count[i]);
+ }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapScoTest) {
+ std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+ View count_view(count_shared, 0, count_shared->size());
+ PacketView<true> count_packet_view({count_view});
+ auto builder = ViewForwarderBuilder::Create(count_packet_view);
+ auto wrapped_sco = LinkLayerPacketBuilder::WrapSco(std::move(builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_sco->Serialize(it);
+
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+ ASSERT_EQ(view.size(), wrapped_sco->size());
+ ASSERT_EQ(view.GetType(), Link::PacketType::SCO);
+ ASSERT_EQ(source_, view.GetSourceAddress());
+ ASSERT_EQ(dest_, view.GetDestinationAddress());
+ auto sco_view = view.GetPayload();
+ ASSERT_EQ(sco_view.size(), count.size());
+ for (size_t i = 0; i < count.size(); i++) {
+ ASSERT_EQ(sco_view[i], count[i]);
+ }
+}
+
+} // namespace packets
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc b/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc
index 5b4ee49dc..0ddd2fc74 100644
--- a/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc
+++ b/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc
@@ -27,8 +27,11 @@
#include <sys/types.h>
#include <unistd.h>
+#include "include/link.h"
#include "model/setup/async_manager.h"
#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
std::vector<uint8_t> count = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
@@ -182,7 +185,14 @@ class LinkLayerSocketDeviceTest : public ::testing::Test {
LinkLayerPacketView NextPacket() {
std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
- LinkLayerPacketView view = LinkLayerPacketView::Create(count_shared);
+ View count_view(count_shared, 0, count_shared->size());
+ PacketView<true> args({count_view});
+ auto builder = CommandBuilder::Create(packet_id_++, args);
+ auto wrapped_command = LinkLayerPacketBuilder::WrapCommand(std::move(builder), source_, dest_);
+ std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+ wrapped_command->Serialize(it);
+ LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
return view;
}
diff --git a/vendor_libs/test_vendor_lib/types/address.h b/vendor_libs/test_vendor_lib/types/address.h
index 12e2dbbb4..1aa8c97f6 100644
--- a/vendor_libs/test_vendor_lib/types/address.h
+++ b/vendor_libs/test_vendor_lib/types/address.h
@@ -20,9 +20,6 @@
#include <string>
-namespace bluetooth {
-namespace types {
-
/** Bluetooth Address */
class Address final {
public:
@@ -77,8 +74,3 @@ inline std::ostream& operator<<(std::ostream& os, const Address& a) {
os << a.ToString();
return os;
}
-
-} // namespace types
-} // namespace bluetooth
-
-using ::bluetooth::types::Address; // TODO, remove
diff --git a/vendor_libs/test_vendor_lib/types/class_of_device.h b/vendor_libs/test_vendor_lib/types/class_of_device.h
index 4c37ebf26..8c2ab37e8 100644
--- a/vendor_libs/test_vendor_lib/types/class_of_device.h
+++ b/vendor_libs/test_vendor_lib/types/class_of_device.h
@@ -20,9 +20,6 @@
#include <string>
-namespace bluetooth {
-namespace types {
-
/** Bluetooth Class of Device */
class ClassOfDevice final {
public:
@@ -55,8 +52,3 @@ inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) {
os << c.ToString();
return os;
}
-
-} // namespace types
-} // namespace bluetooth
-
-using ::bluetooth::types::ClassOfDevice; // TODO, remove \ No newline at end of file