aboutsummaryrefslogtreecommitdiff
path: root/le_audio/system/bt/bta/bap/uclient_main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'le_audio/system/bt/bta/bap/uclient_main.cc')
-rw-r--r--le_audio/system/bt/bta/bap/uclient_main.cc548
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