Merge "Add audio configuration API and the callback function for bluetooth.audo@2.2"

This commit is contained in:
Treehugger Robot 2022-01-05 02:27:59 +00:00 committed by Gerrit Code Review
commit e944c8538f
7 changed files with 278 additions and 5 deletions

View file

@ -59,4 +59,14 @@ interface IBluetoothAudioProvider extends @2.1::IBluetoothAudioProvider {
*/
startSession_2_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
generates (Status status, fmq_sync<uint8_t> dataMQ);
/**
* Called when the audio configuration of the stream has been changed.
*
* @param audioConfig The audio configuration negotiated with the remote
* device. The PCM parameters are set if software based encoding,
* otherwise the correct codec configuration is used for hardware
* encoding.
*/
updateAudioConfiguration(AudioConfiguration audioConfig);
};

View file

@ -186,6 +186,29 @@ Return<void> BluetoothAudioProvider::endSession() {
return Void();
}
Return<void> BluetoothAudioProvider::updateAudioConfiguration(
const AudioConfiguration& audioConfig) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
if (stack_iface_ == nullptr) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
return Void();
}
if (audioConfig.getDiscriminator() != audio_config_.getDiscriminator()) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " audio config type is not match";
return Void();
}
audio_config_ = audioConfig;
BluetoothAudioSessionReport_2_2::ReportAudioConfigChanged(session_type_,
audio_config_);
return Void();
}
} // namespace implementation
} // namespace V2_2
} // namespace audio

View file

@ -53,6 +53,8 @@ class BluetoothAudioProvider : public IBluetoothAudioProvider {
Return<void> streamStarted(BluetoothAudioStatus status) override;
Return<void> streamSuspended(BluetoothAudioStatus status) override;
Return<void> endSession() override;
Return<void> updateAudioConfiguration(
const AudioConfiguration& audioConfig) override;
protected:
sp<BluetoothAudioDeathRecipient> death_recipient_;

View file

@ -48,20 +48,38 @@ class BluetoothAudioSessionControl_2_2 {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
return session_ptr->GetAudioSession()->RegisterStatusCback(cbacks);
PortStatusCallbacks_2_2 cb = {
.control_result_cb_ = cbacks.control_result_cb_,
.session_changed_cb_ = cbacks.session_changed_cb_,
.audio_configuration_changed_cb_ = nullptr};
return session_ptr->RegisterStatusCback(cb);
}
return kObserversCookieUndefined;
}
// The control API helps the bluetooth_audio module to register
// PortStatusCallbacks_2_2
// @return: cookie - the assigned number to this bluetooth_audio output
static uint16_t RegisterControlResultCback(
const SessionType_2_1& session_type,
const PortStatusCallbacks_2_2& cbacks) {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
return session_ptr->RegisterStatusCback(cbacks);
}
return kObserversCookieUndefined;
}
// The control API helps the bluetooth_audio module to unregister
// PortStatusCallbacks
// PortStatusCallbacks and PortStatusCallbacks_2_2
// @param: cookie - indicates which bluetooth_audio output is
static void UnregisterControlResultCback(const SessionType_2_1& session_type,
uint16_t cookie) {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
session_ptr->GetAudioSession()->UnregisterStatusCback(cookie);
session_ptr->UnregisterStatusCback(cookie);
}
}

View file

@ -60,7 +60,20 @@ class BluetoothAudioSessionReport_2_2 {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
session_ptr->GetAudioSession()->ReportControlStatus(start_resp, status);
session_ptr->ReportControlStatus(start_resp, status);
}
}
// The API reports the Bluetooth stack has replied the changed of the audio
// configuration, and will inform registered bluetooth_audio outputs
static void ReportAudioConfigChanged(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type,
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
audio_config) {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
session_ptr->ReportAudioConfigChanged(audio_config);
}
}
};

View file

