diff options
Diffstat (limited to 'le_audio/system/bt/bta/bap/uclient_main.cc')
-rw-r--r-- | le_audio/system/bt/bta/bap/uclient_main.cc | 548 |
1 files changed, 548 insertions, 0 deletions
diff --git a/le_audio/system/bt/bta/bap/uclient_main.cc b/le_audio/system/bt/bta/bap/uclient_main.cc new file mode 100644 index 000000000..0df1c39f6 --- /dev/null +++ b/le_audio/system/bt/bta/bap/uclient_main.cc @@ -0,0 +1,548 @@ +/****************************************************************************** + * + * Copyright 2021 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 "bta_bap_uclient_api.h" +#include "ucast_client_int.h" +#include "bta_pacs_client_api.h" +#include "bta_ascs_client_api.h" +#include <hardware/bt_pacs_client.h> +#include <base/bind.h> +#include <base/callback.h> +#include <base/logging.h> +#include "bta_closure_api.h" +#include "bt_trace.h" + +namespace bluetooth { +namespace bap { +namespace ucast { + +using base::Bind; +using base::Unretained; +using base::Closure; +using bluetooth::Uuid; + +using bluetooth::bap::pacs::PacsClient; +using bluetooth::bap::pacs::ConnectionState; +using bluetooth::bap::pacs::CodecConfig; +using bluetooth::bap::pacs::PacsClientCallbacks; + +using bluetooth::bap::ascs::AscsClient; +using bluetooth::bap::ascs::GattState; +using bluetooth::bap::ascs::AscsClientCallbacks; +using bluetooth::bap::ascs::AseOpId; +using bluetooth::bap::ascs::AseOpStatus; +using bluetooth::bap::ascs::AseParams; + +using bluetooth::bap::ucast::UstreamManagers; +using bluetooth::bap::ucast::UstreamManager; + +using bluetooth::bap::ucast::BapEventData; +using bluetooth::bap::ucast::BapEvent; +using bluetooth::bap::ucast::BapConnect; +using bluetooth::bap::ucast::BapDisconnect; +using bluetooth::bap::ucast::BapStart; +using bluetooth::bap::ucast::BapStop; +using bluetooth::bap::ucast::BapReconfig; +using bluetooth::bap::ucast::PacsConnectionState; +using bluetooth::bap::ucast::PacsDiscovery; +using bluetooth::bap::ucast::PacsAvailableContexts; + +using bluetooth::bap::ucast::CisGroupState; +using bluetooth::bap::ucast::CisStreamState; +using bluetooth::bap::cis::CigState; +using bluetooth::bap::cis::CisState; +using bluetooth::bap::cis::CisInterface; + +using bluetooth::bap::alarm::BapAlarm; +using bluetooth::bap::alarm::BapAlarmCallbacks; + +class UcastClientImpl; +UcastClientImpl* instance = nullptr; + +class CisInterfaceCallbacksImpl : public CisInterfaceCallbacks { + public: + ~CisInterfaceCallbacksImpl() = default; + /** Callback for connection state change */ + void OnCigState(uint8_t cig_id, CigState state) { + do_in_bta_thread(FROM_HERE, Bind(&CisInterfaceCallbacks::OnCigState, + Unretained(UcastClient::Get()), cig_id, + state)); + + } + + void OnCisState(uint8_t cig_id, uint8_t cis_id, + uint8_t direction, CisState state) { + do_in_bta_thread(FROM_HERE, Bind(&CisInterfaceCallbacks::OnCisState, + Unretained(UcastClient::Get()), cig_id, + cis_id, direction, state)); + } +}; + +class PacsClientCallbacksImpl : public PacsClientCallbacks { + public: + ~PacsClientCallbacksImpl() = default; + void OnInitialized(int status, int client_id) override { + LOG(WARNING) << __func__ << ": status =" << loghex(status); + do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnInitialized, + Unretained(UcastClient::Get()), status, + client_id)); + } + + void OnConnectionState(const RawAddress& address, + bluetooth::bap::pacs::ConnectionState state) override { + LOG(WARNING) << __func__ << ": address=" << address; + do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnConnectionState, + Unretained(UcastClient::Get()), + address, state)); + } + + void OnAudioContextAvailable(const RawAddress& address, + uint32_t available_contexts) override { + do_in_bta_thread(FROM_HERE, + Bind(&PacsClientCallbacks::OnAudioContextAvailable, + Unretained(UcastClient::Get()), + address, available_contexts)); + } + + void OnSearchComplete(int status, const RawAddress& address, + std::vector<CodecConfig> sink_pac_records, + std::vector<CodecConfig> src_pac_records, + uint32_t sink_locations, + uint32_t src_locations, + uint32_t available_contexts, + uint32_t supported_contexts) override { + do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnSearchComplete, + Unretained(UcastClient::Get()), + status, address, + sink_pac_records, + src_pac_records, + sink_locations, + src_locations, + available_contexts, + supported_contexts)); + } +}; + +class AscsClientCallbacksImpl : public AscsClientCallbacks { + public: + ~AscsClientCallbacksImpl() = default; + void OnAscsInitialized(int status, int client_id) override { + do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnAscsInitialized, + Unretained(UcastClient::Get()), status, + client_id)); + } + + void OnConnectionState(const RawAddress& address, + bluetooth::bap::ascs::GattState state) override { + DVLOG(2) << __func__ << " address: " << address; + do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnConnectionState, + Unretained(UcastClient::Get()), + address, state)); + } + + void OnAseOpFailed(const RawAddress& address, + AseOpId ase_op_id, + std::vector<AseOpStatus> status) { + do_in_bta_thread(FROM_HERE, + Bind(&AscsClientCallbacks::OnAseOpFailed, + Unretained(UcastClient::Get()), + address, ase_op_id, status)); + + } + + void OnAseState(const RawAddress& address, + AseParams ase) override { + do_in_bta_thread(FROM_HERE, + Bind(&AscsClientCallbacks::OnAseState, + Unretained(UcastClient::Get()), + address, ase)); + } + + void OnSearchComplete(int status, const RawAddress& address, + std::vector<AseParams> sink_ase_list, + std::vector<AseParams> src_ase_list) override { + do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnSearchComplete, + Unretained(UcastClient::Get()), + status, address, sink_ase_list, + src_ase_list)); + } +}; + +class BapAlarmCallbacksImpl : public BapAlarmCallbacks { + public: + ~BapAlarmCallbacksImpl() = default; + /** Callback for timer timeout */ + void OnTimeout(void* data) { + do_in_bta_thread(FROM_HERE, Bind(&BapAlarmCallbacks::OnTimeout, + Unretained(UcastClient::Get()), data)); + } +}; + +class UcastClientImpl : public UcastClient { + public: + ~UcastClientImpl() override = default; + + // APIs exposed for upper layers + void Connect(std::vector<RawAddress> address, bool is_direct, + std::vector<StreamConnect> streams) override { + if(address.size() == 1) { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address[0], + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + BapConnect data = { .bd_addr = address, .is_direct = is_direct, + .streams = streams}; + mgr->ProcessEvent(BAP_CONNECT_REQ_EVT, &data); + } + } + + void Disconnect(const RawAddress& address, + std::vector<StreamType> streams) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + + // hand over the request to stream manager + BapDisconnect data = { .bd_addr = address, + .streams = streams}; + mgr->ProcessEvent(BAP_DISCONNECT_REQ_EVT, &data); + } + + void Start(const RawAddress& address, + std::vector<StreamType> streams) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + + // hand over the request to stream manager + BapStart data = { .bd_addr = address, + .streams = streams}; + mgr->ProcessEvent(BAP_START_REQ_EVT, &data); + } + + void Stop(const RawAddress& address, + std::vector<StreamType> streams) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + + // hand over the request to stream manager + BapStop data = { .bd_addr = address, + .streams = streams}; + mgr->ProcessEvent(BAP_STOP_REQ_EVT, &data); + + } + + void Reconfigure(const RawAddress& address, + std::vector<StreamReconfig> streams) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + + // hand over the request to stream manager + BapReconfig data = { .bd_addr = address, + .streams = streams}; + mgr->ProcessEvent(BAP_RECONFIG_REQ_EVT, &data); + } + + void UpdateStream(const RawAddress& address, + std::vector<StreamUpdate> update_streams) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + + // hand over the request to stream manager + BapStreamUpdate data = { .bd_addr = address, + .update_streams = update_streams}; + mgr->ProcessEvent(BAP_STREAM_UPDATE_REQ_EVT, &data); + } + + // To be called from device specific stream manager + bool ReportStreamState(const RawAddress& address) { + //TODO to check + return true; + + } + + // PACS client related callbacks + // to be forwarded to device specific stream manager + void OnInitialized(int status, int client_id) override { + LOG(WARNING) << __func__ << ": actual client_id = " << loghex(client_id); + pacs_client_id = client_id; + } + + void OnConnectionState(const RawAddress& address, + ConnectionState state) override { + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + PacsConnectionState data = { .bd_addr = address, + .state = state + }; + mgr->ProcessEvent(PACS_CONNECTION_STATE_EVT, &data); + } + + void OnAudioContextAvailable(const RawAddress& address, + uint32_t available_contexts) override { + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + PacsAvailableContexts data = { + .bd_addr = address, + .available_contexts = available_contexts, + }; + mgr->ProcessEvent(PACS_AUDIO_CONTEXT_RES_EVT, &data); + } + + void OnSearchComplete(int status, const RawAddress& address, + std::vector<CodecConfig> sink_pac_records, + std::vector<CodecConfig> src_pac_records, + uint32_t sink_locations, + uint32_t src_locations, + uint32_t available_contexts, + uint32_t supported_contexts) override { + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + PacsDiscovery data = { + .status = status, + .bd_addr = address, + .sink_pac_records = sink_pac_records, + .src_pac_records = src_pac_records, + .sink_locations = sink_locations, + .src_locations = src_locations, + .available_contexts = available_contexts, + .supported_contexts = supported_contexts + }; + mgr->ProcessEvent(PACS_DISCOVERY_RES_EVT, &data); + } + + // ASCS client related callbacks + // to be forwarded to device specific stream manager + void OnAscsInitialized(int status, int client_id) override { + + } + + void OnConnectionState(const RawAddress& address, + bluetooth::bap::ascs::GattState state) override { + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + AscsConnectionState data = { .bd_addr = address, + .state = state + }; + mgr->ProcessEvent(ASCS_CONNECTION_STATE_EVT, &data); + } + + void OnAseOpFailed(const RawAddress& address, + AseOpId ase_op_id, + std::vector<AseOpStatus> status) { + + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + AscsOpFailed data = { + .bd_addr = address, + .ase_op_id = ase_op_id, + .ase_list = status + }; + mgr->ProcessEvent(ASCS_ASE_OP_FAILED_EVT, &data); + } + + void OnAseState(const RawAddress& address, + AseParams ase_params) override { + LOG(WARNING) << __func__ << ": address=" << address; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + AscsState data = { + .bd_addr = address, + .ase_params = ase_params + }; + mgr->ProcessEvent(ASCS_ASE_STATE_EVT, &data); + } + + void OnSearchComplete(int status, const RawAddress& address, + std::vector<AseParams> sink_ase_list, + std::vector<AseParams> src_ase_list) override { + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + AscsDiscovery data = { + .status = status, + .bd_addr = address, + .sink_ases_list = sink_ase_list, + .src_ases_list = src_ase_list + }; + mgr->ProcessEvent(ASCS_DISCOVERY_RES_EVT, &data); + } + + // cis callbacks + void OnCigState(uint8_t cig_id, CigState state) override { + std::vector<UstreamManager *> *mgrs_list = strm_mgrs.GetAllManagers(); + // hand over the request to stream manager + CisGroupState data = { + .cig_id = cig_id, + .state = state + }; + + for (auto it = mgrs_list->begin(); it != mgrs_list->end(); it++) { + (*it)->ProcessEvent(CIS_GROUP_STATE_EVT, &data); + } + } + + void OnCisState(uint8_t cig_id, uint8_t cis_id, uint8_t direction, + CisState state) override { + std::vector<UstreamManager *> *mgrs_list = strm_mgrs.GetAllManagers(); + // hand over the request to stream manager + CisStreamState data = { + .cig_id = cig_id, + .cis_id = cis_id, + .direction = direction, + .state = state + }; + + for (auto it = mgrs_list->begin(); it != mgrs_list->end(); it++) { + (*it)->ProcessEvent(CIS_STATE_EVT, &data); + } + } + + void OnTimeout(void* data) override { + LOG(ERROR) << __func__; + BapTimeout* data_ = (BapTimeout *)data; + UstreamManager *mgr = strm_mgrs.FindorAddByAddress(data_->bd_addr, + pacs_client, pacs_client_id, + ascs_client, cis_intf, + ucl_callbacks, bap_alarm); + // hand over the request to stream manager + mgr->ProcessEvent(BAP_TIME_OUT_EVT, data); + } + + bool Init(UcastClientCallbacks *callback) { + // register callbacks with CIS, ASCS client, PACS client + pacs_callbacks = new PacsClientCallbacksImpl; + PacsClient::Initialize(pacs_callbacks); + pacs_client = PacsClient::Get(); + + ascs_callbacks = new AscsClientCallbacksImpl; + AscsClient::Init(ascs_callbacks); + ascs_client = AscsClient::Get(); + + cis_callbacks = new CisInterfaceCallbacksImpl; + CisInterface::Initialize(cis_callbacks); + cis_intf = CisInterface::Get(); + + bap_alarm_cb = new BapAlarmCallbacksImpl; + BapAlarm::Initialize(bap_alarm_cb); + bap_alarm = BapAlarm::Get(); + + pacs_client_id = 0; + if(ucl_callbacks != nullptr) { + // flag an error + return false; + } else { + ucl_callbacks = callback; + return true; + } + } + + bool CleanUp() { + if(ucl_callbacks != nullptr) { + ucl_callbacks = nullptr; + //call clean ups for each clients(ascs, pacs, cis and bap_alarm) + LOG(ERROR) << __func__ + <<": Cleaning up pacs, ascs clients, cis intf and bap_alarm."; + pacs_client->CleanUp(pacs_client_id); + ascs_client->CleanUp(0x01); + cis_intf->CleanUp(); + bap_alarm->CleanUp(); + pacs_client = nullptr; + ascs_client = nullptr; + cis_intf = nullptr; + bap_alarm = nullptr; + // remove all stream managers and other clean ups + return true; + } else { + return false; + } + } + + private: + UcastClientCallbacks* ucl_callbacks; + UstreamManagers strm_mgrs; + PacsClient *pacs_client; + AscsClient *ascs_client; + PacsClientCallbacks *pacs_callbacks; + AscsClientCallbacks *ascs_callbacks; + CisInterface *cis_intf; + CisInterfaceCallbacks *cis_callbacks; + uint16_t pacs_client_id; + BapAlarm* bap_alarm; + BapAlarmCallbacks* bap_alarm_cb; +}; + +void UcastClient::Initialize(UcastClientCallbacks* callbacks) { + if (!instance) { + instance = new UcastClientImpl(); + instance->Init(callbacks); + } else { + LOG(ERROR) << __func__ << " 2nd client registration ignored"; + } +} + +void UcastClient::CleanUp() { + if(instance && instance->CleanUp()) { + delete instance; + instance = nullptr; + } +} + +UcastClient* UcastClient::Get() { + CHECK(instance); + return instance; +} + +} // namespace ucast +} // namespace bap +} // namespace bluetooth |