blob: 0df1c39f6c77045c7676e2395b1889674ae8a51e [file] [log] [blame]
/******************************************************************************
*
* 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