@ -359,7 +359,7 @@ void BluetoothAudioSession_2_2::OnSessionStarted(
audio_session->stack_iface_ = stack_iface;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< ", AudioConfiguration=" << toString(audio_config);
audio_session->ReportSessionStatus();
ReportSessionStatus();
};
}
}
@ -386,7 +386,150 @@ void BluetoothAudioSession_2_2::OnSessionEnded() {
audio_session->stack_iface_ = nullptr;
audio_session->UpdateDataPath(nullptr);
if (toggled) {
ReportSessionStatus();
}
}
// The control function helps the bluetooth_audio module to register
// PortStatusCallbacks_2_2
// @return: cookie - the assigned number to this bluetooth_audio output
uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
const PortStatusCallbacks_2_2& cbacks) {
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
PortStatusCallbacks cb = {
.control_result_cb_ = cbacks.control_result_cb_,
.session_changed_cb_ = cbacks.session_changed_cb_};
return audio_session->RegisterStatusCback(cb);
}
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
uint16_t cookie = ObserversCookieGetInitValue(session_type_2_1_);
uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_2_1_);
while (cookie < cookie_upper_bound) {
if (observers_.find(cookie) == observers_.end()) {
break;
}
++cookie;
}
if (cookie >= cookie_upper_bound) {
LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " has " << observers_.size()
<< " observers already (No Resource)";
return kObserversCookieUndefined;
}
std::shared_ptr<struct PortStatusCallbacks_2_2> cb =
std::make_shared<struct PortStatusCallbacks_2_2>();
*cb = cbacks;
observers_[cookie] = cb;
return cookie;
}
// The control function helps the bluetooth_audio module to unregister
// PortStatusCallbacks_2_2
// @param: cookie - indicates which bluetooth_audio output is
void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
audio_session->UnregisterStatusCback(cookie);
return;
}
if (observers_.erase(cookie) != 1) {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " no such provider=0x"
<< android::base::StringPrintf("%04x", cookie);
}
}
// invoking the registered session_changed_cb_
void BluetoothAudioSession_2_2::ReportSessionStatus() {
// This is locked already by OnSessionStarted / OnSessionEnded
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
audio_session->ReportSessionStatus();
return;
}
if (observers_.empty()) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " has NO port state observer";
return;
}
for (auto& observer : observers_) {
uint16_t cookie = observer.first;
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " notify to bluetooth_audio=0x"
<< android::base::StringPrintf("%04x", cookie);
cb->session_changed_cb_(cookie);
}
}
// The report function is used to report that the Bluetooth stack has notified
// the result of startStream or suspendStream, and will invoke
// control_result_cb_ to notify registered bluetooth_audio outputs
void BluetoothAudioSession_2_2::ReportControlStatus(
bool start_resp, const BluetoothAudioStatus& status) {
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
audio_session->ReportControlStatus(start_resp, status);
return;
}
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
if (observers_.empty()) {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " has NO port state observer";
return;
}
for (auto& observer : observers_) {
uint16_t cookie = observer.first;
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
LOG(INFO) << __func__ << " - status=" << toString(status)
<< " for SessionType=" << toString(session_type_2_1_)
<< ", bluetooth_audio=0x"
<< android::base::StringPrintf("%04x", cookie)
<< (start_resp ? " started" : " suspended");
cb->control_result_cb_(cookie, start_resp, status);
}
}
// The report function is used to report that the Bluetooth stack has notified
// the result of startStream or suspendStream, and will invoke
// control_result_cb_ to notify registered bluetooth_audio outputs
void BluetoothAudioSession_2_2::ReportAudioConfigChanged(
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
audio_config) {
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
return;
}
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
audio_config_2_2_ = audio_config;
if (observers_.empty()) {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< " has NO port state observer";
return;
}
for (auto& observer : observers_) {
uint16_t cookie = observer.first;
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_2_1_)
<< ", bluetooth_audio=0x"
<< android::base::StringPrintf("%04x", cookie);
if (cb->audio_configuration_changed_cb_ != nullptr) {
cb->audio_configuration_changed_cb_(cookie);
}
}
}

View file

@ -28,6 +28,40 @@ namespace android {
namespace bluetooth {
namespace audio {
inline uint16_t ObserversCookieGetInitValue(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type) {
return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
}
inline uint16_t ObserversCookieGetUpperBound(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type) {
return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
kObserversCookieSize;
}
struct PortStatusCallbacks_2_2 {
// control_result_cb_ - when the Bluetooth stack reports results of
// streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
// this callback to report to the bluetooth_audio module.
// @param: cookie - indicates which bluetooth_audio output should handle
// @param: start_resp - this report is for startStream or not
// @param: status - the result of startStream
std::function<void(uint16_t cookie, bool start_resp,
const BluetoothAudioStatus& status)>
control_result_cb_;
// session_changed_cb_ - when the Bluetooth stack start / end session, the
// BluetoothAudioProvider will invoke this callback to notify to the
// bluetooth_audio module.
// @param: cookie - indicates which bluetooth_audio output should handle
std::function<void(uint16_t cookie)> session_changed_cb_;
// audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
// configuration, the BluetoothAudioProvider will invoke this callback to
// notify to the bluetooth_audio module.
// @param: cookie - indicates which bluetooth_audio output should handle
std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
};
class BluetoothAudioSession_2_2 {
private:
std::shared_ptr<BluetoothAudioSession> audio_session;
@ -50,6 +84,13 @@ class BluetoothAudioSession_2_2 {
static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
invalidLeOffloadAudioConfiguration;
// saving those registered bluetooth_audio's callbacks
std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks_2_2>>
observers_;
// invoking the registered session_changed_cb_
void ReportSessionStatus();
public:
BluetoothAudioSession_2_2(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
@ -82,6 +123,29 @@ class BluetoothAudioSession_2_2 {
bool SuspendStream();
void StopStream();
// The control function helps the bluetooth_audio module to register
// PortStatusCallbacks_2_2
// @return: cookie - the assigned number to this bluetooth_audio output
uint16_t RegisterStatusCback(const PortStatusCallbacks_2_2& cbacks);
// The control function helps the bluetooth_audio module to unregister
// PortStatusCallbacks_2_2
// @param: cookie - indicates which bluetooth_audio output is
void UnregisterStatusCback(uint16_t cookie);
// The report function is used to report that the Bluetooth stack has notified
// the result of startStream or suspendStream, and will invoke
// control_result_cb_ to notify registered bluetooth_audio outputs
void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
// The report function is used to report that the Bluetooth stack has notified
// the audio configuration changed, and will invoke
// audio_configuration_changed_cb_ to notify registered bluetooth_audio
// outputs
void ReportAudioConfigChanged(
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
audio_config);
// The control function is for the bluetooth_audio module to get the current
// AudioConfiguration
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration