| /****************************************************************************** |
| * |
| * Copyright 2009-2012 Broadcom Corporation |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * |
| * Filename: bluetooth.c |
| * |
| * Description: Bluetooth HAL implementation |
| * |
| ******************************************************************************/ |
| |
| #define LOG_TAG "bt_btif" |
| |
| #include <base/logging.h> |
| #include <hardware/bluetooth.h> |
| #include <hardware/bluetooth_headset_interface.h> |
| #include <hardware/bt_av.h> |
| #include <hardware/bt_csis.h> |
| #include <hardware/bt_gatt.h> |
| #include <hardware/bt_has.h> |
| #include <hardware/bt_hd.h> |
| #include <hardware/bt_hearing_aid.h> |
| #include <hardware/bt_hf_client.h> |
| #include <hardware/bt_hh.h> |
| #include <hardware/bt_le_audio.h> |
| #include <hardware/bt_pan.h> |
| #include <hardware/bt_rc.h> |
| #include <hardware/bt_sdp.h> |
| #include <hardware/bt_sock.h> |
| #include <hardware/bt_vc.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include "audio_hal_interface/a2dp_encoding.h" |
| #include "bt_utils.h" |
| #include "bta/include/bta_csis_api.h" |
| #include "bta/include/bta_has_api.h" |
| #include "bta/include/bta_hearing_aid_api.h" |
| #include "bta/include/bta_hf_client_api.h" |
| #include "bta/include/bta_le_audio_api.h" |
| #include "bta/include/bta_le_audio_broadcaster_api.h" |
| #include "bta/include/bta_vc_api.h" |
| #include "btif/avrcp/avrcp_service.h" |
| #include "btif/include/stack_manager.h" |
| #include "btif_a2dp.h" |
| #include "btif_activity_attribution.h" |
| #include "btif_api.h" |
| #include "btif_av.h" |
| #include "btif_bqr.h" |
| #include "btif_config.h" |
| #include "btif_debug_conn.h" |
| #include "btif_hf.h" |
| #include "btif_keystore.h" |
| #include "btif_metrics_logging.h" |
| #include "btif_storage.h" |
| #include "common/address_obfuscator.h" |
| #include "common/metric_id_allocator.h" |
| #include "common/metrics.h" |
| #include "common/os_utils.h" |
| #include "device/include/interop.h" |
| #include "gd/common/init_flags.h" |
| #include "gd/os/parameter_provider.h" |
| #include "main/shim/dumpsys.h" |
| #include "main/shim/shim.h" |
| #include "osi/include/alarm.h" |
| #include "osi/include/allocation_tracker.h" |
| #include "osi/include/allocator.h" |
| #include "osi/include/log.h" |
| #include "osi/include/osi.h" |
| #include "osi/include/wakelock.h" |
| #include "stack/gatt/connection_manager.h" |
| #include "stack/include/avdt_api.h" |
| #include "stack/include/btm_api.h" |
| #include "stack/include/btu.h" |
| #include "types/raw_address.h" |
| |
| using bluetooth::csis::CsisClientInterface; |
| using bluetooth::has::HasClientInterface; |
| using bluetooth::hearing_aid::HearingAidInterface; |
| #ifndef TARGET_FLOSS |
| using bluetooth::le_audio::LeAudioBroadcasterInterface; |
| using bluetooth::le_audio::LeAudioClientInterface; |
| #endif |
| using bluetooth::vc::VolumeControlInterface; |
| |
| /******************************************************************************* |
| * Static variables |
| ******************************************************************************/ |
| |
| static bt_callbacks_t* bt_hal_cbacks = NULL; |
| bool restricted_mode = false; |
| bool common_criteria_mode = false; |
| const int CONFIG_COMPARE_ALL_PASS = 0b11; |
| int common_criteria_config_compare_result = CONFIG_COMPARE_ALL_PASS; |
| bool is_local_device_atv = false; |
| |
| /******************************************************************************* |
| * Externs |
| ******************************************************************************/ |
| |
| /* list all extended interfaces here */ |
| |
| /* handsfree profile - client */ |
| extern const bthf_client_interface_t* btif_hf_client_get_interface(); |
| /* advanced audio profile */ |
| extern const btav_source_interface_t* btif_av_get_src_interface(); |
| extern const btav_sink_interface_t* btif_av_get_sink_interface(); |
| /*rfc l2cap*/ |
| extern const btsock_interface_t* btif_sock_get_interface(); |
| /* hid host profile */ |
| extern const bthh_interface_t* btif_hh_get_interface(); |
| /* hid device profile */ |
| extern const bthd_interface_t* btif_hd_get_interface(); |
| /*pan*/ |
| extern const btpan_interface_t* btif_pan_get_interface(); |
| /* gatt */ |
| extern const btgatt_interface_t* btif_gatt_get_interface(); |
| /* avrc target */ |
| extern const btrc_interface_t* btif_rc_get_interface(); |
| /* avrc controller */ |
| extern const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(); |
| /*SDP search client*/ |
| extern const btsdp_interface_t* btif_sdp_get_interface(); |
| /*Hearing Aid client*/ |
| extern HearingAidInterface* btif_hearing_aid_get_interface(); |
| #ifndef TARGET_FLOSS |
| /* Hearing Access client */ |
| extern HasClientInterface* btif_has_client_get_interface(); |
| /* LeAudio testi client */ |
| extern LeAudioClientInterface* btif_le_audio_get_interface(); |
| /* LeAudio Broadcaster */ |
| extern LeAudioBroadcasterInterface* btif_le_audio_broadcaster_get_interface(); |
| #endif |
| /* Coordinated Set Service Client */ |
| extern CsisClientInterface* btif_csis_client_get_interface(); |
| /* Volume Control client */ |
| extern VolumeControlInterface* btif_volume_control_get_interface(); |
| |
| /******************************************************************************* |
| * Functions |
| ******************************************************************************/ |
| |
| static bool interface_ready(void) { return bt_hal_cbacks != NULL; } |
| void set_hal_cbacks(bt_callbacks_t* callbacks) { bt_hal_cbacks = callbacks; } |
| |
| static bool is_profile(const char* p1, const char* p2) { |
| CHECK(p1); |
| CHECK(p2); |
| return strlen(p1) == strlen(p2) && strncmp(p1, p2, strlen(p2)) == 0; |
| } |
| |
| /***************************************************************************** |
| * |
| * BLUETOOTH HAL INTERFACE FUNCTIONS |
| * |
| ****************************************************************************/ |
| |
| const std::vector<std::string> get_allowed_bt_package_name(void); |
| void handle_migration(const std::string& dst, |
| const std::vector<std::string>& allowed_bt_package_name); |
| |
| static int init(bt_callbacks_t* callbacks, bool start_restricted, |
| bool is_common_criteria_mode, int config_compare_result, |
| const char** init_flags, bool is_atv, |
| const char* user_data_directory) { |
| LOG_INFO( |
| "%s: start restricted = %d ; common criteria mode = %d, config compare " |
| "result = %d", |
| __func__, start_restricted, is_common_criteria_mode, |
| config_compare_result); |
| |
| if (user_data_directory != nullptr) { |
| handle_migration(std::string(user_data_directory), |
| get_allowed_bt_package_name()); |
| } |
| |
| bluetooth::common::InitFlags::Load(init_flags); |
| |
| if (interface_ready()) return BT_STATUS_DONE; |
| |
| #ifdef BLUEDROID_DEBUG |
| allocation_tracker_init(); |
| #endif |
| |
| set_hal_cbacks(callbacks); |
| |
| restricted_mode = start_restricted; |
| |
| bluetooth::os::ParameterProvider::SetBtKeystoreInterface( |
| bluetooth::bluetooth_keystore::getBluetoothKeystoreInterface()); |
| bluetooth::os::ParameterProvider::SetCommonCriteriaMode( |
| is_common_criteria_mode); |
| if (is_bluetooth_uid() && is_common_criteria_mode) { |
| bluetooth::os::ParameterProvider::SetCommonCriteriaConfigCompareResult( |
| config_compare_result); |
| } else { |
| bluetooth::os::ParameterProvider::SetCommonCriteriaConfigCompareResult( |
| CONFIG_COMPARE_ALL_PASS); |
| } |
| |
| is_local_device_atv = is_atv; |
| |
| stack_manager_get_interface()->init_stack(); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int enable() { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| stack_manager_get_interface()->start_up_stack_async(); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int disable(void) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| stack_manager_get_interface()->shut_down_stack_async(); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); } |
| |
| bool is_restricted_mode() { return restricted_mode; } |
| bool is_common_criteria_mode() { |
| return is_bluetooth_uid() && common_criteria_mode; |
| } |
| // if common criteria mode disable, will always return |
| // CONFIG_COMPARE_ALL_PASS(0b11) indicate don't check config checksum. |
| int get_common_criteria_config_compare_result() { |
| return is_common_criteria_mode() ? common_criteria_config_compare_result |
| : CONFIG_COMPARE_ALL_PASS; |
| } |
| |
| bool is_atv_device() { return is_local_device_atv; } |
| |
| static int get_adapter_properties(void) { |
| if (!btif_is_enabled()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_get_adapter_properties)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int get_adapter_property(bt_property_type_t type) { |
| /* Allow get_adapter_property only for BDADDR and BDNAME if BT is disabled */ |
| if (!btif_is_enabled() && (type != BT_PROPERTY_BDADDR) && |
| (type != BT_PROPERTY_BDNAME) && (type != BT_PROPERTY_CLASS_OF_DEVICE)) |
| return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_get_adapter_property, type)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int set_adapter_property(const bt_property_t* property) { |
| if (!btif_is_enabled()) return BT_STATUS_NOT_READY; |
| |
| switch (property->type) { |
| case BT_PROPERTY_BDNAME: |
| case BT_PROPERTY_ADAPTER_SCAN_MODE: |
| case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: |
| case BT_PROPERTY_CLASS_OF_DEVICE: |
| case BT_PROPERTY_LOCAL_IO_CAPS: |
| case BT_PROPERTY_LOCAL_IO_CAPS_BLE: |
| break; |
| default: |
| return BT_STATUS_FAIL; |
| } |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce( |
| [](bt_property_t* property) { |
| btif_set_adapter_property(property); |
| osi_free(property); |
| }, |
| property_deep_copy(property))); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int get_remote_device_properties(RawAddress* remote_addr) { |
| if (!btif_is_enabled()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_get_remote_device_properties, |
| *remote_addr)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int get_remote_device_property(RawAddress* remote_addr, |
| bt_property_type_t type) { |
| if (!btif_is_enabled()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_get_remote_device_property, |
| *remote_addr, type)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int set_remote_device_property(RawAddress* remote_addr, |
| const bt_property_t* property) { |
| if (!btif_is_enabled()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread( |
| FROM_HERE, base::BindOnce( |
| [](RawAddress remote_addr, bt_property_t* property) { |
| btif_set_remote_device_property(&remote_addr, property); |
| osi_free(property); |
| }, |
| *remote_addr, property_deep_copy(property))); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int get_remote_services(RawAddress* remote_addr, int transport) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_get_remote_services, |
| *remote_addr, transport)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int start_discovery(void) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_start_discovery)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int cancel_discovery(void) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_cancel_discovery)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int create_bond(const RawAddress* bd_addr, int transport) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (btif_dm_pairing_is_busy()) return BT_STATUS_BUSY; |
| |
| do_in_main_thread(FROM_HERE, |
| base::BindOnce(btif_dm_create_bond, *bd_addr, transport)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int create_bond_out_of_band(const RawAddress* bd_addr, int transport, |
| const bt_oob_data_t* p192_data, |
| const bt_oob_data_t* p256_data) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (btif_dm_pairing_is_busy()) return BT_STATUS_BUSY; |
| |
| do_in_main_thread(FROM_HERE, |
| base::BindOnce(btif_dm_create_bond_out_of_band, *bd_addr, |
| transport, *p192_data, *p256_data)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int generate_local_oob_data(tBT_TRANSPORT transport) { |
| LOG_INFO("%s", __func__); |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| return do_in_main_thread( |
| FROM_HERE, base::BindOnce(btif_dm_generate_local_oob_data, transport)); |
| } |
| |
| static int cancel_bond(const RawAddress* bd_addr) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_cancel_bond, *bd_addr)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int remove_bond(const RawAddress* bd_addr) { |
| if (is_restricted_mode() && !btif_storage_is_restricted_device(bd_addr)) |
| return BT_STATUS_SUCCESS; |
| |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_remove_bond, *bd_addr)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int get_connection_state(const RawAddress* bd_addr) { |
| if (!interface_ready()) return 0; |
| |
| return btif_dm_get_connection_state(bd_addr); |
| } |
| |
| static int pin_reply(const RawAddress* bd_addr, uint8_t accept, uint8_t pin_len, |
| bt_pin_code_t* pin_code) { |
| bt_pin_code_t tmp_pin_code; |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (pin_code == nullptr || pin_len > PIN_CODE_LEN) return BT_STATUS_FAIL; |
| |
| memcpy(&tmp_pin_code, pin_code, pin_len); |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_pin_reply, *bd_addr, |
| accept, pin_len, tmp_pin_code)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int ssp_reply(const RawAddress* bd_addr, bt_ssp_variant_t variant, |
| uint8_t accept, uint32_t passkey) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (variant == BT_SSP_VARIANT_PASSKEY_ENTRY) return BT_STATUS_FAIL; |
| |
| do_in_main_thread( |
| FROM_HERE, base::BindOnce(btif_dm_ssp_reply, *bd_addr, variant, accept)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int read_energy_info() { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_read_energy_info)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int clear_event_filter() { |
| LOG_VERBOSE("%s", __func__); |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_clear_event_filter)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static void dump(int fd, const char** arguments) { |
| btif_debug_conn_dump(fd); |
| btif_debug_bond_event_dump(fd); |
| btif_debug_linkkey_type_dump(fd); |
| btif_debug_a2dp_dump(fd); |
| btif_debug_av_dump(fd); |
| bta_debug_av_dump(fd); |
| stack_debug_avdtp_api_dump(fd); |
| bluetooth::avrcp::AvrcpService::DebugDump(fd); |
| btif_debug_config_dump(fd); |
| BTA_HfClientDumpStatistics(fd); |
| wakelock_debug_dump(fd); |
| osi_allocator_debug_dump(fd); |
| alarm_debug_dump(fd); |
| bluetooth::csis::CsisClient::DebugDump(fd); |
| #ifndef TARGET_FLOSS |
| le_audio::has::HasClient::DebugDump(fd); |
| #endif |
| HearingAid::DebugDump(fd); |
| #ifndef TARGET_FLOSS |
| LeAudioClient::DebugDump(fd); |
| LeAudioBroadcaster::DebugDump(fd); |
| VolumeControl::DebugDump(fd); |
| #endif |
| connection_manager::dump(fd); |
| bluetooth::bqr::DebugDump(fd); |
| bluetooth::shim::Dump(fd, arguments); |
| } |
| |
| static void dumpMetrics(std::string* output) { |
| bluetooth::common::BluetoothMetricsLogger::GetInstance()->WriteString(output); |
| } |
| |
| static const void* get_profile_interface(const char* profile_id) { |
| LOG_INFO("%s: id = %s", __func__, profile_id); |
| |
| /* sanity check */ |
| if (!interface_ready()) return NULL; |
| |
| /* check for supported profile interfaces */ |
| if (is_profile(profile_id, BT_PROFILE_HANDSFREE_ID)) |
| return bluetooth::headset::GetInterface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_HANDSFREE_CLIENT_ID)) |
| return btif_hf_client_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_SOCKETS_ID)) |
| return btif_sock_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_PAN_ID)) |
| return btif_pan_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID)) |
| return btif_av_get_src_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_SINK_ID)) |
| return btif_av_get_sink_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_HIDHOST_ID)) |
| return btif_hh_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_HIDDEV_ID)) |
| return btif_hd_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_SDP_CLIENT_ID)) |
| return btif_sdp_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_GATT_ID)) |
| return btif_gatt_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_AV_RC_ID)) |
| return btif_rc_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_AV_RC_CTRL_ID)) |
| return btif_rc_ctrl_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_HEARING_AID_ID)) |
| return btif_hearing_aid_get_interface(); |
| |
| #ifndef TARGET_FLOSS |
| if (is_profile(profile_id, BT_PROFILE_HAP_CLIENT_ID)) |
| return btif_has_client_get_interface(); |
| #endif |
| |
| if (is_profile(profile_id, BT_KEYSTORE_ID)) |
| return bluetooth::bluetooth_keystore::getBluetoothKeystoreInterface(); |
| |
| if (is_profile(profile_id, BT_ACTIVITY_ATTRIBUTION_ID)) { |
| return bluetooth::activity_attribution::get_activity_attribution_instance(); |
| } |
| |
| #ifndef TARGET_FLOSS |
| if (is_profile(profile_id, BT_PROFILE_LE_AUDIO_ID)) |
| return btif_le_audio_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_LE_AUDIO_BROADCASTER_ID)) |
| return btif_le_audio_broadcaster_get_interface(); |
| #endif |
| |
| if (is_profile(profile_id, BT_PROFILE_VC_ID)) |
| return btif_volume_control_get_interface(); |
| |
| if (is_profile(profile_id, BT_PROFILE_CSIS_CLIENT_ID)) |
| return btif_csis_client_get_interface(); |
| |
| return NULL; |
| } |
| |
| int dut_mode_configure(uint8_t enable) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (!stack_manager_get_interface()->get_stack_is_running()) |
| return BT_STATUS_NOT_READY; |
| |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_dut_mode_configure, enable)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| if (!btif_is_dut_mode()) return BT_STATUS_FAIL; |
| |
| uint8_t* copy = (uint8_t*)osi_calloc(len); |
| memcpy(copy, buf, len); |
| |
| do_in_main_thread(FROM_HERE, |
| base::BindOnce( |
| [](uint16_t opcode, uint8_t* buf, uint8_t len) { |
| btif_dut_mode_send(opcode, buf, len); |
| osi_free(buf); |
| }, |
| opcode, copy, len)); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len) { |
| if (!interface_ready()) return BT_STATUS_NOT_READY; |
| |
| switch (opcode) { |
| case HCI_BLE_TRANSMITTER_TEST: |
| if (len != 3) return BT_STATUS_PARM_INVALID; |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_ble_transmitter_test, |
| buf[0], buf[1], buf[2])); |
| break; |
| case HCI_BLE_RECEIVER_TEST: |
| if (len != 1) return BT_STATUS_PARM_INVALID; |
| do_in_main_thread(FROM_HERE, |
| base::BindOnce(btif_ble_receiver_test, buf[0])); |
| break; |
| case HCI_BLE_TEST_END: |
| do_in_main_thread(FROM_HERE, base::BindOnce(btif_ble_test_end)); |
| break; |
| default: |
| return BT_STATUS_UNSUPPORTED; |
| } |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static bt_os_callouts_t* wakelock_os_callouts_saved = nullptr; |
| |
| static int acquire_wake_lock_cb(const char* lock_name) { |
| return do_in_jni_thread( |
| FROM_HERE, base::Bind(base::IgnoreResult( |
| wakelock_os_callouts_saved->acquire_wake_lock), |
| lock_name)); |
| } |
| |
| static int release_wake_lock_cb(const char* lock_name) { |
| return do_in_jni_thread( |
| FROM_HERE, base::Bind(base::IgnoreResult( |
| wakelock_os_callouts_saved->release_wake_lock), |
| lock_name)); |
| } |
| |
| static bt_os_callouts_t wakelock_os_callouts_jni = { |
| sizeof(wakelock_os_callouts_jni), |
| nullptr /* not used */, |
| acquire_wake_lock_cb, |
| release_wake_lock_cb, |
| }; |
| |
| static int set_os_callouts(bt_os_callouts_t* callouts) { |
| wakelock_os_callouts_saved = callouts; |
| wakelock_set_os_callouts(&wakelock_os_callouts_jni); |
| return BT_STATUS_SUCCESS; |
| } |
| |
| static int config_clear(void) { |
| LOG_INFO("%s", __func__); |
| return btif_config_clear() ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; |
| } |
| |
| static bluetooth::avrcp::ServiceInterface* get_avrcp_service(void) { |
| return bluetooth::avrcp::AvrcpService::GetServiceInterface(); |
| } |
| |
| static std::string obfuscate_address(const RawAddress& address) { |
| return bluetooth::common::AddressObfuscator::GetInstance()->Obfuscate( |
| address); |
| } |
| |
| static int get_metric_id(const RawAddress& address) { |
| return allocate_metric_id_from_metric_id_allocator(address); |
| } |
| |
| static int set_dynamic_audio_buffer_size(int codec, int size) { |
| return btif_set_dynamic_audio_buffer_size(codec, size); |
| } |
| |
| static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { |
| LOG_INFO("%s %s", __func__, allowed ? "true" : "false"); |
| bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed(allowed); |
| return true; |
| } |
| |
| EXPORT_SYMBOL bt_interface_t bluetoothInterface = { |
| sizeof(bluetoothInterface), |
| init, |
| enable, |
| disable, |
| cleanup, |
| get_adapter_properties, |
| get_adapter_property, |
| set_adapter_property, |
| get_remote_device_properties, |
| get_remote_device_property, |
| set_remote_device_property, |
| nullptr, |
| get_remote_services, |
| start_discovery, |
| cancel_discovery, |
| create_bond, |
| create_bond_out_of_band, |
| remove_bond, |
| cancel_bond, |
| get_connection_state, |
| pin_reply, |
| ssp_reply, |
| get_profile_interface, |
| dut_mode_configure, |
| dut_mode_send, |
| le_test_mode, |
| set_os_callouts, |
| read_energy_info, |
| dump, |
| dumpMetrics, |
| config_clear, |
| interop_database_clear, |
| interop_database_add, |
| get_avrcp_service, |
| obfuscate_address, |
| get_metric_id, |
| set_dynamic_audio_buffer_size, |
| generate_local_oob_data, |
| allow_low_latency_audio, |
| clear_event_filter}; |
| |
| // callback reporting helpers |
| |
| bt_property_t* property_deep_copy_array(int num_properties, |
| bt_property_t* properties) { |
| bt_property_t* copy = nullptr; |
| if (num_properties > 0) { |
| size_t content_len = 0; |
| for (int i = 0; i < num_properties; i++) { |
| auto len = properties[i].len; |
| if (len > 0) { |
| content_len += len; |
| } |
| } |
| |
| copy = (bt_property_t*)osi_calloc((sizeof(bt_property_t) * num_properties) + |
| content_len); |
| ASSERT(copy != nullptr); |
| uint8_t* content = (uint8_t*)(copy + num_properties); |
| |
| for (int i = 0; i < num_properties; i++) { |
| auto len = properties[i].len; |
| copy[i].type = properties[i].type; |
| copy[i].len = len; |
| if (len <= 0) { |
| continue; |
| } |
| copy[i].val = content; |
| memcpy(content, properties[i].val, len); |
| content += len; |
| } |
| } |
| return copy; |
| } |
| |
| void invoke_adapter_state_changed_cb(bt_state_t state) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bt_state_t state) { |
| HAL_CBACK(bt_hal_cbacks, |
| adapter_state_changed_cb, state); |
| }, |
| state)); |
| } |
| |
| void invoke_adapter_properties_cb(bt_status_t status, int num_properties, |
| bt_property_t* properties) { |
| do_in_jni_thread(FROM_HERE, |
| base::BindOnce( |
| [](bt_status_t status, int num_properties, |
| bt_property_t* properties) { |
| HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, status, |
| num_properties, properties); |
| if (properties) { |
| osi_free(properties); |
| } |
| }, |
| status, num_properties, |
| property_deep_copy_array(num_properties, properties))); |
| } |
| |
| void invoke_remote_device_properties_cb(bt_status_t status, RawAddress bd_addr, |
| int num_properties, |
| bt_property_t* properties) { |
| do_in_jni_thread( |
| FROM_HERE, base::BindOnce( |
| [](bt_status_t status, RawAddress bd_addr, |
| int num_properties, bt_property_t* properties) { |
| HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, |
| status, &bd_addr, num_properties, properties); |
| if (properties) { |
| osi_free(properties); |
| } |
| }, |
| status, bd_addr, num_properties, |
| property_deep_copy_array(num_properties, properties))); |
| } |
| |
| void invoke_device_found_cb(int num_properties, bt_property_t* properties) { |
| do_in_jni_thread(FROM_HERE, |
| base::BindOnce( |
| [](int num_properties, bt_property_t* properties) { |
| HAL_CBACK(bt_hal_cbacks, device_found_cb, |
| num_properties, properties); |
| if (properties) { |
| osi_free(properties); |
| } |
| }, |
| num_properties, |
| property_deep_copy_array(num_properties, properties))); |
| } |
| |
| void invoke_discovery_state_changed_cb(bt_discovery_state_t state) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bt_discovery_state_t state) { |
| HAL_CBACK(bt_hal_cbacks, |
| discovery_state_changed_cb, |
| state); |
| }, |
| state)); |
| } |
| |
| void invoke_pin_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, |
| uint32_t cod, bool min_16_digit) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](RawAddress bd_addr, bt_bdname_t bd_name, |
| uint32_t cod, bool min_16_digit) { |
| HAL_CBACK(bt_hal_cbacks, pin_request_cb, |
| &bd_addr, &bd_name, cod, |
| min_16_digit); |
| }, |
| bd_addr, bd_name, cod, min_16_digit)); |
| } |
| |
| void invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, |
| uint32_t cod, bt_ssp_variant_t pairing_variant, |
| uint32_t pass_key) { |
| do_in_jni_thread(FROM_HERE, |
| base::BindOnce( |
| [](RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, |
| bt_ssp_variant_t pairing_variant, uint32_t pass_key) { |
| HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, |
| &bd_name, cod, pairing_variant, pass_key); |
| }, |
| bd_addr, bd_name, cod, pairing_variant, pass_key)); |
| } |
| |
| void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, |
| Octet16 r, RawAddress raw_address, |
| uint8_t address_type) { |
| LOG_INFO("%s", __func__); |
| bt_oob_data_t oob_data = {}; |
| const char* local_name; |
| BTM_ReadLocalDeviceName(&local_name); |
| for (int i = 0; i < BTM_MAX_LOC_BD_NAME_LEN; i++) { |
| oob_data.device_name[i] = local_name[i]; |
| } |
| |
| // Set the local address |
| int j = 5; |
| for (int i = 0; i < 6; i++) { |
| oob_data.address[i] = raw_address.address[j]; |
| j--; |
| } |
| oob_data.address[6] = address_type; |
| |
| // Each value (for C and R) is 16 octets in length |
| bool c_empty = true; |
| for (int i = 0; i < 16; i++) { |
| // C cannot be all 0s, if so then we want to fail |
| if (c[i] != 0) c_empty = false; |
| oob_data.c[i] = c[i]; |
| // R is optional and may be empty |
| oob_data.r[i] = r[i]; |
| } |
| oob_data.is_valid = valid && !c_empty; |
| // The oob_data_length is 2 octects in length. The value includes the length |
| // of itself. 16 + 16 + 2 = 34 Data 0x0022 Little Endian order 0x2200 |
| oob_data.oob_data_length[0] = 0; |
| oob_data.oob_data_length[1] = 34; |
| bt_status_t status = do_in_jni_thread( |
| FROM_HERE, base::BindOnce( |
| [](tBT_TRANSPORT t, bt_oob_data_t oob_data) { |
| HAL_CBACK(bt_hal_cbacks, generate_local_oob_data_cb, t, |
| oob_data); |
| }, |
| t, oob_data)); |
| if (status != BT_STATUS_SUCCESS) { |
| LOG_ERROR("%s: Failed to call callback!", __func__); |
| } |
| } |
| |
| void invoke_bond_state_changed_cb(bt_status_t status, RawAddress bd_addr, |
| bt_bond_state_t state, int fail_reason) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bt_status_t status, RawAddress bd_addr, |
| bt_bond_state_t state, int fail_reason) { |
| HAL_CBACK(bt_hal_cbacks, |
| bond_state_changed_cb, status, |
| &bd_addr, state, fail_reason); |
| }, |
| status, bd_addr, state, fail_reason)); |
| } |
| |
| void invoke_address_consolidate_cb(RawAddress main_bd_addr, |
| RawAddress secondary_bd_addr) { |
| do_in_jni_thread( |
| FROM_HERE, base::BindOnce( |
| [](RawAddress main_bd_addr, RawAddress secondary_bd_addr) { |
| HAL_CBACK(bt_hal_cbacks, address_consolidate_cb, |
| &main_bd_addr, &secondary_bd_addr); |
| }, |
| main_bd_addr, secondary_bd_addr)); |
| } |
| |
| void invoke_le_address_associate_cb(RawAddress main_bd_addr, |
| RawAddress secondary_bd_addr) { |
| do_in_jni_thread( |
| FROM_HERE, base::BindOnce( |
| [](RawAddress main_bd_addr, RawAddress secondary_bd_addr) { |
| HAL_CBACK(bt_hal_cbacks, le_address_associate_cb, |
| &main_bd_addr, &secondary_bd_addr); |
| }, |
| main_bd_addr, secondary_bd_addr)); |
| } |
| void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr, |
| bt_acl_state_t state, int transport_link_type, |
| bt_hci_error_code_t hci_reason) { |
| do_in_jni_thread( |
| FROM_HERE, |
| base::BindOnce( |
| [](bt_status_t status, RawAddress bd_addr, bt_acl_state_t state, |
| int transport_link_type, bt_hci_error_code_t hci_reason) { |
| HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, status, &bd_addr, |
| state, transport_link_type, hci_reason); |
| }, |
| status, bd_addr, state, transport_link_type, hci_reason)); |
| } |
| |
| void invoke_thread_evt_cb(bt_cb_thread_evt event) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bt_cb_thread_evt event) { |
| HAL_CBACK(bt_hal_cbacks, thread_evt_cb, |
| event); |
| if (event == DISASSOCIATE_JVM) { |
| bt_hal_cbacks = NULL; |
| } |
| }, |
| event)); |
| } |
| |
| void invoke_le_test_mode_cb(bt_status_t status, uint16_t count) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bt_status_t status, uint16_t count) { |
| HAL_CBACK(bt_hal_cbacks, le_test_mode_cb, |
| status, count); |
| }, |
| status, count)); |
| } |
| |
| // takes ownership of |uid_data| |
| void invoke_energy_info_cb(bt_activity_energy_info energy_info, |
| bt_uid_traffic_t* uid_data) { |
| do_in_jni_thread( |
| FROM_HERE, |
| base::BindOnce( |
| [](bt_activity_energy_info energy_info, bt_uid_traffic_t* uid_data) { |
| HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info, uid_data); |
| osi_free(uid_data); |
| }, |
| energy_info, uid_data)); |
| } |
| |
| void invoke_link_quality_report_cb( |
| uint64_t timestamp, int report_id, int rssi, int snr, |
| int retransmission_count, int packets_not_receive_count, |
| int negative_acknowledgement_count) { |
| do_in_jni_thread( |
| FROM_HERE, |
| base::BindOnce( |
| [](uint64_t timestamp, int report_id, int rssi, int snr, |
| int retransmission_count, int packets_not_receive_count, |
| int negative_acknowledgement_count) { |
| HAL_CBACK(bt_hal_cbacks, link_quality_report_cb, |
| timestamp, report_id, rssi, snr, retransmission_count, |
| packets_not_receive_count, |
| negative_acknowledgement_count); |
| }, |
| timestamp, report_id, rssi, snr, retransmission_count, |
| packets_not_receive_count, negative_acknowledgement_count)); |
| } |
| |
| void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) { |
| do_in_jni_thread( |
| FROM_HERE, |
| base::BindOnce( |
| [](bool is_low_latency_buffer_size) { |
| HAL_CBACK(bt_hal_cbacks, switch_buffer_size_cb, |
| is_low_latency_buffer_size); |
| }, |
| is_low_latency_buffer_size)); |
| } |
| |
| void invoke_switch_codec_cb(bool is_low_latency_buffer_size) { |
| do_in_jni_thread(FROM_HERE, base::BindOnce( |
| [](bool is_low_latency_buffer_size) { |
| HAL_CBACK(bt_hal_cbacks, switch_codec_cb, |
| is_low_latency_buffer_size); |
| }, |
| is_low_latency_buffer_size)); |
| } |