diff options
56 files changed, 1302 insertions, 558 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING index d29c2f7d0..8b050569b 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -78,7 +78,7 @@ "host" : true }, { - "name" : "net_test_stack_a2dp_native", + "name" : "net_test_btif_rc", "host" : true } ] diff --git a/binder/android/bluetooth/IBluetoothManager.aidl b/binder/android/bluetooth/IBluetoothManager.aidl index 2e1270048..8a80d4991 100644 --- a/binder/android/bluetooth/IBluetoothManager.aidl +++ b/binder/android/bluetooth/IBluetoothManager.aidl @@ -46,6 +46,8 @@ interface IBluetoothManager String getAddress(); String getName(); + boolean onFactoryReset(); + boolean isBleScanAlwaysAvailable(); int updateBleAppCount(IBinder b, boolean enable, String packageName); boolean isBleAppPresent(); diff --git a/binder/android/bluetooth/IBluetoothPan.aidl b/binder/android/bluetooth/IBluetoothPan.aidl index 16b6ddff8..4052aa4a1 100644 --- a/binder/android/bluetooth/IBluetoothPan.aidl +++ b/binder/android/bluetooth/IBluetoothPan.aidl @@ -26,7 +26,7 @@ import android.bluetooth.BluetoothDevice; interface IBluetoothPan { // Public API boolean isTetheringOn(); - void setBluetoothTethering(boolean value); + void setBluetoothTethering(boolean value, String pkgName); boolean connect(in BluetoothDevice device); boolean disconnect(in BluetoothDevice device); List<BluetoothDevice> getConnectedDevices(); diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc index b022b43af..7cd70561c 100644 --- a/bta/av/bta_av_aact.cc +++ b/bta/av/bta_av_aact.cc @@ -1246,7 +1246,6 @@ void bta_av_str_opened(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { open.chnl = p_scb->chnl; open.hndl = p_scb->hndl; open.status = BTA_AV_SUCCESS; - open.starting = bta_av_chk_start(p_scb); open.edr = 0; p = BTM_ReadRemoteFeatures(p_scb->PeerAddress()); if (p != NULL) { @@ -1262,8 +1261,10 @@ void bta_av_str_opened(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr, p_scb->hdi); #endif if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) { + open.starting = false; open.sep = AVDT_TSEP_SNK; } else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK) { + open.starting = bta_av_chk_start(p_scb); open.sep = AVDT_TSEP_SRC; } diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc index 34516fcdd..bdd8a70fa 100644 --- a/bta/av/bta_av_main.cc +++ b/bta/av/bta_av_main.cc @@ -1108,8 +1108,10 @@ bool bta_av_link_role_ok(tBTA_AV_SCB* p_scb, uint8_t bits) { "%s: peer %s BTM_SwitchRole(BTM_ROLE_MASTER) error: %d", __func__, p_scb->PeerAddress().ToString().c_str(), status); } - is_ok = false; - p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_START; + if (status != BTM_DEV_BLACKLISTED) { + is_ok = false; + p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_START; + } } } diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc index a1a94b0e3..80effa372 100644 --- a/bta/av/bta_av_ssm.cc +++ b/bta/av/bta_av_ssm.cc @@ -329,7 +329,7 @@ static const uint8_t bta_av_sst_open[][BTA_AV_NUM_COLS] = { /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST}, /* AVRC_TIMER_EVT */ - {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START, BTA_AV_OPEN_SST}, + {BTA_AV_OPEN_RC, BTA_AV_SIGNORE, BTA_AV_OPEN_SST}, /* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST}, /* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST}, diff --git a/bta/hearing_aid/hearing_aid.cc b/bta/hearing_aid/hearing_aid.cc index fb7cab71a..867c6282b 100644 --- a/bta/hearing_aid/hearing_aid.cc +++ b/bta/hearing_aid/hearing_aid.cc @@ -390,6 +390,13 @@ class HearingAidImpl : public HearingAid { hearingDevice->connection_update_status = AWAITING; } + tACL_CONN* p_acl = btm_bda_to_acl(address, BT_TRANSPORT_LE); + if (p_acl != nullptr && controller_get_interface()->supports_ble_2m_phy() && + HCI_LE_2M_PHY_SUPPORTED(p_acl->peer_le_features)) { + LOG(INFO) << address << " set preferred PHY to 2M"; + BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0); + } + // Set data length // TODO(jpawlowski: for 16khz only 87 is required, optimize BTM_SetBleDataLength(address, 167); @@ -1005,13 +1012,16 @@ class HearingAidImpl : public HearingAid { } } - void OnAudioSuspend() { + void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) { + CHECK(stop_audio_ticks) << "stop_audio_ticks is empty"; + if (!audio_running) { LOG(WARNING) << __func__ << ": Unexpected audio suspend"; } else { LOG(INFO) << __func__ << ": audio_running=" << audio_running; } audio_running = false; + stop_audio_ticks(); std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP}); for (auto& device : hearingDevices.devices) { @@ -1032,23 +1042,33 @@ class HearingAidImpl : public HearingAid { } } - void OnAudioResume() { + void OnAudioResume(const std::function<void()>& start_audio_ticks) { + CHECK(start_audio_ticks) << "start_audio_ticks is empty"; + if (audio_running) { LOG(ERROR) << __func__ << ": Unexpected Audio Resume"; } else { LOG(INFO) << __func__ << ": audio_running=" << audio_running; } - audio_running = true; + + for (auto& device : hearingDevices.devices) { + if (!device.accepting_audio) continue; + audio_running = true; + SendStart(&device); + } + + if (!audio_running) { + LOG(INFO) << __func__ << ": No device (0/" << GetDeviceCount() + << ") ready to start"; + return; + } // TODO: shall we also reset the encoder ? encoder_state_release(); encoder_state_init(); seq_counter = 0; - for (auto& device : hearingDevices.devices) { - if (!device.accepting_audio) continue; - SendStart(&device); - } + start_audio_ticks(); } uint8_t GetOtherSideStreamStatus(HearingDevice* this_side_device) { @@ -1140,10 +1160,9 @@ class HearingAidImpl : public HearingAid { } if (left == nullptr && right == nullptr) { - HearingAidAudioSource::Stop(); - audio_running = false; - encoder_state_release(); - current_volume = VOLUME_UNKNOWN; + LOG(WARNING) << __func__ << ": No more (0/" << GetDeviceCount() + << ") devices ready"; + DoDisconnectAudioStop(); return; } @@ -1456,8 +1475,17 @@ class HearingAidImpl : public HearingAid { hearingDevices.Remove(address); - if (connected) - callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address); + if (!connected) { + return; + } + + callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address); + for (const auto& device : hearingDevices.devices) { + if (device.accepting_audio) return; + } + LOG(INFO) << __func__ << ": No more (0/" << GetDeviceCount() + << ") devices ready"; + DoDisconnectAudioStop(); } void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id, @@ -1479,7 +1507,16 @@ class HearingAidImpl : public HearingAid { DoDisconnectCleanUp(hearingDevice); + // Keep this hearing aid in the list, and allow to reconnect back. + callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda); + + for (const auto& device : hearingDevices.devices) { + if (device.accepting_audio) return; + } + LOG(INFO) << __func__ << ": No more (0/" << GetDeviceCount() + << ") devices ready"; + DoDisconnectAudioStop(); } void DoDisconnectCleanUp(HearingDevice* hearingDevice) { @@ -1512,6 +1549,13 @@ class HearingAidImpl : public HearingAid { hearingDevice->command_acked = false; } + void DoDisconnectAudioStop() { + HearingAidAudioSource::Stop(); + audio_running = false; + encoder_state_release(); + current_volume = VOLUME_UNKNOWN; + } + void SetVolume(int8_t volume) override { VLOG(2) << __func__ << ": " << +volume; current_volume = volume; @@ -1723,14 +1767,11 @@ class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver { void OnAudioDataReady(const std::vector<uint8_t>& data) override { if (instance) instance->OnAudioDataReady(data); } - void OnAudioSuspend(std::promise<void> do_suspend_promise) override { - if (instance) instance->OnAudioSuspend(); - do_suspend_promise.set_value(); + void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) override { + if (instance) instance->OnAudioSuspend(stop_audio_ticks); } - - void OnAudioResume(std::promise<void> do_resume_promise) override { - if (instance) instance->OnAudioResume(); - do_resume_promise.set_value(); + void OnAudioResume(const std::function<void()>& start_audio_ticks) override { + if (instance) instance->OnAudioResume(start_audio_ticks); } }; diff --git a/bta/hearing_aid/hearing_aid_audio_source.cc b/bta/hearing_aid/hearing_aid_audio_source.cc index 3b92d41a8..0896e2bb3 100644 --- a/bta/hearing_aid/hearing_aid_audio_source.cc +++ b/bta/hearing_aid/hearing_aid_audio_source.cc @@ -97,12 +97,20 @@ void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) { } void start_audio_ticks() { + if (data_interval_ms != HA_INTERVAL_10_MS && + data_interval_ms != HA_INTERVAL_20_MS) { + LOG(FATAL) << " Unsupported data interval: " << data_interval_ms; + } + wakelock_acquire(); - audio_timer.SchedulePeriodic(get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data), - base::TimeDelta::FromMilliseconds(data_interval_ms)); + audio_timer.SchedulePeriodic( + get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data), + base::TimeDelta::FromMilliseconds(data_interval_ms)); + LOG(INFO) << __func__ << ": running with data interval: " << data_interval_ms; } void stop_audio_ticks() { + LOG(INFO) << __func__ << ": stopped"; audio_timer.CancelAndWait(); wakelock_release(); } @@ -121,17 +129,12 @@ void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) { UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO, reinterpret_cast<void*>(0)); - if (data_interval_ms != HA_INTERVAL_10_MS && - data_interval_ms != HA_INTERVAL_20_MS) { - LOG(FATAL) << " Unsupported data interval: " << data_interval_ms; - } - - start_audio_ticks(); + do_in_main_thread(FROM_HERE, base::BindOnce(start_audio_ticks)); break; case UIPC_CLOSE_EVT: LOG(INFO) << __func__ << ": UIPC_CLOSE_EVT"; hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); - stop_audio_ticks(); + do_in_main_thread(FROM_HERE, base::BindOnce(stop_audio_ticks)); break; default: LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event; @@ -306,65 +309,52 @@ void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) { } bool hearing_aid_on_resume_req(bool start_media_task) { - // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_START) - if (localAudioReceiver != nullptr) { - // Call OnAudioResume and block till it returns. - std::promise<void> do_resume_promise; - std::future<void> do_resume_future = do_resume_promise.get_future(); - bt_status_t status = do_in_main_thread( - FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume, - base::Unretained(localAudioReceiver), - std::move(do_resume_promise))); - if (status == BT_STATUS_SUCCESS) { - do_resume_future.wait(); - } else { - LOG(ERROR) << __func__ - << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err=" - << status; - return false; - } - } else { + if (localAudioReceiver == nullptr) { LOG(ERROR) << __func__ << ": HEARING_AID_CTRL_CMD_START: audio receiver not started"; return false; } - - // hearing_aid_data_cb(UIPC_OPEN_EVT): start_media_task + bt_status_t status; if (start_media_task) { - if (data_interval_ms != HA_INTERVAL_10_MS && - data_interval_ms != HA_INTERVAL_20_MS) { - LOG(FATAL) << " Unsupported data interval: " << data_interval_ms; - data_interval_ms = HA_INTERVAL_10_MS; - } - start_audio_ticks(); + status = do_in_main_thread( + FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume, + base::Unretained(localAudioReceiver), + start_audio_ticks)); + } else { + auto start_dummy_ticks = []() { + LOG(INFO) << "start_audio_ticks: waiting for data path opened"; + }; + status = do_in_main_thread( + FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume, + base::Unretained(localAudioReceiver), + start_dummy_ticks)); + } + if (status != BT_STATUS_SUCCESS) { + LOG(ERROR) << __func__ + << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err=" + << status; + return false; } return true; } bool hearing_aid_on_suspend_req() { - // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_SUSPEND): stop_media_task - stop_audio_ticks(); - if (localAudioReceiver != nullptr) { - // Call OnAudioSuspend and block till it returns. - std::promise<void> do_suspend_promise; - std::future<void> do_suspend_future = do_suspend_promise.get_future(); - bt_status_t status = do_in_main_thread( - FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend, - base::Unretained(localAudioReceiver), - std::move(do_suspend_promise))); - if (status == BT_STATUS_SUCCESS) { - do_suspend_future.wait(); - return true; - } else { - LOG(ERROR) << __func__ - << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err=" - << status; - } - } else { + if (localAudioReceiver == nullptr) { LOG(ERROR) << __func__ << ": HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started"; + return false; } - return false; + bt_status_t status = do_in_main_thread( + FROM_HERE, + base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend, + base::Unretained(localAudioReceiver), stop_audio_ticks)); + if (status != BT_STATUS_SUCCESS) { + LOG(ERROR) << __func__ + << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err=" + << status; + return false; + } + return true; } } // namespace diff --git a/bta/hf_client/bta_hf_client_rfc.cc b/bta/hf_client/bta_hf_client_rfc.cc index f3e0947eb..535371f6b 100644 --- a/bta/hf_client/bta_hf_client_rfc.cc +++ b/bta/hf_client/bta_hf_client_rfc.cc @@ -127,6 +127,7 @@ static void bta_hf_client_mgmt_cback(uint32_t code, uint16_t port_handle) { } else { APPL_TRACE_ERROR("%s: PORT_SUCCESS, ignoring handle = %d", __func__, port_handle); + osi_free(p_buf); return; } } else if (client_cb != NULL && @@ -136,6 +137,10 @@ static void bta_hf_client_mgmt_cback(uint32_t code, uint16_t port_handle) { RFCOMM_RemoveServer(port_handle); p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT; + } else if (client_cb == NULL) { + // client_cb is already cleaned due to hfp client disabled. + // Assigned a valid event value to header and send this message anyway. + p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT; } p_buf->hdr.layer_specific = client_cb != NULL ? client_cb->handle : 0; diff --git a/bta/include/bta_hearing_aid_api.h b/bta/include/bta_hearing_aid_api.h index 902626221..6c4954b09 100644 --- a/bta/include/bta_hearing_aid_api.h +++ b/bta/include/bta_hearing_aid_api.h @@ -21,7 +21,6 @@ #include <base/callback_forward.h> #include <hardware/bt_hearing_aid.h> #include <deque> -#include <future> #include <vector> constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1; @@ -39,8 +38,22 @@ class HearingAidAudioReceiver { public: virtual ~HearingAidAudioReceiver() = default; virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0; - virtual void OnAudioSuspend(std::promise<void> do_suspend_promise) = 0; - virtual void OnAudioResume(std::promise<void> do_resume_promise) = 0; + + // API to stop our feeding timer, and notify hearing aid devices that the + // streaming would stop, too. + // + // @param stop_audio_ticks a callable function calls out to stop the media + // timer for reading data. + virtual void OnAudioSuspend( + const std::function<void()>& stop_audio_ticks) = 0; + + // To notify hearing aid devices to be ready for streaming, and start the + // media timer to feed the audio data. + // + // @param start_audio_ticks a callable function calls out to start a periodic + // timer for feeding data from the audio HAL. + virtual void OnAudioResume( + const std::function<void()>& start_audio_ticks) = 0; }; // Number of rssi reads to attempt when requested diff --git a/bta/jv/bta_jv_act.cc b/bta/jv/bta_jv_act.cc index 462ee9d6b..2ede5c948 100644 --- a/bta/jv/bta_jv_act.cc +++ b/bta/jv/bta_jv_act.cc @@ -362,6 +362,8 @@ tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB* p_cb) { p_cb->cong = false; bta_jv_free_sec_id(&p_cb->sec_id); p_cb->p_cback = NULL; + p_cb->handle = 0; + p_cb->l2cap_socket_id = 0; return status; } @@ -1121,7 +1123,7 @@ void bta_jv_l2cap_start_server(int32_t type, tBTA_SEC sec_mask, /* stops an L2CAP server */ void bta_jv_l2cap_stop_server(uint16_t local_psm, uint32_t l2cap_socket_id) { for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) { - if (bta_jv_cb.l2c_cb[i].psm == local_psm) { + if (bta_jv_cb.l2c_cb[i].l2cap_socket_id == l2cap_socket_id) { tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[i]; tBTA_JV_L2CAP_CBACK* p_cback = p_cb->p_cback; tBTA_JV_L2CAP_CLOSE evt_data; diff --git a/btif/Android.bp b/btif/Android.bp index f33d174cf..0ecf20792 100644 --- a/btif/Android.bp +++ b/btif/Android.bp @@ -208,3 +208,36 @@ cc_test { ], cflags: ["-DBUILDCFG"], } + +// btif rc unit tests for target +// ======================================================== +cc_test { + name: "net_test_btif_rc", + defaults: ["fluoride_defaults"], + test_suites: ["device-tests"], + host_supported: true, + include_dirs: btifCommonIncludes, + srcs: [ + "test/btif_rc_test.cc", + ], + header_libs: ["libbluetooth_headers"], + shared_libs: [ + "libcrypto", + "libcutils", + "liblog", + "libprotobuf-cpp-lite", + ], + static_libs: [ + "libbluetooth-types", + "libbt-common", + "libbt-protos-lite", + "libosi", + "libosi-AllocationTestHarness", + ], + cflags: ["-DBUILDCFG"], + sanitize: { + address: true, + cfi: true, + misc_undefined: ["bounds"], + }, +} diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h index 71acd2836..50d833f30 100644 --- a/btif/include/btif_api.h +++ b/btif/include/btif_api.h @@ -105,7 +105,7 @@ bool is_restricted_mode(void); /******************************************************************************* * - * Function is_single_user_mode_ + * Function is_niap_mode * * Description Checks if BT was enabled in single user mode. In this * mode, use of keystore for key attestation of LTK is limitee @@ -114,7 +114,7 @@ bool is_restricted_mode(void); * Returns bool * ******************************************************************************/ -bool is_single_user_mode(void); +bool is_niap_mode(void); /******************************************************************************* * diff --git a/btif/include/btif_bqr.h b/btif/include/btif_bqr.h index 4407b0d03..ecf69f187 100644 --- a/btif/include/btif_bqr.h +++ b/btif/include/btif_bqr.h @@ -67,6 +67,11 @@ static constexpr int8_t kCriWarnRssi = -80; static constexpr uint8_t kCriWarnUnusedCh = 55; // The queue size of recording the BQR events. static constexpr uint8_t kBqrEventQueueSize = 25; +// The minimum size of the ROOT_INFLAMMATION event +// HCI_VENDOR_SPECIFIC_EVT(1) + BQR sub event(1) + BQR report ID(1) + +// error code(1) + vendor error code(1) = 5 +static constexpr uint8_t kRootInflammationPacketMinSize = 5; + // The Property of BQR event mask configuration. static constexpr const char* kpPropertyEventMask = "persist.bluetooth.bqr.event_mask"; @@ -90,7 +95,8 @@ enum BqrQualityReportId : uint8_t { QUALITY_REPORT_ID_MONITOR_MODE = 0x01, QUALITY_REPORT_ID_APPROACH_LSTO = 0x02, QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY = 0x03, - QUALITY_REPORT_ID_SCO_VOICE_CHOPPY = 0x04 + QUALITY_REPORT_ID_SCO_VOICE_CHOPPY = 0x04, + QUALITY_REPORT_ID_ROOT_INFLAMMATION = 0x05 }; // Packet Type definition diff --git a/btif/include/btif_keystore.h b/btif/include/btif_keystore.h index cc06a9826..1b3663d03 100644 --- a/btif/include/btif_keystore.h +++ b/btif/include/btif_keystore.h @@ -70,9 +70,7 @@ class BtifKeystore { private: std::unique_ptr<keystore::KeystoreClient> keystore_client_; std::mutex api_mutex_; - keystore::KeyStoreNativeReturnCode GenerateKey(const std::string& name, - int32_t flags, - bool auth_bound); + bool GenerateKey(const std::string& name, int32_t flags); }; } // namespace bluetooth diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc index f55bcf9ba..158a739ca 100644 --- a/btif/src/bluetooth.cc +++ b/btif/src/bluetooth.cc @@ -81,7 +81,7 @@ using bluetooth::hearing_aid::HearingAidInterface; bt_callbacks_t* bt_hal_cbacks = NULL; bool restricted_mode = false; -bool single_user_mode = false; +bool niap_mode = false; bool is_local_device_atv = false; /******************************************************************************* @@ -135,9 +135,9 @@ static bool is_profile(const char* p1, const char* p2) { ****************************************************************************/ static int init(bt_callbacks_t* callbacks, bool start_restricted, - bool is_single_user_mode, bool is_atv) { - LOG_INFO(LOG_TAG, "%s: start restricted = %d ; single user = %d", __func__, - start_restricted, is_single_user_mode); + bool is_niap_mode, bool is_atv) { + LOG_INFO(LOG_TAG, "%s: start restricted = %d ; niap = %d", __func__, + start_restricted, is_niap_mode); if (interface_ready()) return BT_STATUS_DONE; @@ -147,7 +147,7 @@ static int init(bt_callbacks_t* callbacks, bool start_restricted, bt_hal_cbacks = callbacks; restricted_mode = start_restricted; - single_user_mode = is_single_user_mode; + niap_mode = is_niap_mode; is_local_device_atv = is_atv; stack_manager_get_interface()->init_stack(); btif_debug_init(); @@ -171,7 +171,7 @@ static int disable(void) { static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); } bool is_restricted_mode() { return restricted_mode; } -bool is_single_user_mode() { return single_user_mode; } +bool is_niap_mode() { return niap_mode; } bool is_atv_device() { return is_local_device_atv; } diff --git a/btif/src/btif_a2dp_sink.cc b/btif/src/btif_a2dp_sink.cc index bb1bc49c0..aa75d21d4 100644 --- a/btif/src/btif_a2dp_sink.cc +++ b/btif/src/btif_a2dp_sink.cc @@ -667,7 +667,6 @@ static void btif_a2dp_sink_set_focus_state_event( LOG_INFO(LOG_TAG, "%s: state=%d", __func__, state); LockGuard lock(g_mutex); - if (!btif_av_is_connected()) return; APPL_TRACE_DEBUG("%s: setting focus state to %d", __func__, state); btif_a2dp_sink_cb.rx_focus_state = state; if (btif_a2dp_sink_cb.rx_focus_state == BTIF_A2DP_SINK_FOCUS_NOT_GRANTED) { diff --git a/btif/src/btif_config.cc b/btif/src/btif_config.cc index ed24d7dde..277671ca0 100644 --- a/btif/src/btif_config.cc +++ b/btif/src/btif_config.cc @@ -20,6 +20,7 @@ #include "btif_config.h" +#include <base/base64.h> #include <base/logging.h> #include <ctype.h> #include <openssl/rand.h> @@ -60,8 +61,8 @@ static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S"; constexpr int kBufferSize = 400 * 10; // initial file is ~400B -static bool use_key_attestation() { - return getuid() == AID_BLUETOOTH && is_single_user_mode(); +static bool btif_is_niap_mode() { + return getuid() == AID_BLUETOOTH && is_niap_mode(); } #define BT_CONFIG_METRICS_SECTION "Metrics" @@ -93,10 +94,22 @@ static void btif_config_remove_restricted(config_t* config); static std::unique_ptr<config_t> btif_config_open(const char* filename, const char* checksum_filename); // Key attestation +static std::string btif_convert_to_encrypt_key( + const std::string& unencrypt_str); +static std::string btif_convert_to_unencrypt_key( + const std::string& encrypt_str); +static bool btif_in_encrypt_key_name_list(std::string key); +static bool btif_is_key_encrypted(int key_from_config_size, + std::string key_type_string); static std::string hash_file(const char* filename); static std::string read_checksum_file(const char* filename); static void write_checksum_file(const char* filename, const std::string& hash); +static const int ENCRYPT_KEY_NAME_LIST_SIZE = 7; +static const std::string encrypt_key_name_list[] = { + "LinkKey", "LE_KEY_PENC", "LE_KEY_PID", "LE_KEY_LID", + "LE_KEY_PCSRK", "LE_KEY_LENC", "LE_KEY_LCSRK"}; + static enum ConfigSource { NOT_LOADED, ORIGINAL, @@ -183,9 +196,7 @@ static BtifKeystore btif_keystore(new keystore::KeystoreClientImpl); static future_t* init(void) { std::unique_lock<std::recursive_mutex> lock(config_lock); - if (is_factory_reset() || - (use_key_attestation() && !btif_keystore.DoesKeyExist())) - delete_config_files(); + if (is_factory_reset()) delete_config_files(); std::string file_source; @@ -271,7 +282,8 @@ static std::unique_ptr<config_t> btif_config_open(const char* filename, const ch std::string stored_hash = read_checksum_file(checksum_filename); if (stored_hash.empty()) { LOG(ERROR) << __func__ << ": stored_hash=<empty>"; - if (!current_hash.empty()) { + // Will encrypt once since the bt_config never encrypt. + if (!btif_keystore.DoesKeyExist() && !current_hash.empty()) { write_checksum_file(checksum_filename, current_hash); stored_hash = read_checksum_file(checksum_filename); } @@ -408,14 +420,29 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, CHECK(length != NULL); std::unique_lock<std::recursive_mutex> lock(config_lock); - const std::string* value_str = config_get_string(*config, section, key, NULL); + const std::string* value_str; + const std::string* value_str_from_config = + config_get_string(*config, section, key, NULL); - if (!value_str) { + if (!value_str_from_config) { VLOG(1) << __func__ << ": cannot find string for section " << section << ", key " << key; return false; } + bool in_encrypt_key_name_list = btif_in_encrypt_key_name_list(key); + bool is_key_encrypted = + btif_is_key_encrypted(value_str_from_config->size(), key); + + if (in_encrypt_key_name_list && is_key_encrypted) { + VLOG(2) << __func__ << " decrypt section: " << section << " key:" << key; + std::string tmp_value_str = + btif_convert_to_unencrypt_key(*value_str_from_config); + value_str = &tmp_value_str; + } else { + value_str = value_str_from_config; + } + size_t value_len = value_str->length(); if ((value_len % 2) != 0 || *length < (value_len / 2)) { LOG(WARNING) << ": value size not divisible by 2, size is " << value_len; @@ -429,12 +456,72 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, } const char* ptr = value_str->c_str(); - for (*length = 0; *ptr; ptr += 2, *length += 1) + for (*length = 0; *ptr; ptr += 2, *length += 1) { sscanf(ptr, "%02hhx", &value[*length]); + } + + if (btif_is_niap_mode()) { + if (in_encrypt_key_name_list && !is_key_encrypted) { + VLOG(2) << __func__ << " encrypt section: " << section << " key:" << key; + std::string encrypt_str = + btif_convert_to_encrypt_key(*value_str_from_config); + config_set_string(config.get(), section, key, encrypt_str); + } + } else { + if (in_encrypt_key_name_list && is_key_encrypted) { + config_set_string(config.get(), section, key, value_str->c_str()); + } + } return true; } +static bool btif_in_encrypt_key_name_list(std::string key) { + return std::find(encrypt_key_name_list, + encrypt_key_name_list + ENCRYPT_KEY_NAME_LIST_SIZE, + key) != (encrypt_key_name_list + ENCRYPT_KEY_NAME_LIST_SIZE); +} + +static bool btif_is_key_encrypted(int key_from_config_size, + std::string key_type_string) { + if (key_type_string.compare("LinkKey") == 0) { + return sizeof(LinkKey) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_PENC") == 0) { + return sizeof(tBTM_LE_PENC_KEYS) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_PID") == 0) { + return sizeof(tBTM_LE_PID_KEYS) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_LID") == 0) { + return sizeof(tBTM_LE_PID_KEYS) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_PCSRK") == 0) { + return sizeof(tBTM_LE_PCSRK_KEYS) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_LENC") == 0) { + return sizeof(tBTM_LE_LENC_KEYS) * 2 != key_from_config_size; + } else if (key_type_string.compare("LE_KEY_LCSRK") == 0) { + return sizeof(tBTM_LE_LCSRK_KEYS) * 2 != key_from_config_size; + } else { + VLOG(2) << __func__ << ": " << key_type_string + << " Key type is unknown, return false first"; + return false; + } +} + +static std::string btif_convert_to_unencrypt_key( + const std::string& encrypt_str) { + if (!encrypt_str.empty()) { + std::string tmp_encrypt_str(""); + if (base::Base64Decode(encrypt_str, &tmp_encrypt_str)) { + std::string unencrypt_str = btif_keystore.Decrypt(tmp_encrypt_str); + if (!unencrypt_str.empty()) { + return unencrypt_str; + } + } else { + LOG(WARNING) << __func__ + << ": base64string decode fail, will return empty string"; + } + } + return ""; +} + size_t btif_config_get_bin_length(const std::string& section, const std::string& key) { CHECK(config != NULL); @@ -468,15 +555,37 @@ bool btif_config_set_bin(const std::string& section, const std::string& key, str[(i * 2) + 1] = lookup[value[i] & 0x0F]; } + std::string value_str; + if (btif_is_niap_mode() && btif_in_encrypt_key_name_list(key)) { + VLOG(2) << __func__ << " encrypt section: " << section << " key:" << key; + value_str = btif_convert_to_encrypt_key(str); + } else { + value_str = str; + } + { std::unique_lock<std::recursive_mutex> lock(config_lock); - config_set_string(config.get(), section, key, str); + config_set_string(config.get(), section, key, value_str); } osi_free(str); return true; } +static std::string btif_convert_to_encrypt_key( + const std::string& unencrypt_str) { + if (!unencrypt_str.empty()) { + std::string encrypt_str = btif_keystore.Encrypt(unencrypt_str, 0); + if (!encrypt_str.empty()) { + base::Base64Encode(encrypt_str, &encrypt_str); + return encrypt_str; + } else { + LOG(ERROR) << __func__ << ": Encrypt fail, will return empty str."; + } + } + return ""; +} + std::list<section_t>& btif_config_sections() { return config->sections; } bool btif_config_remove(const std::string& section, const std::string& key) { @@ -643,7 +752,7 @@ static void delete_config_files(void) { } static std::string hash_file(const char* filename) { - if (!use_key_attestation()) { + if (!btif_is_niap_mode()) { LOG(INFO) << __func__ << ": Disabled for multi-user"; return DISABLED; } @@ -671,7 +780,7 @@ static std::string hash_file(const char* filename) { } static std::string read_checksum_file(const char* checksum_filename) { - if (!use_key_attestation()) { + if (!btif_is_niap_mode()) { LOG(INFO) << __func__ << ": Disabled for multi-user"; return DISABLED; } @@ -685,7 +794,7 @@ static std::string read_checksum_file(const char* checksum_filename) { static void write_checksum_file(const char* checksum_filename, const std::string& hash) { - if (!use_key_attestation()) { + if (!btif_is_niap_mode()) { LOG(INFO) << __func__ << ": Disabled for multi-user, since config changed removing " "checksums."; diff --git a/btif/src/btif_keystore.cc b/btif/src/btif_keystore.cc index 0af03e11b..1bf2c0ff1 100644 --- a/btif/src/btif_keystore.cc +++ b/btif/src/btif_keystore.cc @@ -17,6 +17,8 @@ ******************************************************************************/ #include "btif_keystore.h" +#include "keystore_client.pb.h" +#include "string.h" #include <base/files/file_util.h> #include <base/logging.h> @@ -29,7 +31,9 @@ using namespace keystore; using namespace bluetooth; -constexpr char kKeyStore[] = "AndroidKeystore"; +const std::string kKeyStore = "bluetooth-key-encrypted"; +constexpr uint32_t kAESKeySize = 256; // bits +constexpr uint32_t kMACOutputSize = 128; // bits namespace bluetooth { @@ -43,19 +47,45 @@ std::string BtifKeystore::Encrypt(const std::string& data, int32_t flags) { LOG(ERROR) << __func__ << ": empty data"; return output; } - if (!keystore_client_->doesKeyExist(kKeyStore)) { - auto gen_result = GenerateKey(kKeyStore, 0, false); - if (!gen_result.isOk()) { - LOG(FATAL) << "EncryptWithAuthentication Failed: generateKey response=" - << gen_result; - return output; - } + if (!GenerateKey(kKeyStore, flags)) { + return output; } - if (!keystore_client_->encryptWithAuthentication(kKeyStore, data, flags, - &output)) { - LOG(FATAL) << "EncryptWithAuthentication failed."; + + AuthorizationSetBuilder encrypt_params; + encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Authorization(TAG_MAC_LENGTH, kMACOutputSize) + .Padding(PaddingMode::NONE); + AuthorizationSet output_params; + std::string raw_encrypted_data; + if (!keystore_client_->oneShotOperation( + KeyPurpose::ENCRYPT, kKeyStore, encrypt_params, data, + std::string() /* signature_to_verify */, &output_params, + &raw_encrypted_data)) { + LOG(ERROR) << __func__ << ": AES operation failed."; return output; } + auto init_vector_blob = output_params.GetTagValue(TAG_NONCE); + if (!init_vector_blob.isOk()) { + LOG(ERROR) << __func__ << ": Missing initialization vector."; + return output; + } + + const hidl_vec<uint8_t>& value = init_vector_blob.value(); + std::string init_vector = + std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), + value.size()); + + if (memcmp(&init_vector_blob, &init_vector, init_vector.length()) == 0) { + LOG(ERROR) << __func__ + << ": Protobuf nonce data doesn't match the actual nonce."; + } + + EncryptedData protobuf; + protobuf.set_init_vector(init_vector); + protobuf.set_encrypted_data(raw_encrypted_data); + if (!protobuf.SerializeToString(&output)) { + LOG(ERROR) << __func__ << ": Failed to serialize EncryptedData protobuf."; + } return output; } @@ -66,36 +96,49 @@ std::string BtifKeystore::Decrypt(const std::string& input) { return ""; } std::string output; - if (!keystore_client_->decryptWithAuthentication(kKeyStore, input, &output)) { - LOG(FATAL) << "DecryptWithAuthentication failed.\n"; + EncryptedData protobuf; + if (!protobuf.ParseFromString(input)) { + LOG(ERROR) << __func__ << ": Failed to parse EncryptedData protobuf."; + return output; + } + AuthorizationSetBuilder encrypt_params; + encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Authorization(TAG_MAC_LENGTH, kMACOutputSize) + .Authorization(TAG_NONCE, protobuf.init_vector().data(), + protobuf.init_vector().size()) + .Padding(PaddingMode::NONE); + AuthorizationSet output_params; + if (!keystore_client_->oneShotOperation( + KeyPurpose::DECRYPT, kKeyStore, encrypt_params, + protobuf.encrypted_data(), std::string() /* signature_to_verify */, + &output_params, &output)) { + LOG(ERROR) << __func__ << ": AES operation failed."; } return output; } -// Note: auth_bound keys created with this tool will not be usable. -KeyStoreNativeReturnCode BtifKeystore::GenerateKey(const std::string& name, - int32_t flags, - bool auth_bound) { - AuthorizationSetBuilder params; - params.RsaSigningKey(2048, 65537) - .Digest(Digest::SHA_2_224) - .Digest(Digest::SHA_2_256) - .Digest(Digest::SHA_2_384) - .Digest(Digest::SHA_2_512) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN) - .Padding(PaddingMode::RSA_PSS); - if (auth_bound) { - // Gatekeeper normally generates the secure user id. - // Using zero allows the key to be created, but it will not be usuable. - params.Authorization(TAG_USER_SECURE_ID, 0); - } else { - params.Authorization(TAG_NO_AUTH_REQUIRED); +bool BtifKeystore::GenerateKey(const std::string& name, int32_t flags) { + if (!DoesKeyExist()) { + AuthorizationSetBuilder params; + params.AesEncryptionKey(kAESKeySize) + .Authorization(TAG_NO_AUTH_REQUIRED) + .Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT) + .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT) + .Padding(PaddingMode::NONE) + .Authorization(TAG_MIN_MAC_LENGTH, kMACOutputSize); + AuthorizationSet hardware_enforced_characteristics; + AuthorizationSet software_enforced_characteristics; + auto result = keystore_client_->generateKey( + name, params, flags, &hardware_enforced_characteristics, + &software_enforced_characteristics); + if (!result.isOk()) { + LOG(FATAL) << __func__ << "Failed to generate key: name: " << name + << ", error code: " << result.getErrorCode(); + return false; + } } - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - return keystore_client_->generateKey(name, params, flags, - &hardware_enforced_characteristics, - &software_enforced_characteristics); + return true; } bool BtifKeystore::DoesKeyExist() { diff --git a/btif/src/btif_profile_queue.cc b/btif/src/btif_profile_queue.cc index 41275f127..900a6af52 100644 --- a/btif/src/btif_profile_queue.cc +++ b/btif/src/btif_profile_queue.cc @@ -195,7 +195,14 @@ bt_status_t btif_queue_connect_next(void) { LOG_INFO(LOG_TAG, "%s: executing connection request: %s", __func__, head.ToString().c_str()); - return head.connect(); + bt_status_t b_status = head.connect(); + if (b_status != BT_STATUS_SUCCESS) { + LOG_INFO(LOG_TAG, + "%s: connect %s failed, advance to next scheduled connection.", + __func__, head.ToString().c_str()); + btif_queue_advance(); + } + return b_status; } /******************************************************************************* diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc index 9919a7b42..575d83e37 100644 --- a/btif/src/btif_rc.cc +++ b/btif/src/btif_rc.cc @@ -1836,6 +1836,12 @@ static bt_status_t get_element_attr_rsp(const RawAddress& bd_addr, BTIF_TRACE_DEBUG("%s", __func__); CHECK_RC_CONNECTED(p_dev); + if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) { + LOG(WARNING) << __func__ + << " Exceeded number attributes:" << static_cast<int>(num_attr) + << " max:" << BTRC_MAX_ELEM_ATTR_SIZE; + num_attr = BTRC_MAX_ELEM_ATTR_SIZE; + } memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr); if (num_attr == 0) { @@ -1844,7 +1850,8 @@ static bt_status_t get_element_attr_rsp(const RawAddress& bd_addr, for (i = 0; i < num_attr; i++) { element_attrs[i].attr_id = p_attrs[i].attr_id; element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8; - element_attrs[i].name.str_len = (uint16_t)strlen((char*)p_attrs[i].text); + element_attrs[i].name.str_len = + (uint16_t)strnlen((char*)p_attrs[i].text, BTRC_MAX_ATTR_STR_LEN); element_attrs[i].name.p_str = p_attrs[i].text; BTIF_TRACE_DEBUG( "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__, @@ -2939,11 +2946,12 @@ static void register_for_event_notification(btif_rc_supported_event_t* p_event, return; } // interval is only valid for AVRC_EVT_PLAY_POS_CHANGED - uint32_t interval = 0; + uint32_t interval_in_seconds = 0; if (p_event->event_id == AVRC_EVT_PLAY_POS_CHANGED) { - interval = 2000; + interval_in_seconds = 2; } - status = register_notification_cmd(p_transaction->lbl, p_event->event_id, interval, p_dev); + status = register_notification_cmd(p_transaction->lbl, p_event->event_id, + interval_in_seconds, p_dev); if (status != BT_STATUS_SUCCESS) { BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__, status); @@ -3152,11 +3160,10 @@ static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg, break; } else { uint8_t* p_data = p_rsp->param.track; - /* Update the UID for current track - * Attributes will be fetched after the AVRCP procedure - */ BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data); get_play_status_cmd(p_dev); + get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, + p_dev); } break; @@ -3336,6 +3343,8 @@ static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg, rc_ctrl_procedure_complete(p_dev); return; } + p_dev->rc_app_settings.num_attrs = 0; + p_dev->rc_app_settings.num_ext_attrs = 0; for (xx = 0; xx < p_rsp->num_attr; xx++) { uint8_t st_index; @@ -3809,6 +3818,10 @@ static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg, if (p_rsp->status == AVRC_STS_NO_ERROR) { do_in_jni_thread( FROM_HERE, + base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb, p_dev->rc_addr, + (btrc_play_status_t)p_rsp->play_status)); + do_in_jni_thread( + FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb, p_dev->rc_addr, p_rsp->song_len, p_rsp->song_pos)); } else { @@ -3907,6 +3920,12 @@ static void handle_get_folder_items_response(tBTA_AV_META_MSG* pmeta_msg, /* We want to make the ownership explicit in native */ btrc_items, item_count)); + if (item_count > 0) { + if (btrc_items[0].item_type == AVRC_ITEM_PLAYER && + (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING)) { + list_player_app_setting_attrib_cmd(p_dev); + } + } /* Release the memory block for items and attributes allocated here. * Since the executor for do_in_jni_thread is a Single Thread Task Runner it * is okay to queue up the cleanup of btrc_items */ diff --git a/btif/src/btif_sock_l2cap.cc b/btif/src/btif_sock_l2cap.cc index 1f85c732b..105d5a1cc 100644 --- a/btif/src/btif_sock_l2cap.cc +++ b/btif/src/btif_sock_l2cap.cc @@ -97,6 +97,7 @@ static void btsock_l2cap_server_listen(l2cap_socket* sock); static std::mutex state_lock; l2cap_socket* socks = NULL; +static uint32_t last_sock_id = 0; static uid_set_t* uid_set = NULL; static int pth = -1; @@ -254,6 +255,11 @@ static void btsock_l2cap_free_l(l2cap_socket* sock) { } if ((sock->channel >= 0) && (sock->server)) { BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE); + if (!sock->fixed_chan) { + VLOG(2) << __func__ << ": stopping L2CAP LE COC server channel " + << sock->channel; + BTA_JvL2capStopServer(sock->channel, sock->id); + } } } else { // Only call if we are non server connections @@ -322,7 +328,7 @@ static l2cap_socket* btsock_l2cap_alloc_l(const char* name, sock->next = socks; sock->prev = NULL; if (socks) socks->prev = sock; - sock->id = (socks ? socks->id : 0) + 1; + sock->id = last_sock_id + 1; sock->tx_bytes = 0; sock->rx_bytes = 0; socks = sock; @@ -340,6 +346,7 @@ static l2cap_socket* btsock_l2cap_alloc_l(const char* name, if (!++sock->id) /* no zero IDs allowed */ sock->id++; } + last_sock_id = sock->id; DVLOG(2) << __func__ << " SOCK_LIST: alloc id:" << sock->id; return sock; diff --git a/btif/test/btif_profile_queue_test.cc b/btif/test/btif_profile_queue_test.cc index 486959b56..af0255b19 100644 --- a/btif/test/btif_profile_queue_test.cc +++ b/btif/test/btif_profile_queue_test.cc @@ -97,6 +97,49 @@ TEST_F(BtifProfileQueueTest, test_connect) { EXPECT_EQ(sResult, UUID1_ADDR1); } +static bt_status_t test_connect_cb_fail(RawAddress* bda, uint16_t uuid) { + sResult = UNKNOWN; + if (*bda == BtifProfileQueueTest::kTestAddr1) { + if (uuid == BtifProfileQueueTest::kTestUuid1) { + sResult = UUID1_ADDR1; + } else if (uuid == BtifProfileQueueTest::kTestUuid2) { + sResult = UUID2_ADDR1; + } + } else if (*bda == BtifProfileQueueTest::kTestAddr2) { + if (uuid == BtifProfileQueueTest::kTestUuid1) { + sResult = UUID1_ADDR2; + } else if (uuid == BtifProfileQueueTest::kTestUuid2) { + sResult = UUID2_ADDR2; + } + } + return BT_STATUS_BUSY; +} + +TEST_F(BtifProfileQueueTest, test_connect_fail_still_can_advance_the_queue) { + sResult = NOT_SET; + // First connect-message for UUID1-ADDR1 is executed, but does not be removed + // from connect-queue yet. + btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb); + EXPECT_EQ(sResult, UUID1_ADDR1); + sResult = NOT_SET; + // Second connect-message for UUID2-ADDR1 be pushed into connect-queue, but is + // not executed + btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb_fail); + EXPECT_EQ(sResult, NOT_SET); + // Third connect-message for UUID1-ADDR2 be pushed into connect-queue, but is + // not executed + btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb_fail); + EXPECT_EQ(sResult, NOT_SET); + // Fourth connect-message for UUID2-ADDR2 be pushed into connect-queue, but is + // not executed + btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb_fail); + EXPECT_EQ(sResult, NOT_SET); + // removed First connect-message from connect-queue, check it can advance to + // subsequent connect-message. + btif_queue_advance(); + EXPECT_EQ(sResult, UUID2_ADDR2); +} + TEST_F(BtifProfileQueueTest, test_connect_same_uuid_do_not_repeat) { sResult = NOT_SET; btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb); diff --git a/btif/test/btif_rc_test.cc b/btif/test/btif_rc_test.cc new file mode 100644 index 000000000..6271881c9 --- /dev/null +++ b/btif/test/btif_rc_test.cc @@ -0,0 +1,131 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <base/logging.h> +#include <gtest/gtest.h> +#include <stdio.h> +#include <cstdint> + +#include "bta/include/bta_av_api.h" +#include "btif/include/btif_common.h" +#include "device/include/interop.h" +#include "include/hardware/bt_rc.h" +#include "osi/test/AllocationTestHarness.h" +#include "stack/include/btm_api_types.h" +#include "types/raw_address.h" +#undef LOG_TAG +#include "btif/src/btif_rc.cc" + +extern void allocation_tracker_uninit(void); + +namespace { +int AVRC_BldResponse_ = 0; +} // namespace + +uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING; +uint8_t btif_trace_level = BT_TRACE_LEVEL_WARNING; + +tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) { return 0; } +tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp, + BT_HDR** pp_pkt) { + AVRC_BldResponse_++; + return 0; +} +tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) { + return 0; +} +tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result, + uint8_t* p_buf, uint16_t* buf_len) { + return 0; +} +tAVRC_STS AVRC_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result, + uint8_t* p_buf, uint16_t buf_len) { + return 0; +} +tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result, + UNUSED_ATTR uint8_t* p_buf, + UNUSED_ATTR uint16_t buf_len) { + return 0; +} +void BTA_AvCloseRc(uint8_t rc_handle) {} +void BTA_AvMetaCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CMD cmd_code, + BT_HDR* p_pkt) {} +void BTA_AvMetaRsp(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE rsp_code, + BT_HDR* p_pkt) {} +void BTA_AvRemoteCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_RC rc_id, + tBTA_AV_STATE key_state) {} +void BTA_AvRemoteVendorUniqueCmd(uint8_t rc_handle, uint8_t label, + tBTA_AV_STATE key_state, uint8_t* p_msg, + uint8_t buf_len) {} +void BTA_AvVendorCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE cmd_code, + uint8_t* p_data, uint16_t len) {} +void BTA_AvVendorRsp(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE rsp_code, + uint8_t* p_data, uint16_t len, uint32_t company_id) {} +void btif_av_clear_remote_suspend_flag(void) {} +bool btif_av_is_connected(void) { return false; } +bool btif_av_is_sink_enabled(void) { return false; } +RawAddress btif_av_sink_active_peer(void) { return RawAddress(); } +RawAddress btif_av_source_active_peer(void) { return RawAddress(); } +bool btif_av_stream_started_ready(void) { return false; } +bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event, + char* p_params, int param_len, + tBTIF_COPY_CBACK* p_copy_cback) { + return BT_STATUS_SUCCESS; +} +const char* dump_rc_event(uint8_t event) { return nullptr; } +const char* dump_rc_notification_event_id(uint8_t event_id) { return nullptr; } +const char* dump_rc_pdu(uint8_t pdu) { return nullptr; } +bt_status_t do_in_jni_thread(const base::Location& from_here, + base::OnceClosure task) { + return BT_STATUS_SUCCESS; +} +base::MessageLoop* get_main_message_loop() { return nullptr; } +bool interop_match_addr(const interop_feature_t feature, + const RawAddress* addr) { + return false; +} +void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {} + +/** + * Test class to test selected functionality in hci/src/hci_layer.cc + */ +class BtifRcTest : public AllocationTestHarness { + protected: + void SetUp() override { + AllocationTestHarness::SetUp(); + // Disable our allocation tracker to allow ASAN full range + allocation_tracker_uninit(); + } + + void TearDown() override { AllocationTestHarness::TearDown(); } +}; + +TEST_F(BtifRcTest, get_element_attr_rsp) { + RawAddress bd_addr; + + btif_rc_cb.rc_multi_cb[0].rc_addr = bd_addr; + btif_rc_cb.rc_multi_cb[0].rc_connected = true; + btif_rc_cb.rc_multi_cb[0] + .rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP] + .is_rsp_pending = true; + btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED; + + btrc_element_attr_val_t p_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; + uint8_t num_attr = BTRC_MAX_ELEM_ATTR_SIZE + 1; + + CHECK(get_element_attr_rsp(bd_addr, num_attr, p_attrs) == BT_STATUS_SUCCESS); + CHECK(AVRC_BldResponse_ == 1); +} diff --git a/hci/Android.bp b/hci/Android.bp index 635d939e3..57021770c 100644 --- a/hci/Android.bp +++ b/hci/Android.bp @@ -36,6 +36,7 @@ cc_library_static { "system/bt/stack/include", "system/bt/utils/include", "system/bt/bta/include", + "system/bt/btif/include", "system/libhwbinder/include", ], } diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc index ed2908cdd..80f63deee 100644 --- a/hci/src/hci_layer.cc +++ b/hci/src/hci_layer.cc @@ -36,10 +36,12 @@ #include <mutex> #include "btcore/include/module.h" +#include "btif/include/btif_bqr.h" #include "btsnoop.h" #include "buffer_allocator.h" #include "common/message_loop_thread.h" #include "common/metrics.h" +#include "common/once_timer.h" #include "hci_inject.h" #include "hci_internals.h" #include "hcidefs.h" @@ -54,6 +56,7 @@ #define BT_HCI_TIMEOUT_TAG_NUM 1010000 using bluetooth::common::MessageLoopThread; +using bluetooth::common::OnceTimer; extern void hci_initialize(); extern void hci_transmit(BT_HDR* packet); @@ -110,7 +113,7 @@ static std::queue<base::Closure> command_queue; static alarm_t* command_response_timer; static list_t* commands_pending_response; static std::recursive_timed_mutex commands_pending_response_mutex; -static alarm_t* hci_timeout_abort_timer; +static OnceTimer abort_timer; // The hand-off point for data going to a higher layer, set by the higher layer static base::Callback<void(const base::Location&, BT_HDR*)> send_data_upwards; @@ -160,6 +163,14 @@ void sco_data_received(BT_HDR* packet) { packet_fragmenter->reassemble_and_dispatch(packet); } +void hal_service_died() { + if (abort_timer.IsScheduled()) { + LOG(ERROR) << "abort_timer is scheduled, wait for timeout"; + return; + } + abort(); +} + // Module lifecycle functions static future_t* hci_module_shut_down(); @@ -258,12 +269,6 @@ static future_t* hci_module_shut_down() { packet_fragmenter->cleanup(); - // Clean up abort timer, if it exists. - if (hci_timeout_abort_timer != NULL) { - alarm_free(hci_timeout_abort_timer); - hci_timeout_abort_timer = NULL; - } - if (hci_firmware_log_fd != INVALID_FD) { hci_close_firmware_log_file(hci_firmware_log_fd); hci_firmware_log_fd = INVALID_FD; @@ -436,7 +441,7 @@ static void fragmenter_transmit_finished(BT_HDR* packet, } // Abort. The chip has had time to write any debugging information. -static void hci_timeout_abort(void* unused_data) { +static void hci_timeout_abort(void) { LOG_ERROR(LOG_TAG, "%s restarting the Bluetooth process.", __func__); hci_close_firmware_log_file(hci_firmware_log_fd); @@ -445,6 +450,12 @@ static void hci_timeout_abort(void* unused_data) { abort(); } +static void hci_root_inflamed_abort(uint8_t error_code, + uint8_t vendor_error_code) { + LOG(FATAL) << __func__ << ": error_code = " << std::to_string(error_code) + << ", vendor_error_code = " << std::to_string(vendor_error_code); +} + static void command_timed_out_log_info(void* original_wait_entry) { LOG_ERROR(LOG_TAG, "%s: %d commands pending response", __func__, get_num_waiting_commands()); @@ -494,7 +505,7 @@ static void command_timed_out(void* original_wait_entry) { } // Don't request a firmware dump for multiple hci timeouts - if (hci_timeout_abort_timer != NULL || hci_firmware_log_fd != INVALID_FD) { + if (hci_firmware_log_fd != INVALID_FD) { return; } @@ -521,13 +532,13 @@ static void command_timed_out(void* original_wait_entry) { osi_free(bt_hdr); LOG_ERROR(LOG_TAG, "%s: Setting a timer to restart.", __func__); - hci_timeout_abort_timer = alarm_new("hci.hci_timeout_aborter"); - if (!hci_timeout_abort_timer) { + // alarm_default_callbacks thread post to hci_thread. + if (!abort_timer.Schedule( + hci_thread.GetWeakPtr(), FROM_HERE, base::Bind(hci_timeout_abort), + base::TimeDelta::FromMilliseconds(COMMAND_TIMEOUT_RESTART_MS))) { LOG_ERROR(LOG_TAG, "%s unable to create an abort timer.", __func__); abort(); } - alarm_set(hci_timeout_abort_timer, COMMAND_TIMEOUT_RESTART_MS, - hci_timeout_abort, nullptr); } // Event/packet receiving functions @@ -614,15 +625,62 @@ static bool filter_incoming_event(BT_HDR* packet) { } goto intercepted; - } else if (event_code == HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT) { - if (hci_firmware_log_fd == INVALID_FD) - hci_firmware_log_fd = hci_open_firmware_log_file(); + } else if (event_code == HCI_VENDOR_SPECIFIC_EVT) { + uint8_t sub_event_code; + STREAM_TO_UINT8(sub_event_code, stream); - if (hci_firmware_log_fd != INVALID_FD) - hci_log_firmware_debug_packet(hci_firmware_log_fd, packet); + if (sub_event_code == HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT) { + if (hci_firmware_log_fd == INVALID_FD) + hci_firmware_log_fd = hci_open_firmware_log_file(); - buffer_allocator->free(packet); - return true; + if (hci_firmware_log_fd != INVALID_FD) + hci_log_firmware_debug_packet(hci_firmware_log_fd, packet); + + buffer_allocator->free(packet); + return true; + } else if (sub_event_code == HCI_VSE_SUBCODE_BQR_SUB_EVT) { + uint8_t bqr_report_id; + STREAM_TO_UINT8(bqr_report_id, stream); + + if (bqr_report_id == + bluetooth::bqr::QUALITY_REPORT_ID_ROOT_INFLAMMATION && + packet->len >= bluetooth::bqr::kRootInflammationPacketMinSize) { + uint8_t error_code; + uint8_t vendor_error_code; + STREAM_TO_UINT8(error_code, stream); + STREAM_TO_UINT8(vendor_error_code, stream); + // TODO(ugoyu) Report to bluetooth metrics here + + LOG(ERROR) << __func__ + << ": Root inflammation event! setting timer to restart."; + { + // Try to stop hci command and startup timers + std::unique_lock<std::recursive_timed_mutex> lock( + commands_pending_response_mutex, std::defer_lock); + if (lock.try_lock_for(std::chrono::milliseconds( + COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) { + if (alarm_is_scheduled(startup_timer)) { + alarm_cancel(startup_timer); + } + if (alarm_is_scheduled(command_response_timer)) { + alarm_cancel(command_response_timer); + } + } else { + LOG(ERROR) << __func__ << ": Failed to obtain mutex"; + } + } + + // HwBinder thread post to hci_thread + if (!abort_timer.Schedule(hci_thread.GetWeakPtr(), FROM_HERE, + base::Bind(hci_root_inflamed_abort, + error_code, vendor_error_code), + base::TimeDelta::FromMilliseconds( + COMMAND_TIMEOUT_RESTART_MS))) { + LOG(ERROR) << "Failed to schedule abort_timer!"; + hci_root_inflamed_abort(error_code, vendor_error_code); + } + } + } } return false; diff --git a/hci/src/hci_layer_android.cc b/hci/src/hci_layer_android.cc index 92be0df59..a9fde50ee 100644 --- a/hci/src/hci_layer_android.cc +++ b/hci/src/hci_layer_android.cc @@ -51,6 +51,7 @@ extern void initialization_complete(); extern void hci_event_received(const base::Location& from_here, BT_HDR* packet); extern void acl_event_received(BT_HDR* packet); extern void sco_data_received(BT_HDR* packet); +extern void hal_service_died(); android::sp<IBluetoothHci> btHci; @@ -58,7 +59,7 @@ class BluetoothHciDeathRecipient : public hidl_death_recipient { public: virtual void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) { LOG_ERROR(LOG_TAG, "Bluetooth HAL service died!"); - abort(); + hal_service_died(); } }; android::sp<BluetoothHciDeathRecipient> bluetoothHciDeathRecipient = new BluetoothHciDeathRecipient(); diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h index 4c88de8d8..ae58ac22e 100644 --- a/include/hardware/bluetooth.h +++ b/include/hardware/bluetooth.h @@ -469,11 +469,10 @@ typedef struct { * The |start_restricted| flag inits the adapter in restricted mode. In * restricted mode, bonds that are created are marked as restricted in the * config file. These devices are deleted upon leaving restricted mode. - * The |is_single_user_mode| flag inits the adapter in NIAP mode. + * The |is_niap_mode| flag inits the adapter in NIAP mode. * The |is_atv| flag indicates whether the local device is an Android TV */ - int (*init)(bt_callbacks_t* callbacks, bool guest_mode, - bool is_single_user_mode, bool is_atv); + int (*init)(bt_callbacks_t* callbacks, bool guest_mode, bool is_niap_mode, bool is_atv); /** Enable Bluetooth. */ int (*enable)(); diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h index 67a67c56d..d12223425 100644 --- a/internal_include/bt_target.h +++ b/internal_include/bt_target.h @@ -108,7 +108,7 @@ #endif #ifndef BTA_DM_SDP_DB_SIZE -#define BTA_DM_SDP_DB_SIZE 8000 +#define BTA_DM_SDP_DB_SIZE 20000 #endif #ifndef HL_INCLUDED diff --git a/profile/avrcp/connection_handler.cc b/profile/avrcp/connection_handler.cc index 3177506a1..686f89be6 100644 --- a/profile/avrcp/connection_handler.cc +++ b/profile/avrcp/connection_handler.cc @@ -138,9 +138,7 @@ bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) { bool ConnectionHandler::DisconnectDevice(const RawAddress& bdaddr) { for (auto it = device_map_.begin(); it != device_map_.end(); it++) { if (bdaddr == it->second->GetAddress()) { - it->second->DeviceDisconnected(); uint8_t handle = it->first; - device_map_.erase(handle); return avrc_->Close(handle) == AVRC_SUCCESS; } } diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc index 4ca624b81..264eaf04c 100644 --- a/profile/avrcp/device.cc +++ b/profile/avrcp/device.cc @@ -98,6 +98,19 @@ void Device::VendorPacketHandler(uint8_t label, case CommandPdu::REGISTER_NOTIFICATION: { auto register_notification = Packet::Specialize<RegisterNotificationResponse>(pkt); + + if (!register_notification->IsValid()) { + DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid"; + auto response = + RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), + Status::INVALID_PARAMETER); + send_message(label, false, std::move(response)); + active_labels_.erase(label); + volume_interface_ = nullptr; + volume_ = VOL_REGISTRATION_FAILED; + return; + } + if (register_notification->GetEvent() != Event::VOLUME_CHANGED) { DEVICE_LOG(WARNING) << __func__ << ": Unhandled register notification received: " @@ -336,16 +349,6 @@ void Device::HandleVolumeChanged( uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) { DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim(); - if (!pkt->IsValid()) { - DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid"; - auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER); - send_message(label, false, std::move(response)); - active_labels_.erase(label); - volume_interface_ = nullptr; - volume_ = VOL_REGISTRATION_FAILED; - return; - } - if (volume_interface_ == nullptr) return; if (pkt->GetCType() == CType::REJECTED) { diff --git a/stack/Android.bp b/stack/Android.bp index 4863afbce..f9d11e21d 100644 --- a/stack/Android.bp +++ b/stack/Android.bp @@ -200,6 +200,7 @@ cc_test { ], srcs: [ "test/stack_a2dp_test.cc", + "test/stack_avrcp_test.cc", ], shared_libs: [ "libcrypto", @@ -446,36 +447,3 @@ cc_test { cfi: false, }, } - -cc_test { - name: "net_test_stack_a2dp_native", - defaults: ["fluoride_defaults"], - test_suites: ["device-tests"], - host_supported: true, - include_dirs: [ - "external/libldac/inc", - "system/bt", - "system/bt/stack/include", - ], - srcs: [ - "test/a2dp/a2dp_vendor_ldac_decoder_test.cc", - "test/a2dp/misc_fake.cc", - ], - shared_libs: [ - "libcrypto", - "libcutils", - "libprotobuf-cpp-lite", - ], - static_libs: [ - "libbt-common", - "libbt-protos-lite", - "liblog", - "libosi", - "libosi-AllocationTestHarness", - ], - sanitize: { - address: true, - cfi: true, - misc_undefined: ["bounds"], - }, -} diff --git a/stack/BUILD.gn b/stack/BUILD.gn index 00680c85e..87dc72639 100644 --- a/stack/BUILD.gn +++ b/stack/BUILD.gn @@ -202,6 +202,7 @@ executable("stack_unittests") { testonly = true sources = [ "test/stack_a2dp_test.cc", + "test/stack_avrcp_test.cc", ] include_dirs = [ diff --git a/stack/a2dp/a2dp_vendor_ldac_decoder.cc b/stack/a2dp/a2dp_vendor_ldac_decoder.cc index d49337a98..444af3426 100644 --- a/stack/a2dp/a2dp_vendor_ldac_decoder.cc +++ b/stack/a2dp/a2dp_vendor_ldac_decoder.cc @@ -217,20 +217,11 @@ void a2dp_vendor_ldac_decoder_cleanup(void) { } bool a2dp_vendor_ldac_decoder_decode_packet(BT_HDR* p_buf) { - if (p_buf == nullptr) { - LOG_ERROR(LOG_TAG, "%s Dropping packet with nullptr", __func__); - return false; - } unsigned char* pBuffer = reinterpret_cast<unsigned char*>(p_buf->data + p_buf->offset); // unsigned int bufferSize = p_buf->len; unsigned int bytesValid = p_buf->len; int err; - if (bytesValid == 0) { - LOG_WARN(LOG_TAG, "%s Dropping packet with zero length", __func__); - return false; - } - LDACBT_SMPL_FMT_T fmt; int bs_bytes, used_bytes, wrote_bytes, frame_number; diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc index 853f36985..33fbfa744 100644 --- a/stack/avdt/avdt_msg.cc +++ b/stack/avdt/avdt_msg.cc @@ -985,18 +985,30 @@ static uint8_t avdt_msg_prs_security_rsp(tAVDT_MSG* p_msg, uint8_t* p, * Returns Error code or zero if no error. * ******************************************************************************/ -static uint8_t avdt_msg_prs_rej(tAVDT_MSG* p_msg, uint8_t* p, uint8_t sig) { - if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG)) { - p_msg->hdr.err_param = *p++; - p_msg->hdr.err_code = *p; - } else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND)) { - AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param); - p_msg->hdr.err_code = *p; +static uint8_t avdt_msg_prs_rej(tAVDT_MSG* p_msg, uint8_t* p, uint16_t len, + uint8_t sig) { + uint8_t error = 0; + + if (len > 0) { + if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG)) { + p_msg->hdr.err_param = *p++; + len--; + } else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND)) { + AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param); + len--; + } + } + + if (len < 1) { + char error_info[] = "AVDT rejected response length mismatch"; + android_errorWriteWithInfoLog(0x534e4554, "79702484", -1, error_info, + strlen(error_info)); + error = AVDT_ERR_LENGTH; } else { p_msg->hdr.err_code = *p; } - return 0; + return error; } /******************************************************************************* @@ -1604,7 +1616,7 @@ void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) { evt = avdt_msg_rsp_2_evt[sig - 1]; } else /* msg_type == AVDT_MSG_TYPE_REJ */ { - err = avdt_msg_prs_rej(&msg, p, sig); + err = avdt_msg_prs_rej(&msg, p, p_buf->len, sig); evt = avdt_msg_rej_2_evt[sig - 1]; } diff --git a/stack/avrc/avrc_pars_ct.cc b/stack/avrc/avrc_pars_ct.cc index 80dc882da..39ed921d9 100644 --- a/stack/avrc/avrc_pars_ct.cc +++ b/stack/avrc/avrc_pars_ct.cc @@ -806,7 +806,7 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, if (len < min_len) goto length_error; BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p); BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p); - BE_STREAM_TO_UINT8(p_result->get_play_status.status, p); + BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p); break; case AVRC_PDU_SET_ADDRESSED_PLAYER: diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc index 22471bda5..fe1db3dbc 100644 --- a/stack/avrc/avrc_pars_tg.cc +++ b/stack/avrc/avrc_pars_tg.cc @@ -363,7 +363,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg, * * Description This function is used to parse cmds received for CTRL * Currently it is for SetAbsVolume and Volume Change - * Notification.. + * Notification. * * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed * successfully. @@ -390,6 +390,12 @@ tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) { return status; } +#define RETURN_STATUS_IF_FALSE(_status_, _b_, _msg_, ...) \ + if (!(_b_)) { \ + AVRC_TRACE_DEBUG(_msg_, ##__VA_ARGS__); \ + return _status_; \ + } + /******************************************************************************* * * Function avrc_pars_browsing_cmd @@ -409,6 +415,10 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, uint8_t* p = p_msg->p_browse_data; int count; + uint16_t min_len = 3; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + p_result->pdu = *p++; AVRC_TRACE_DEBUG("avrc_pars_browsing_cmd() pdu:0x%x", p_result->pdu); /* skip over len */ @@ -416,11 +426,20 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, switch (p_result->pdu) { case AVRC_PDU_SET_BROWSED_PLAYER: /* 0x70 */ + min_len += 2; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + // For current implementation all players are browsable. BE_STREAM_TO_UINT16(p_result->br_player.player_id, p); break; case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */ + + min_len += 10; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + STREAM_TO_UINT8(p_result->get_items.scope, p); // To be modified later here (Scope) when all browsing commands are // supported @@ -441,12 +460,21 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, if (buf_len < (count << 2)) p_result->get_items.attr_count = count = (buf_len >> 2); for (int idx = 0; idx < count; idx++) { + min_len += 4; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, + (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT32(p_result->get_items.p_attr_list[idx], p); } } break; case AVRC_PDU_CHANGE_PATH: /* 0x72 */ + min_len += 11; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT16(p_result->chg_path.uid_counter, p); BE_STREAM_TO_UINT8(p_result->chg_path.direction, p); if (p_result->chg_path.direction != AVRC_DIR_UP && @@ -457,7 +485,12 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, break; case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */ + min_len += 12; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT8(p_result->get_attrs.scope, p); + if (p_result->get_attrs.scope > AVRC_SCOPE_NOW_PLAYING) { status = AVRC_STS_BAD_SCOPE; break; @@ -473,6 +506,11 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, p_result->get_attrs.attr_count = count = (buf_len >> 2); for (int idx = 0, count = 0; idx < p_result->get_attrs.attr_count; idx++) { + min_len += 4; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, + (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT32(p_result->get_attrs.p_attr_list[count], p); if (AVRC_IS_VALID_MEDIA_ATTRIBUTE( p_result->get_attrs.p_attr_list[count])) { @@ -488,6 +526,10 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, break; case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: /* 0x75 */ + ++min_len; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT8(p_result->get_num_of_items.scope, p); if (p_result->get_num_of_items.scope > AVRC_SCOPE_NOW_PLAYING) { status = AVRC_STS_BAD_SCOPE; @@ -495,6 +537,10 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, break; case AVRC_PDU_SEARCH: /* 0x80 */ + min_len += 4; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_UINT16(p_result->search.string.charset_id, p); BE_STREAM_TO_UINT16(p_result->search.string.str_len, p); p_result->search.string.p_str = p_buf; @@ -504,6 +550,10 @@ static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg, } else { android_errorWriteLog(0x534e4554, "63146237"); } + min_len += p_result->search.string.str_len; + RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len), + "msg too short"); + BE_STREAM_TO_ARRAY(p, p_buf, p_result->search.string.str_len); } else { status = AVRC_STS_INTERNAL_ERR; diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc index 694577d0e..6daf2d23c 100644 --- a/stack/btm/btm_acl.cc +++ b/stack/btm/btm_acl.cc @@ -825,7 +825,8 @@ void btm_use_preferred_conn_params(const RawAddress& bda) { tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda); /* If there are any preferred connection parameters, set them now */ - if ((p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN) && + if ((p_lcb != NULL) && (p_dev_rec != NULL) && + (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN) && (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX) && (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN) && (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX) && diff --git a/stack/btm/btm_ble_batchscan.cc b/stack/btm/btm_ble_batchscan.cc index 89b3e6c55..db8282995 100644 --- a/stack/btm/btm_ble_batchscan.cc +++ b/stack/btm/btm_ble_batchscan.cc @@ -63,6 +63,7 @@ void btm_ble_batchscan_filter_track_adv_vse_cback(uint8_t len, uint8_t* p) { uint8_t sub_event = 0; tBTM_BLE_VSC_CB cmn_ble_vsc_cb; + if (len == 0) return; STREAM_TO_UINT8(sub_event, p); BTM_TRACE_EVENT( @@ -90,6 +91,7 @@ void btm_ble_batchscan_filter_track_adv_vse_cback(uint8_t len, uint8_t* p) { /* Extract the adv info details */ if (ADV_INFO_PRESENT == adv_data.advertiser_info_present) { + if (len < 15) return; STREAM_TO_UINT8(adv_data.tx_power, p); STREAM_TO_UINT8(adv_data.rssi_value, p); STREAM_TO_UINT16(adv_data.time_stamp, p); diff --git a/stack/btm/btm_ble_bgconn.cc b/stack/btm/btm_ble_bgconn.cc index 73256c883..209f49fe5 100644 --- a/stack/btm/btm_ble_bgconn.cc +++ b/stack/btm/btm_ble_bgconn.cc @@ -39,6 +39,7 @@ extern void btm_send_hci_create_connection( uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, uint8_t phy); extern void btm_ble_create_conn_cancel(); +void wl_remove_complete(uint8_t* p_data, uint16_t /* evt_len */); // Unfortunately (for now?) we have to maintain a copy of the device whitelist // on the host to determine if a device is pending to be connected or not. This @@ -72,7 +73,14 @@ static void background_connection_add(uint8_t addr_type, BackgroundConnection{address, addr_type, false, 0, false}; } else { BackgroundConnection* connection = &map_iter->second; - connection->addr_type = addr_type; + if (addr_type != connection->addr_type) { + LOG(INFO) << __func__ << " Addr type mismatch " << address; + btsnd_hcic_ble_remove_from_white_list( + connection->addr_type_in_wl, connection->address, + base::Bind(&wl_remove_complete)); + connection->addr_type = addr_type; + connection->in_controller_wl = false; + } connection->pending_removal = false; } } @@ -170,8 +178,7 @@ bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) { return true; // bonded device with identity address known - if (p_dev_rec->ble.identity_addr != address && - !p_dev_rec->ble.identity_addr.IsEmpty()) { + if (!p_dev_rec->ble.identity_addr.IsEmpty()) { return true; } @@ -197,8 +204,7 @@ bool btm_add_dev_to_controller(bool to_add, const RawAddress& bd_addr) { if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) { if (to_add) { - if (p_dev_rec->ble.identity_addr != bd_addr && - !p_dev_rec->ble.identity_addr.IsEmpty()) { + if (!p_dev_rec->ble.identity_addr.IsEmpty()) { background_connection_add(p_dev_rec->ble.identity_addr_type, p_dev_rec->ble.identity_addr); } else { @@ -212,8 +218,7 @@ bool btm_add_dev_to_controller(bool to_add, const RawAddress& bd_addr) { p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT; } else { - if (!p_dev_rec->ble.identity_addr.IsEmpty() && - p_dev_rec->ble.identity_addr != bd_addr) { + if (!p_dev_rec->ble.identity_addr.IsEmpty()) { background_connection_remove(p_dev_rec->ble.identity_addr); } else { background_connection_remove(bd_addr); diff --git a/stack/btm/btm_ble_connection_establishment.cc b/stack/btm/btm_ble_connection_establishment.cc index c0d77911e..77bc00f0e 100644 --- a/stack/btm/btm_ble_connection_establishment.cc +++ b/stack/btm/btm_ble_connection_establishment.cc @@ -159,6 +159,7 @@ void btm_ble_conn_complete(uint8_t* p, UNUSED_ATTR uint16_t evt_len, if (!btm_ble_init_pseudo_addr(match_rec, bda)) { /* assign the original address to be the current report address */ bda = match_rec->ble.pseudo_addr; + bda_type = match_rec->ble.ble_addr_type; } else { bda = match_rec->bd_addr; } diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc index c46acf0d3..05cac15b4 100644 --- a/stack/btm/btm_ble_gap.cc +++ b/stack/btm/btm_ble_gap.cc @@ -1755,6 +1755,7 @@ void btm_ble_process_adv_addr(RawAddress& bda, uint8_t* addr_type) { } else { // Assign the original address to be the current report address bda = match_rec->ble.pseudo_addr; + *addr_type = match_rec->ble.ble_addr_type; } } } diff --git a/stack/btm/btm_ble_multi_adv.cc b/stack/btm/btm_ble_multi_adv.cc index 22d2e176a..b425c0927 100644 --- a/stack/btm/btm_ble_multi_adv.cc +++ b/stack/btm/btm_ble_multi_adv.cc @@ -728,16 +728,13 @@ class BleAdvertisingManagerImpl data.insert(data.begin(), flags.begin(), flags.end()); } - // Find and fill TX Power with the correct value - if (data.size()) { - size_t i = 0; - while (i < data.size()) { - uint8_t type = data[i + 1]; - if (type == HCI_EIR_TX_POWER_LEVEL_TYPE) { - data[i + 2] = adv_inst[inst_id].tx_power; - } - i += data[i] + 1; + // Find and fill TX Power with the correct value. + // The TX Power section is a 3 byte section. + for (size_t i = 0; (i + 2) < data.size();) { + if (data[i + 1] == HCI_EIR_TX_POWER_LEVEL_TYPE) { + data[i + 2] = adv_inst[inst_id].tx_power; } + i += data[i] + 1; } VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size()); diff --git a/stack/btm/btm_inq.cc b/stack/btm/btm_inq.cc index 1a5d7f526..f56369b4b 100644 --- a/stack/btm/btm_inq.cc +++ b/stack/btm/btm_inq.cc @@ -25,6 +25,7 @@ * ******************************************************************************/ +#include <log/log.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> @@ -914,10 +915,9 @@ tBTM_STATUS BTM_CancelRemoteDeviceName(void) { /* Make sure there is not already one in progress */ if (p_inq->remname_active) { if (BTM_UseLeLink(p_inq->remname_bda)) { - if (btm_ble_cancel_remote_name(p_inq->remname_bda)) - return (BTM_CMD_STARTED); - else - return (BTM_UNKNOWN_ADDR); + /* Cancel remote name request for LE device, and process remote name + * callback. */ + btm_inq_rmt_name_failed_cancelled(); } else btsnd_hcic_rmt_name_req_cancel(p_inq->remname_bda); return (BTM_CMD_STARTED); @@ -1602,7 +1602,8 @@ static void btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST* p_inq) { * Returns void * ******************************************************************************/ -void btm_process_inq_results(uint8_t* p, uint8_t inq_res_mode) { +void btm_process_inq_results(uint8_t* p, uint8_t hci_evt_len, + uint8_t inq_res_mode) { uint8_t num_resp, xx; RawAddress bda; tINQ_DB_ENT* p_i; @@ -1631,10 +1632,29 @@ void btm_process_inq_results(uint8_t* p, uint8_t inq_res_mode) { STREAM_TO_UINT8(num_resp, p); - if (inq_res_mode == BTM_INQ_RESULT_EXTENDED && (num_resp > 1)) { - BTM_TRACE_ERROR("btm_process_inq_results() extended results (%d) > 1", - num_resp); - return; + if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) { + if (num_resp > 1) { + BTM_TRACE_ERROR("btm_process_inq_results() extended results (%d) > 1", + num_resp); + return; + } + + constexpr uint16_t extended_inquiry_result_size = 254; + if (hci_evt_len - 1 != extended_inquiry_result_size) { + android_errorWriteLog(0x534e4554, "141620271"); + BTM_TRACE_ERROR("%s: can't fit %d results in %d bytes", __func__, + num_resp, hci_evt_len); + return; + } + } else if (inq_res_mode == BTM_INQ_RESULT_STANDARD || + inq_res_mode == BTM_INQ_RESULT_WITH_RSSI) { + constexpr uint16_t inquiry_result_size = 14; + if (hci_evt_len < num_resp * inquiry_result_size) { + android_errorWriteLog(0x534e4554, "141620271"); + BTM_TRACE_ERROR("%s: can't fit %d results in %d bytes", __func__, + num_resp, hci_evt_len); + return; + } } for (xx = 0; xx < num_resp; xx++) { @@ -2070,22 +2090,22 @@ void btm_process_remote_name(const RawAddress* bda, BD_NAME bdn, } void btm_inq_remote_name_timer_timeout(UNUSED_ATTR void* data) { - btm_inq_rmt_name_failed(); + btm_inq_rmt_name_failed_cancelled(); } /******************************************************************************* * - * Function btm_inq_rmt_name_failed + * Function btm_inq_rmt_name_failed_cancelled * - * Description This function is if timeout expires while getting remote - * name. This is done for devices that incorrectly do not - * report operation failure + * Description This function is if timeout expires or request is cancelled + * while getting remote name. This is done for devices that + * incorrectly do not report operation failure * * Returns void * ******************************************************************************/ -void btm_inq_rmt_name_failed(void) { - BTM_TRACE_ERROR("btm_inq_rmt_name_failed() remname_active=%d", +void btm_inq_rmt_name_failed_cancelled(void) { + BTM_TRACE_ERROR("btm_inq_rmt_name_failed_cancelled() remname_active=%d", btm_cb.btm_inq_vars.remname_active); if (btm_cb.btm_inq_vars.remname_active) diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h index ee1d6554a..05180db5e 100644 --- a/stack/btm/btm_int.h +++ b/stack/btm/btm_int.h @@ -59,13 +59,14 @@ extern tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda, extern void btm_process_remote_name(const RawAddress* bda, BD_NAME name, uint16_t evt_len, uint8_t hci_status); -extern void btm_inq_rmt_name_failed(void); +extern void btm_inq_rmt_name_failed_cancelled(void); extern void btm_inq_remote_name_timer_timeout(void* data); /* Inquiry related functions */ extern void btm_clr_inq_db(const RawAddress* p_bda); extern void btm_inq_db_init(void); -extern void btm_process_inq_results(uint8_t* p, uint8_t inq_res_mode); +extern void btm_process_inq_results(uint8_t* p, uint8_t hci_evt_len, + uint8_t inq_res_mode); extern void btm_process_inq_complete(uint8_t status, uint8_t mode); extern void btm_process_cancel_complete(uint8_t status, uint8_t mode); extern void btm_event_filter_complete(uint8_t* p); diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc index ad3763f92..32e4b4e82 100644 --- a/stack/btm/btm_sec.cc +++ b/stack/btm/btm_sec.cc @@ -4313,12 +4313,15 @@ void btm_sec_connected(const RawAddress& bda, uint16_t handle, uint8_t status, } } - if (!addr_matched) { - /* Don't callback unless this Connection-Complete-failure event has the - * same mac address as the bonding device */ + /* p_auth_complete_callback might have freed the p_dev_rec, ensure it exists + * before accessing */ + p_dev_rec = btm_find_dev(bda); + if (!p_dev_rec) { + /* Don't callback when device security record was removed */ VLOG(1) << __func__ - << ": Different mac addresses: pairing_bda=" << btm_cb.pairing_bda - << ", bda=" << bda << ", do not callback"; + << ": device security record associated with this bda has been " + "removed! bda=" + << bda << ", do not callback!"; return; } diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc index c70448e81..52d5d60f8 100644 --- a/stack/btu/btu_hcif.cc +++ b/stack/btu/btu_hcif.cc @@ -48,6 +48,7 @@ #include "btu.h" #include "common/metrics.h" #include "device/include/controller.h" +#include "hci_evt_length.h" #include "hci_layer.h" #include "hcimsgs.h" #include "l2c_int.h" @@ -64,11 +65,12 @@ extern void smp_cancel_start_encryption_attempt(); /* L O C A L F U N C T I O N P R O T O T Y P E S */ /******************************************************************************/ static void btu_hcif_inquiry_comp_evt(uint8_t* p); -static void btu_hcif_inquiry_result_evt(uint8_t* p); -static void btu_hcif_inquiry_rssi_result_evt(uint8_t* p); -static void btu_hcif_extended_inquiry_result_evt(uint8_t* p); +static void btu_hcif_inquiry_result_evt(uint8_t* p, uint8_t hci_evt_len); +static void btu_hcif_inquiry_rssi_result_evt(uint8_t* p, uint8_t hci_evt_len); +static void btu_hcif_extended_inquiry_result_evt(uint8_t* p, + uint8_t hci_evt_len); -static void btu_hcif_connection_comp_evt(uint8_t* p); +static void btu_hcif_connection_comp_evt(uint8_t* p, uint8_t evt_len); static void btu_hcif_connection_request_evt(uint8_t* p); static void btu_hcif_disconnection_comp_evt(uint8_t* p); static void btu_hcif_authentication_comp_evt(uint8_t* p); @@ -85,7 +87,7 @@ static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command, static void btu_hcif_hardware_error_evt(uint8_t* p); static void btu_hcif_flush_occured_evt(void); static void btu_hcif_role_change_evt(uint8_t* p); -static void btu_hcif_num_compl_data_pkts_evt(uint8_t* p); +static void btu_hcif_num_compl_data_pkts_evt(uint8_t* p, uint8_t evt_len); static void btu_hcif_mode_change_evt(uint8_t* p); static void btu_hcif_pin_code_request_evt(uint8_t* p); static void btu_hcif_link_key_request_evt(uint8_t* p); @@ -256,6 +258,13 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) { STREAM_TO_UINT8(hci_evt_code, p); STREAM_TO_UINT8(hci_evt_len, p); + // validate event size + if (hci_evt_len < hci_event_parameters_minimum_length[hci_evt_code]) { + HCI_TRACE_WARNING("%s: evt:0x%2X, malformed event of size %hhd", __func__, + hci_evt_code, hci_evt_len); + return; + } + btu_hcif_log_event_metrics(hci_evt_code, p); switch (hci_evt_code) { @@ -263,16 +272,16 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) { btu_hcif_inquiry_comp_evt(p); break; case HCI_INQUIRY_RESULT_EVT: - btu_hcif_inquiry_result_evt(p); + btu_hcif_inquiry_result_evt(p, hci_evt_len); break; case HCI_INQUIRY_RSSI_RESULT_EVT: - btu_hcif_inquiry_rssi_result_evt(p); + btu_hcif_inquiry_rssi_result_evt(p, hci_evt_len); break; case HCI_EXTENDED_INQUIRY_RESULT_EVT: - btu_hcif_extended_inquiry_result_evt(p); + btu_hcif_extended_inquiry_result_evt(p, hci_evt_len); break; case HCI_CONNECTION_COMP_EVT: - btu_hcif_connection_comp_evt(p); + btu_hcif_connection_comp_evt(p, hci_evt_len); break; case HCI_CONNECTION_REQUEST_EVT: btu_hcif_connection_request_evt(p); @@ -326,7 +335,7 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) { btu_hcif_role_change_evt(p); break; case HCI_NUM_COMPL_DATA_PKTS_EVT: - btu_hcif_num_compl_data_pkts_evt(p); + btu_hcif_num_compl_data_pkts_evt(p, hci_evt_len); break; case HCI_MODE_CHANGE_EVT: btu_hcif_mode_change_evt(p); @@ -948,9 +957,9 @@ static void btu_hcif_inquiry_comp_evt(uint8_t* p) { * Returns void * ******************************************************************************/ -static void btu_hcif_inquiry_result_evt(uint8_t* p) { +static void btu_hcif_inquiry_result_evt(uint8_t* p, uint8_t hci_evt_len) { /* Store results in the cache */ - btm_process_inq_results(p, BTM_INQ_RESULT_STANDARD); + btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_STANDARD); } /******************************************************************************* @@ -962,9 +971,9 @@ static void btu_hcif_inquiry_result_evt(uint8_t* p) { * Returns void * ******************************************************************************/ -static void btu_hcif_inquiry_rssi_result_evt(uint8_t* p) { +static void btu_hcif_inquiry_rssi_result_evt(uint8_t* p, uint8_t hci_evt_len) { /* Store results in the cache */ - btm_process_inq_results(p, BTM_INQ_RESULT_WITH_RSSI); + btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_WITH_RSSI); } /******************************************************************************* @@ -976,9 +985,10 @@ static void btu_hcif_inquiry_rssi_result_evt(uint8_t* p) { * Returns void * ******************************************************************************/ -static void btu_hcif_extended_inquiry_result_evt(uint8_t* p) { +static void btu_hcif_extended_inquiry_result_evt(uint8_t* p, + uint8_t hci_evt_len) { /* Store results in the cache */ - btm_process_inq_results(p, BTM_INQ_RESULT_EXTENDED); + btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_EXTENDED); } /******************************************************************************* @@ -990,7 +1000,7 @@ static void btu_hcif_extended_inquiry_result_evt(uint8_t* p) { * Returns void * ******************************************************************************/ -static void btu_hcif_connection_comp_evt(uint8_t* p) { +static void btu_hcif_connection_comp_evt(uint8_t* p, uint8_t evt_len) { uint8_t status; uint16_t handle; RawAddress bda; @@ -998,6 +1008,12 @@ static void btu_hcif_connection_comp_evt(uint8_t* p) { uint8_t enc_mode; tBTM_ESCO_DATA esco_data; + if (evt_len < 11) { + android_errorWriteLog(0x534e4554, "141619686"); + HCI_TRACE_WARNING("%s: malformed event of size %hhd", __func__, evt_len); + return; + } + STREAM_TO_UINT8(status, p); STREAM_TO_UINT16(handle, p); STREAM_TO_BDADDR(bda, p); @@ -1699,9 +1715,9 @@ static void btu_hcif_role_change_evt(uint8_t* p) { * Returns void * ******************************************************************************/ -static void btu_hcif_num_compl_data_pkts_evt(uint8_t* p) { +static void btu_hcif_num_compl_data_pkts_evt(uint8_t* p, uint8_t evt_len) { /* Process for L2CAP and SCO */ - l2c_link_process_num_completed_pkts(p); + l2c_link_process_num_completed_pkts(p, evt_len); /* Send on to SCO */ /*?? No SCO for now */ diff --git a/stack/gatt/gatt_main.cc b/stack/gatt/gatt_main.cc index 87f9c87f7..ed8d3fd11 100644 --- a/stack/gatt/gatt_main.cc +++ b/stack/gatt/gatt_main.cc @@ -823,6 +823,9 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { } } + /* Remove the direct connection */ + connection_manager::on_connection_complete(p_tcb->peer_bda); + if (!p_tcb->app_hold_link.empty() && p_tcb->att_lcid == L2CAP_ATT_CID) { /* disable idle timeout if one or more clients are holding the link disable * the idle timer */ diff --git a/stack/include/hci_evt_length.h b/stack/include/hci_evt_length.h new file mode 100644 index 000000000..ea8dfdff1 --- /dev/null +++ b/stack/include/hci_evt_length.h @@ -0,0 +1,278 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Definitions for HCI Event Parameter Minimum Length + */ +static const uint8_t hci_event_parameters_minimum_length[] = { + 0, // 0x00 - N/A + 1, // 0x01 - HCI_Inquiry_Complete Event + 15, // 0x02 - HCI_Inquiry_Result Event (Num_Responses = 1) + 11, // 0x03 - HCI_Connection_Complete Event + 10, // 0x04 - HCI_Connection_Request Event + 4, // 0x05 - HCI_Disconnection_Complete Event + 3, // 0x06 - HCI_Authentication_Complete Event + 255, // 0x07 - HCI_Remote_Name_Request_Complete Event + 4, // 0x08 - HCI_Encryption_Change Event + 3, // 0x09 - HCI_Change_Connection_Link_Key_Complete Event + 4, // 0x0A - HCI_Master_Link_Key_Complete Event + 11, // 0x0B - HCI_Read_Remote_Supported_Features_Complete Event + 8, // 0x0C - HCI_Read_Remote_Version_Information_Complete Event + 21, // 0x0D - HCI_QoS_Setup_Complete Event + 3, // 0x0E - HCI_Command_Complete Event (Depends on command) + 4, // 0x0F - HCI_Command_Status Event + 1, // 0x10 - HCI_Hardware_Error Event + 2, // 0x11 - HCI_Flush_Occurred Event + 8, // 0x12 - HCI_Role_Change Event + 5, // 0x13 - HCI_Number_Of_Completed_Packets Event (Num_Handles = 1) + 6, // 0x14 - HCI_Mode_Change Event + 23, // 0x15 - HCI_Return_Link_Keys Event (Num_Keys = 1) + 6, // 0x16 - HCI_PIN_Code_Request Event + 6, // 0x17 - HCI_Link_Key_Request Event + 23, // 0x18 - HCI_Link_Key_Notification Event + 3, // 0x19 - HCI_Loopback_Command Event (Depends on command) + 1, // 0x1A - HCI_Data_Buffer_Overflow Event + 3, // 0x1B - HCI_Max_Slots_Change Event + 5, // 0x1C - HCI_Read_Clock_Offset_Complete Event + 5, // 0x1D - HCI_Connection_Packet_Type_Changed Event + 2, // 0x1E - HCI_QoS_Violation Event + 7, // 0x1F - HCI_Page_Scan_Mode_Change Event (Deprecated) + 7, // 0x20 - HCI_Page_Scan_Repetition_Mode_Change Event + 22, // 0x21 - HCI_Flow_Specification_Complet Event + 15, // 0x22 - HCI_Inquiry_Result_with_RSSI Event (Num_Responses = 1) + 13, // 0x23 - HCI_Read_Remote_Extended_Features_Complete Event + 0, // 0x24 - N/A + 0, // 0x25 - N/A + 0, // 0x26 - N/A + 0, // 0x27 - N/A + 0, // 0x28 - N/A + 0, // 0x29 - N/A + 0, // 0x2A - N/A + 0, // 0x2B - N/A + 17, // 0x2C - HCI_Synchronous_Connection_Complete Event + 9, // 0x2D - HCI_Synchronous_Connection_Changed Event + 11, // 0x2E - HCI_Sniff_Subrating Event + 255, // 0x2F - HCI_Extended_Inquiry_Result Event + 3, // 0x30 - HCI_Encryption_Key_Refresh_Complete Event + 6, // 0x31 - HCI_IO_Capability_Request Event + 9, // 0x32 - HCI_IO_Capability_Response Event + 10, // 0x33 - HCI_User_Confirmation_Request Event + 6, // 0x34 - HCI_User_Passkey_Request Event + 6, // 0x35 - HCI_Remote_OOB_Data_Request Event + 7, // 0x36 - HCI_Simple_Pairing_Complete Event + 0, // 0x37 - N/A + 4, // 0x38 - HCI_Link_Supervision_Timeout_Changed Event + 2, // 0x39 - HCI_Enhanced_Flush_Complete Event + 0, // 0x3A - N/A + 10, // 0x3B - HCI_User_Passkey_Notification Event + 7, // 0x3C - HCI_Keypress_Notification Event + 14, // 0x3D - HCI_Remote_Host_Supported_Features_Notification Event + 0, // 0x3E - LE Meta event + 0, // 0x3F - N/A + 2, // 0x40 - HCI_Physical_Link_Complete Event + 1, // 0x41 - HCI_Channel_Selected Event + 3, // 0x42 - HCI_Disconnection_Physical_Link_Complete Event + 2, // 0x43 - HCI_Physical_Link_Loss_Early_Warning Event + 1, // 0x44 - HCI_Physical_Link_Recovery Event + 5, // 0x45 - HCI_Logical_Link_Complete Event + 4, // 0x46 - HCI_Disconnection_Logical_Link_Complete Event + 3, // 0x47 - HCI_Flow_Spec_Modify_Complete Event + 9, // 0x48 - HCI_Number_Of_Completed_Data_Blocks Event (Num_Handles = 1) + 2, // 0x49 - HCI_AMP_Start_Test Event + 2, // 0x4A - HCI_AMP_Test_End Event + 18, // 0x4B - HCI_AMP_Receiver_Report Event + 3, // 0x4C - HCI_Short_Range_Mode_Change_Complete Event + 2, // 0x4D - HCI_AMP_Status_Change Event + 9, // 0x4E - HCI_Triggered_Clock_Capture Event + 1, // 0x4F - HCI_Synchronization_Train_Complete Event + 29, // 0x50 - HCI_Synchronization_Train_Received Event + 18, // 0x51 - HCI_Connectionless_Slave_Broadcast_Receive Event + // (Data_Length = 0) + 7, // 0x52 - HCI_Connectionless_Slave_Broadcast_Timeout Event + 7, // 0x53 - HCI_Truncated_Page_Complete Event + 0, // 0x54 - HCI_Slave_Page_Response_Timeout Event + 10, // 0x55 - HCI_Connectionless_Slave_Broadcast_Channel_Map_Change Event + 4, // 0x56 - HCI_Inquiry_Response_Notification Event + 2, // 0x57 - HCI_Authenticated_Payload_Timeout_Expired Event + 8, // 0x58 - HCI_SAM_Status_Change Event + 0, // 0x59 - N/A + 0, // 0x5A - N/A + 0, // 0x5B - N/A + 0, // 0x5C - N/A + 0, // 0x5D - N/A + 0, // 0x5E - N/A + 0, // 0x5F - N/A + 0, // 0x60 - N/A + 0, // 0x61 - N/A + 0, // 0x62 - N/A + 0, // 0x63 - N/A + 0, // 0x64 - N/A + 0, // 0x65 - N/A + 0, // 0x66 - N/A + 0, // 0x67 - N/A + 0, // 0x68 - N/A + 0, // 0x69 - N/A + 0, // 0x6A - N/A + 0, // 0x6B - N/A + 0, // 0x6C - N/A + 0, // 0x6D - N/A + 0, // 0x6E - N/A + 0, // 0x6F - N/A + 0, // 0x70 - N/A + 0, // 0x71 - N/A + 0, // 0x72 - N/A + 0, // 0x73 - N/A + 0, // 0x74 - N/A + 0, // 0x75 - N/A + 0, // 0x76 - N/A + 0, // 0x77 - N/A + 0, // 0x78 - N/A + 0, // 0x79 - N/A + 0, // 0x7A - N/A + 0, // 0x7B - N/A + 0, // 0x7C - N/A + 0, // 0x7D - N/A + 0, // 0x7E - N/A + 0, // 0x7F - N/A + 0, // 0x80 - N/A + 0, // 0x81 - N/A + 0, // 0x82 - N/A + 0, // 0x83 - N/A + 0, // 0x84 - N/A + 0, // 0x85 - N/A + 0, // 0x86 - N/A + 0, // 0x87 - N/A + 0, // 0x88 - N/A + 0, // 0x89 - N/A + 0, // 0x8A - N/A + 0, // 0x8B - N/A + 0, // 0x8C - N/A + 0, // 0x8D - N/A + 0, // 0x8E - N/A + 0, // 0x8F - N/A + 0, // 0x90 - N/A + 0, // 0x91 - N/A + 0, // 0x92 - N/A + 0, // 0x93 - N/A + 0, // 0x94 - N/A + 0, // 0x95 - N/A + 0, // 0x96 - N/A + 0, // 0x97 - N/A + 0, // 0x98 - N/A + 0, // 0x99 - N/A + 0, // 0x9A - N/A + 0, // 0x9B - N/A + 0, // 0x9C - N/A + 0, // 0x9D - N/A + 0, // 0x9E - N/A + 0, // 0x9F - N/A + 0, // 0xA0 - N/A + 0, // 0xA1 - N/A + 0, // 0xA2 - N/A + 0, // 0xA3 - N/A + 0, // 0xA4 - N/A + 0, // 0xA5 - N/A + 0, // 0xA6 - N/A + 0, // 0xA7 - N/A + 0, // 0xA8 - N/A + 0, // 0xA9 - N/A + 0, // 0xAA - N/A + 0, // 0xAB - N/A + 0, // 0xAC - N/A + 0, // 0xAD - N/A + 0, // 0xAE - N/A + 0, // 0xAF - N/A + 0, // 0xB0 - N/A + 0, // 0xB1 - N/A + 0, // 0xB2 - N/A + 0, // 0xB3 - N/A + 0, // 0xB4 - N/A + 0, // 0xB5 - N/A + 0, // 0xB6 - N/A + 0, // 0xB7 - N/A + 0, // 0xB8 - N/A + 0, // 0xB9 - N/A + 0, // 0xBA - N/A + 0, // 0xBB - N/A + 0, // 0xBC - N/A + 0, // 0xBD - N/A + 0, // 0xBE - N/A + 0, // 0xBF - N/A + 0, // 0xC0 - N/A + 0, // 0xC1 - N/A + 0, // 0xC2 - N/A + 0, // 0xC3 - N/A + 0, // 0xC4 - N/A + 0, // 0xC5 - N/A + 0, // 0xC6 - N/A + 0, // 0xC7 - N/A + 0, // 0xC8 - N/A + 0, // 0xC9 - N/A + 0, // 0xCA - N/A + 0, // 0xCB - N/A + 0, // 0xCC - N/A + 0, // 0xCD - N/A + 0, // 0xCE - N/A + 0, // 0xCF - N/A + 0, // 0xD0 - N/A + 0, // 0xD1 - N/A + 0, // 0xD2 - N/A + 0, // 0xD3 - N/A + 0, // 0xD4 - N/A + 0, // 0xD5 - N/A + 0, // 0xD6 - N/A + 0, // 0xD7 - N/A + 0, // 0xD8 - N/A + 0, // 0xD9 - N/A + 0, // 0xDA - N/A + 0, // 0xDB - N/A + 0, // 0xDC - N/A + 0, // 0xDD - N/A + 0, // 0xDE - N/A + 0, // 0xDF - N/A + 0, // 0xE0 - N/A + 0, // 0xE1 - N/A + 0, // 0xE2 - N/A + 0, // 0xE3 - N/A + 0, // 0xE4 - N/A + 0, // 0xE5 - N/A + 0, // 0xE6 - N/A + 0, // 0xE7 - N/A + 0, // 0xE8 - N/A + 0, // 0xE9 - N/A + 0, // 0xEA - N/A + 0, // 0xEB - N/A + 0, // 0xEC - N/A + 0, // 0xED - N/A + 0, // 0xEE - N/A + 0, // 0xEF - N/A + 0, // 0xF0 - N/A + 0, // 0xF1 - N/A + 0, // 0xF2 - N/A + 0, // 0xF3 - N/A + 0, // 0xF4 - N/A + 0, // 0xF5 - N/A + 0, // 0xF6 - N/A + 0, // 0xF7 - N/A + 0, // 0xF8 - N/A + 0, // 0xF9 - N/A + 0, // 0xFA - N/A + 0, // 0xFB - N/A + 0, // 0xFC - N/A + 0, // 0xFD - N/A + 0, // 0xFE - N/A + 0, // 0xFF - HCI_Vendor_Specific Event +}; diff --git a/stack/include/ldacBT_bco_for_fluoride.h b/stack/include/ldacBT_bco_for_fluoride.h deleted file mode 100644 index 9666a7c9d..000000000 --- a/stack/include/ldacBT_bco_for_fluoride.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2016 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. - */ -#ifndef LDACBT_BCO_FOR_FLUORIDE_H__ -#define LDACBT_BCO_FOR_FLUORIDE_H__ - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef LDAC_BCO_API -#define LDAC_BCO_API -#endif /* LDAC_BCO_API */ - -/* This file contains the definitions, declarations and macros for an - * implementation of LDAC buffer control operation. - */ - -#define LDAC_BCO_ERR_NONE 0 -#define LDAC_BCO_ERR_FATAL (-1) - -/* LDAC BCO handle type */ -typedef struct _ldacbt_bco_handle* HANDLE_LDAC_BCO; - -typedef void (*decoded_data_callback_t)(uint8_t* buf, uint32_t len); - -/* Prepare to use LDAC BCO. - * - Register a callback function for passing decoded data. - * - Allocation of LDAC BCO handle. - * Format - * HANDLE_LDAC_BCO ldac_BCO_init(decoded_data_callback_t decode_callback); - * Arguments - * decoded_data_callback_t decode_callback - * Callback function that outputs PCM data after decoding. - * (See also a2dp_codec_api.h) - * Return value - * HANDLE_LDAC_BCO for success, NULL for failure. - */ -LDAC_BCO_API HANDLE_LDAC_BCO -ldac_BCO_init(decoded_data_callback_t decode_callback); - -/* End LDAC BCO. - * - Release of LDAC BCO handle. - * Format - * int32_t ldac_BCO_cleanup(HANDLE_LDAC_BCO hLdacBco); - * Arguments - * HANDLE_LDAC_BCO hLdacBco LDAC BCO handle. - * Return value - * int32_t : Processing result. - * LDAC_BCO_ERR_NONE:Successful completion - * LDAC_BCO_ERR_FATAL:Error - * Note - * The function ldac_BCO_init() shall be called before calling this - * function. - */ -LDAC_BCO_API int32_t ldac_BCO_cleanup(HANDLE_LDAC_BCO hLdacBco); - -/* Decode LDAC packets. - * - Perform buffer control and decode processing. - * Format - * int32_t ldac_BCO_decode_packet(HANDLE_LDAC_BCO hLdacBco, void *data, - * int32_t length); - * Arguments - * HANDLE_LDAC_BCO hLdacBco LDAC BCO handle. - * void *data LDAC packet. - * int32_t length LDAC packet size. - * Return value - * int32_t : Processing result. - * LDAC_BCO_ERR_NONE:Successful completion - * LDAC_BCO_ERR_FATAL:Error - * Note - * The function ldac_BCO_init() shall be called before calling this - * function. - */ -LDAC_BCO_API int32_t ldac_BCO_decode_packet(HANDLE_LDAC_BCO hLdacBco, - void* data, int32_t length); - -/* Start decoding process. - * - Start or resume decoder thread. - * Format - * int32_t ldac_BCO_start(HANDLE_LDAC_BCO hLdacBco); - * Arguments - * HANDLE_LDAC_BCO hLdacBco LDAC BCO handle. - * Return value - * int32_t : Processing result. - * LDAC_BCO_ERR_NONE:Successful completion - * LDAC_BCO_ERR_FATAL:Error - * Note - * The function ldac_BCO_init() shall be called before calling this - * function. - */ -LDAC_BCO_API int32_t ldac_BCO_start(HANDLE_LDAC_BCO hLdacBco); - -/* Suspend decoding process. - * - Suspend the decoder thread. - * Format - * int32_t ldac_BCO_suspend(HANDLE_LDAC_BCO hLdacBco); - * Arguments - * HANDLE_LDAC_BCO hLdacBco LDAC BCO handle. - * Return value - * int32_t : Processing result. - * LDAC_BCO_ERR_NONE:Successful completion - * LDAC_BCO_ERR_FATAL:Error - * Note - * The function ldac_BCO_init() shall be called before calling this - * function. - */ -LDAC_BCO_API int32_t ldac_BCO_suspend(HANDLE_LDAC_BCO hLdacBco); - -/* Configure codec information. - * - Set sample rate, bits/sample and channel mode. - * Format - * int32_t ldac_BCO_configure(HANDLE_LDAC_BCO hLdacBco, - * int32_t sample_rate, int32_t bits_per_sample, - * int32_t channel_mode); - * Arguments - * HANDLE_LDAC_BCO hLdacBco LDAC BCO handle. - * int32_t sample_rate sample rate. - * int32_t bits_per_sample bits/sample. - * int32_t channel_mode channel mode. - * Return value - * int32_t : Processing result. - * LDAC_BCO_ERR_NONE:Successful completion - * LDAC_BCO_ERR_FATAL:Error - * Note - * The function ldac_BCO_init() shall be called before calling this - * function. - */ -LDAC_BCO_API int32_t ldac_BCO_configure(HANDLE_LDAC_BCO hLdacBco, - int32_t sample_rate, - int32_t bits_per_sample, - int32_t channel_mode); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LDACBT_BCO_FOR_FLUORIDE_H__ */ diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h index 53b6f3239..e58efaf16 100644 --- a/stack/l2cap/l2c_int.h +++ b/stack/l2cap/l2c_int.h @@ -713,7 +713,7 @@ extern void l2c_info_resp_timer_timeout(void* data); extern void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf); extern void l2c_link_adjust_allocation(void); -extern void l2c_link_process_num_completed_pkts(uint8_t* p); +extern void l2c_link_process_num_completed_pkts(uint8_t* p, uint8_t evt_len); extern void l2c_link_process_num_completed_blocks(uint8_t controller_id, uint8_t* p, uint16_t evt_len); extern void l2c_link_processs_num_bufs(uint16_t num_lm_acl_bufs); diff --git a/stack/l2cap/l2c_link.cc b/stack/l2cap/l2c_link.cc index 8e04c6e98..958425d20 100644 --- a/stack/l2cap/l2c_link.cc +++ b/stack/l2cap/l2c_link.cc @@ -40,6 +40,7 @@ #include "l2c_api.h" #include "l2c_int.h" #include "l2cdefs.h" +#include "log/log.h" #include "osi/include/osi.h" static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, @@ -675,6 +676,8 @@ void l2c_link_adjust_allocation(void) { uint16_t num_hipri_links = 0; uint16_t controller_xmit_quota = l2cb.num_lm_acl_bufs; uint16_t high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A; + bool is_share_buffer = + (l2cb.num_lm_ble_bufs == L2C_DEF_NUM_BLE_BUF_SHARED) ? true : false; /* If no links active, reset buffer quotas and controller buffers */ if (l2cb.num_links_active == 0) { @@ -685,7 +688,8 @@ void l2c_link_adjust_allocation(void) { /* First, count the links */ for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { - if (p_lcb->in_use) { + if (p_lcb->in_use && + (is_share_buffer || p_lcb->transport != BT_TRANSPORT_LE)) { if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) num_hipri_links++; else @@ -732,7 +736,8 @@ void l2c_link_adjust_allocation(void) { /* Now, assign the quotas to each link */ for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { - if (p_lcb->in_use) { + if (p_lcb->in_use && + (is_share_buffer || p_lcb->transport != BT_TRANSPORT_LE)) { if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) { p_lcb->link_xmit_quota = high_pri_link_quota; } else { @@ -1210,13 +1215,22 @@ static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, * Returns void * ******************************************************************************/ -void l2c_link_process_num_completed_pkts(uint8_t* p) { +void l2c_link_process_num_completed_pkts(uint8_t* p, uint8_t evt_len) { uint8_t num_handles, xx; uint16_t handle; uint16_t num_sent; tL2C_LCB* p_lcb; - STREAM_TO_UINT8(num_handles, p); + if (evt_len > 0) { + STREAM_TO_UINT8(num_handles, p); + } else { + num_handles = 0; + } + + if (num_handles > evt_len / (2 * sizeof(uint16_t))) { + android_errorWriteLog(0x534e4554, "141617601"); + num_handles = evt_len / (2 * sizeof(uint16_t)); + } for (xx = 0; xx < num_handles; xx++) { STREAM_TO_UINT16(handle, p); diff --git a/stack/l2cap/l2c_main.cc b/stack/l2cap/l2c_main.cc index 128f60e97..52d77c5b2 100644 --- a/stack/l2cap/l2c_main.cc +++ b/stack/l2cap/l2c_main.cc @@ -97,6 +97,11 @@ void l2c_rcv_acl_data(BT_HDR* p_msg) { /* There is a slight possibility (specifically with USB) that we get an */ /* L2CAP connection request before we get the HCI connection complete. */ /* So for these types of messages, hold them for up to 2 seconds. */ + if (l2cap_len == 0) { + L2CAP_TRACE_WARNING("received empty L2CAP packet"); + osi_free(p_msg); + return; + } uint8_t cmd_code; STREAM_TO_UINT8(cmd_code, p); diff --git a/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc b/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc deleted file mode 100644 index ac8c2609c..000000000 --- a/stack/test/a2dp/a2dp_vendor_ldac_decoder_test.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <base/logging.h> -#include <gtest/gtest.h> -#include <stdio.h> -#include <cstdint> - -#include "stack/include/ldacBT_bco_for_fluoride.h" - -#include "osi/test/AllocationTestHarness.h" -#undef LOG_TAG -#include "stack/a2dp/a2dp_vendor_ldac_decoder.cc" - -extern void allocation_tracker_uninit(void); -namespace { - -uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; } - -} // namespace - -/** - * Test class to test selected functionality in stack/a2dp - */ -class A2dpStackTest : public AllocationTestHarness { - protected: - void SetUp() override { - AllocationTestHarness::SetUp(); - // Disable our allocation tracker to allow ASAN full range - allocation_tracker_uninit(); - } - - void TearDown() override { AllocationTestHarness::TearDown(); } - - BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const { - auto packet = AllocatePacket(data.size()); - std::copy(data.cbegin(), data.cend(), Data(packet)); - return packet; - } - - private: - BT_HDR* AllocatePacket(size_t packet_length) const { - BT_HDR* packet = - static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length)); - packet->len = packet_length; - return packet; - } -}; - -TEST_F(A2dpStackTest, DecodePacket_ZeroLength) { - const std::vector<uint8_t> data; - BT_HDR* p_buf = AllocateL2capPacket(data); - CHECK(!a2dp_vendor_ldac_decoder_decode_packet(p_buf)); - osi_free(p_buf); -} diff --git a/stack/test/a2dp/misc_fake.cc b/stack/test/a2dp/misc_fake.cc deleted file mode 100644 index 6f06218fb..000000000 --- a/stack/test/a2dp/misc_fake.cc +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "service/common/bluetooth/a2dp_codec_config.h" -#include "stack/include/a2dp_vendor_ldac.h" - -bluetooth::A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) { - return nullptr; -} - -int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info) { return 0; } -int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* p_codec_info) { - return 0; -} -int A2DP_VendorGetChannelModeCodeLdac(const uint8_t* p_codec_info) { return 0; } diff --git a/stack/test/stack_avrcp_test.cc b/stack/test/stack_avrcp_test.cc new file mode 100644 index 000000000..ad1cc9e72 --- /dev/null +++ b/stack/test/stack_avrcp_test.cc @@ -0,0 +1,112 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <dlfcn.h> +#include <gtest/gtest.h> + +#include "stack/include/avrc_api.h" + +class StackAvrcpTest : public ::testing::Test { + protected: + StackAvrcpTest() = default; + + virtual ~StackAvrcpTest() = default; +}; + +TEST_F(StackAvrcpTest, test_avrcp_parse_browse_cmd) { + uint8_t scratch_buf[512]{}; + tAVRC_MSG msg{}; + tAVRC_COMMAND result{}; + uint8_t browse_cmd_buf[512]{}; + + msg.hdr.opcode = AVRC_OP_BROWSE; + msg.browse.p_browse_data = browse_cmd_buf; + msg.browse.browse_len = 2; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_SET_BROWSED_PLAYER; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + msg.browse.browse_len = 5; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_GET_FOLDER_ITEMS; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + msg.browse.browse_len = 13; + uint8_t* p = &browse_cmd_buf[3]; + UINT8_TO_STREAM(p, AVRC_SCOPE_NOW_PLAYING); // scope + UINT32_TO_STREAM(p, 0x00000001); // start_item + UINT32_TO_STREAM(p, 0x00000002); // end_item + browse_cmd_buf[12] = 0; // attr_count + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_CHANGE_PATH; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + msg.browse.browse_len = 14; + p = &browse_cmd_buf[3]; + UINT16_TO_STREAM(p, 0x1234); // uid_counter + UINT8_TO_STREAM(p, AVRC_DIR_UP); // direction + UINT8_TO_STREAM(p, 0); // attr_count + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_GET_ITEM_ATTRIBUTES; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + msg.browse.browse_len = 15; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + msg.browse.browse_len = 4; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); + + memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf)); + browse_cmd_buf[0] = AVRC_PDU_SEARCH; + msg.browse.browse_len = 3; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_BAD_CMD); + + p = &browse_cmd_buf[3]; + UINT16_TO_STREAM(p, 0x0000); // charset_id + UINT16_TO_STREAM(p, 0x0000); // str_len + msg.browse.browse_len = 7; + EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)), + AVRC_STS_NO_ERROR); +} |