diff --git a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp index b4a61b6ce9..3fe1a4dc13 100644 --- a/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp +++ b/bluetooth/audio/2.1/default/A2dpOffloadAudioProvider.cpp @@ -22,8 +22,8 @@ #include #include -#include "BluetoothAudioSessionReport.h" -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSessionReport_2_1.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { @@ -32,7 +32,7 @@ namespace audio { namespace V2_1 { namespace implementation { -using ::android::bluetooth::audio::BluetoothAudioSessionReport; +using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::MessageQueue; using ::android::hardware::Void; @@ -81,8 +81,8 @@ Return A2dpOffloadAudioProvider::startSession( Return A2dpOffloadAudioProvider::onSessionReady( startSession_cb _hidl_cb) { - BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, - nullptr, audio_config_); + BluetoothAudioSessionReport_2_1::OnSessionStarted(session_type_, stack_iface_, + nullptr, audio_config_); _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor()); return Void(); } diff --git a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp index a67c341abb..a37176ba4d 100644 --- a/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp +++ b/bluetooth/audio/2.1/default/A2dpSoftwareAudioProvider.cpp @@ -20,8 +20,8 @@ #include -#include "BluetoothAudioSessionReport.h" -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSessionReport_2_1.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { @@ -30,7 +30,7 @@ namespace audio { namespace V2_1 { namespace implementation { -using ::android::bluetooth::audio::BluetoothAudioSessionReport; +using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1; using ::android::hardware::Void; using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; @@ -96,7 +96,7 @@ Return A2dpSoftwareAudioProvider::startSession( Return A2dpSoftwareAudioProvider::onSessionReady( startSession_cb _hidl_cb) { if (mDataMQ && mDataMQ->isValid()) { - BluetoothAudioSessionReport::OnSessionStarted( + BluetoothAudioSessionReport_2_1::OnSessionStarted( session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_); _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc()); } else { diff --git a/bluetooth/audio/2.1/default/Android.bp b/bluetooth/audio/2.1/default/Android.bp index 5381fec43e..c05aa3f04a 100644 --- a/bluetooth/audio/2.1/default/Android.bp +++ b/bluetooth/audio/2.1/default/Android.bp @@ -16,29 +16,7 @@ cc_library_shared { "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", "libbase", - "libbluetooth_audio_session_2_1", - "libcutils", - "libfmq", - "libhidlbase", - "liblog", - "libutils", - ], -} - -cc_library_shared { - name: "libbluetooth_audio_session_2_1", - defaults: ["hidl_defaults"], - vendor: true, - srcs: [ - "session/BluetoothAudioSession.cpp", - "session/BluetoothAudioSupportedCodecsDB.cpp", - ], - export_include_dirs: ["session/"], - header_libs: ["libhardware_headers"], - shared_libs: [ - "android.hardware.bluetooth.audio@2.0", - "android.hardware.bluetooth.audio@2.1", - "libbase", + "libbluetooth_audio_session", "libcutils", "libfmq", "libhidlbase", diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp index 73fe06c961..38889ae543 100644 --- a/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp +++ b/bluetooth/audio/2.1/default/BluetoothAudioProvider.cpp @@ -20,8 +20,8 @@ #include -#include "BluetoothAudioSessionReport.h" -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSessionReport_2_1.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { @@ -30,7 +30,7 @@ namespace audio { namespace V2_1 { namespace implementation { -using ::android::bluetooth::audio::BluetoothAudioSessionReport; +using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::MessageQueue; using ::android::hardware::Void; @@ -105,8 +105,8 @@ Return BluetoothAudioProvider::streamStarted( * HAL server should start the streaming on data path. */ if (stack_iface_) { - BluetoothAudioSessionReport::ReportControlStatus(session_type_, true, - status); + BluetoothAudioSessionReport_2_1::ReportControlStatus(session_type_, true, + status); } else { LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status) << " has NO session"; @@ -125,8 +125,8 @@ Return BluetoothAudioProvider::streamSuspended( * HAL server should suspend the streaming on data path. */ if (stack_iface_) { - BluetoothAudioSessionReport::ReportControlStatus(session_type_, false, - status); + BluetoothAudioSessionReport_2_1::ReportControlStatus(session_type_, false, + status); } else { LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status) << " has NO session"; @@ -139,7 +139,7 @@ Return BluetoothAudioProvider::endSession() { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); if (stack_iface_) { - BluetoothAudioSessionReport::OnSessionEnded(session_type_); + BluetoothAudioSessionReport_2_1::OnSessionEnded(session_type_); stack_iface_->unlinkToDeath(death_recipient_); } else { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp index adf27170d7..e1b1ac6793 100644 --- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp +++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp @@ -20,7 +20,7 @@ #include -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { diff --git a/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp index aded7e157a..712bd4f718 100644 --- a/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp +++ b/bluetooth/audio/2.1/default/HearingAidAudioProvider.cpp @@ -20,8 +20,8 @@ #include -#include "BluetoothAudioSessionReport.h" -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSessionReport_2_1.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { @@ -30,7 +30,7 @@ namespace audio { namespace V2_1 { namespace implementation { -using ::android::bluetooth::audio::BluetoothAudioSessionReport; +using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1; using ::android::hardware::Void; using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; @@ -95,7 +95,7 @@ Return HearingAidAudioProvider::startSession( Return HearingAidAudioProvider::onSessionReady(startSession_cb _hidl_cb) { if (mDataMQ && mDataMQ->isValid()) { - BluetoothAudioSessionReport::OnSessionStarted( + BluetoothAudioSessionReport_2_1::OnSessionStarted( session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_); _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc()); } else { diff --git a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp index 9c2b4fe1db..2ebf6c511e 100644 --- a/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp +++ b/bluetooth/audio/2.1/default/LeAudioAudioProvider.cpp @@ -21,8 +21,8 @@ #include -#include "BluetoothAudioSessionReport.h" -#include "BluetoothAudioSupportedCodecsDB.h" +#include "BluetoothAudioSessionReport_2_1.h" +#include "BluetoothAudioSupportedCodecsDB_2_1.h" namespace android { namespace hardware { @@ -31,7 +31,7 @@ namespace audio { namespace V2_1 { namespace implementation { -using ::android::bluetooth::audio::BluetoothAudioSessionReport; +using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1; using ::android::hardware::Void; using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; @@ -179,7 +179,7 @@ Return LeAudioAudioProvider::startSession_2_1( Return LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) { if (mDataMQ && mDataMQ->isValid()) { - BluetoothAudioSessionReport::OnSessionStarted( + BluetoothAudioSessionReport_2_1::OnSessionStarted( session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_); _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc()); } else { diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp deleted file mode 100644 index ea2c54afe1..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.cpp +++ /dev/null @@ -1,467 +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. - */ - -#define LOG_TAG "BTAudioProviderSession" - -#include "BluetoothAudioSession.h" - -#include -#include - -namespace android { -namespace bluetooth { -namespace audio { - -using ::android::hardware::audio::common::V5_0::AudioContentType; -using ::android::hardware::audio::common::V5_0::AudioUsage; -using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata; -using ::android::hardware::audio::common::V5_0::SourceMetadata; -using ::android::hardware::bluetooth::audio::V2_0::CodecType; -using ::android::hardware::bluetooth::audio::V2_0::TimeSpec; - -const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = { - .codecType = CodecType::UNKNOWN, - .encodedAudioBitrate = 0x00000000, - .peerMtu = 0xffff, - .isScmstEnabled = false, - .config = {}}; -AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration = - {}; -AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {}; - -static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending -static constexpr int kFmqReceiveTimeoutMs = - 1000; // 1000 ms timeout for receiving -static constexpr int kWritePollMs = 1; // polled non-blocking interval -static constexpr int kReadPollMs = 1; // polled non-blocking interval - -static inline timespec timespec_convert_from_hal(const TimeSpec& TS) { - return {.tv_sec = static_cast(TS.tvSec), - .tv_nsec = static_cast(TS.tvNSec)}; -} - -BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type) - : session_type_(session_type), stack_iface_(nullptr), mDataMQ(nullptr) { - invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters); - invalidOffloadAudioConfiguration.codecConfig(kInvalidCodecConfiguration); -} - -// The report function is used to report that the Bluetooth stack has started -// this session without any failure, and will invoke session_changed_cb_ to -// notify those registered bluetooth_audio outputs -void BluetoothAudioSession::OnSessionStarted( - const sp stack_iface, const DataMQ::Descriptor* dataMQ, - const AudioConfiguration& audio_config) { - std::lock_guard guard(mutex_); - if (stack_iface == nullptr) { - LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) - << ", IBluetoothAudioPort Invalid"; - } else if (!UpdateAudioConfig(audio_config)) { - LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) - << ", AudioConfiguration=" << toString(audio_config) - << " Invalid"; - } else if (!UpdateDataPath(dataMQ)) { - LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) - << " DataMQ Invalid"; - audio_config_ = - (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH - ? kInvalidOffloadAudioConfiguration - : kInvalidSoftwareAudioConfiguration); - } else { - stack_iface_ = stack_iface; - LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) - << ", AudioConfiguration=" << toString(audio_config); - ReportSessionStatus(); - } -} - -// The report function is used to report that the Bluetooth stack has ended the -// session, and will invoke session_changed_cb_ to notify registered -// bluetooth_audio outputs -void BluetoothAudioSession::OnSessionEnded() { - std::lock_guard guard(mutex_); - bool toggled = IsSessionReady(); - LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); - audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH - ? kInvalidOffloadAudioConfiguration - : kInvalidSoftwareAudioConfiguration); - stack_iface_ = nullptr; - UpdateDataPath(nullptr); - if (toggled) { - ReportSessionStatus(); - } -} - -// invoking the registered session_changed_cb_ -void BluetoothAudioSession::ReportSessionStatus() { - // This is locked already by OnSessionStarted / OnSessionEnded - if (observers_.empty()) { - LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO port state observer"; - return; - } - for (auto& observer : observers_) { - uint16_t cookie = observer.first; - std::shared_ptr cb = observer.second; - LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) - << " 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::ReportControlStatus( - bool start_resp, const BluetoothAudioStatus& status) { - std::lock_guard guard(mutex_); - if (observers_.empty()) { - LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO port state observer"; - return; - } - for (auto& observer : observers_) { - uint16_t cookie = observer.first; - std::shared_ptr cb = observer.second; - LOG(INFO) << __func__ << " - status=" << toString(status) - << " for SessionType=" << toString(session_type_) - << ", bluetooth_audio=0x" - << android::base::StringPrintf("%04x", cookie) - << (start_resp ? " started" : " suspended"); - cb->control_result_cb_(cookie, start_resp, status); - } -} - -// The function helps to check if this session is ready or not -// @return: true if the Bluetooth stack has started the specified session -bool BluetoothAudioSession::IsSessionReady() { - std::lock_guard guard(mutex_); - bool dataMQ_valid = - (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH || - (mDataMQ != nullptr && mDataMQ->isValid())); - return stack_iface_ != nullptr && dataMQ_valid; -} - -bool BluetoothAudioSession::UpdateDataPath(const DataMQ::Descriptor* dataMQ) { - if (dataMQ == nullptr) { - // usecase of reset by nullptr - mDataMQ = nullptr; - return true; - } - std::unique_ptr tempDataMQ; - tempDataMQ.reset(new DataMQ(*dataMQ)); - if (!tempDataMQ || !tempDataMQ->isValid()) { - mDataMQ = nullptr; - return false; - } - mDataMQ = std::move(tempDataMQ); - return true; -} - -bool BluetoothAudioSession::UpdateAudioConfig( - const AudioConfiguration& audio_config) { - bool is_software_session = - (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH); - bool is_offload_session = - (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); - auto audio_config_discriminator = audio_config.getDiscriminator(); - bool is_software_audio_config = - (is_software_session && - audio_config_discriminator == - AudioConfiguration::hidl_discriminator::pcmConfig); - bool is_offload_audio_config = - (is_offload_session && - audio_config_discriminator == - AudioConfiguration::hidl_discriminator::codecConfig); - if (!is_software_audio_config && !is_offload_audio_config) { - return false; - } - audio_config_ = audio_config; - return true; -} - -// The control function helps the bluetooth_audio module to register -// PortStatusCallbacks -// @return: cookie - the assigned number to this bluetooth_audio output -uint16_t BluetoothAudioSession::RegisterStatusCback( - const PortStatusCallbacks& cbacks) { - std::lock_guard guard(mutex_); - uint16_t cookie = ObserversCookieGetInitValue(session_type_); - uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_); - - 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_) - << " has " << observers_.size() - << " observers already (No Resource)"; - return kObserversCookieUndefined; - } - std::shared_ptr cb = - std::make_shared(); - *cb = cbacks; - observers_[cookie] = cb; - return cookie; -} - -// The control function helps the bluetooth_audio module to unregister -// PortStatusCallbacks -// @param: cookie - indicates which bluetooth_audio output is -void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) { - std::lock_guard guard(mutex_); - if (observers_.erase(cookie) != 1) { - LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) - << " no such provider=0x" - << android::base::StringPrintf("%04x", cookie); - } -} - -// The control function is for the bluetooth_audio module to get the current -// AudioConfiguration -const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() { - std::lock_guard guard(mutex_); - if (IsSessionReady()) { - return audio_config_; - } else if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { - return kInvalidOffloadAudioConfiguration; - } else { - return kInvalidSoftwareAudioConfiguration; - } -} - -// Those control functions are for the bluetooth_audio module to start, suspend, -// stop stream, to check position, and to update metadata. -bool BluetoothAudioSession::StartStream() { - std::lock_guard guard(mutex_); - if (!IsSessionReady()) { - LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO session"; - return false; - } - auto hal_retval = stack_iface_->startStream(); - if (!hal_retval.isOk()) { - LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" - << toString(session_type_) << " failed"; - return false; - } - return true; -} - -bool BluetoothAudioSession::SuspendStream() { - std::lock_guard guard(mutex_); - if (!IsSessionReady()) { - LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO session"; - return false; - } - auto hal_retval = stack_iface_->suspendStream(); - if (!hal_retval.isOk()) { - LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" - << toString(session_type_) << " failed"; - return false; - } - return true; -} - -void BluetoothAudioSession::StopStream() { - std::lock_guard guard(mutex_); - if (!IsSessionReady()) { - return; - } - auto hal_retval = stack_iface_->stopStream(); - if (!hal_retval.isOk()) { - LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" - << toString(session_type_) << " failed"; - } -} - -bool BluetoothAudioSession::GetPresentationPosition( - uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed, - timespec* data_position) { - std::lock_guard guard(mutex_); - if (!IsSessionReady()) { - LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO session"; - return false; - } - bool retval = false; - auto hal_retval = stack_iface_->getPresentationPosition( - [&retval, &remote_delay_report_ns, &total_bytes_readed, &data_position]( - BluetoothAudioStatus status, - const uint64_t& remoteDeviceAudioDelayNanos, - uint64_t transmittedOctets, - const TimeSpec& transmittedOctetsTimeStamp) { - if (status == BluetoothAudioStatus::SUCCESS) { - if (remote_delay_report_ns) - *remote_delay_report_ns = remoteDeviceAudioDelayNanos; - if (total_bytes_readed) *total_bytes_readed = transmittedOctets; - if (data_position) - *data_position = - timespec_convert_from_hal(transmittedOctetsTimeStamp); - retval = true; - } - }); - if (!hal_retval.isOk()) { - LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" - << toString(session_type_) << " failed"; - return false; - } - return retval; -} - -void BluetoothAudioSession::UpdateTracksMetadata( - const struct source_metadata* source_metadata) { - std::lock_guard guard(mutex_); - if (!IsSessionReady()) { - LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) - << " has NO session"; - return; - } - - ssize_t track_count = source_metadata->track_count; - LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", " - << track_count << " track(s)"; - if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { - return; - } - - struct playback_track_metadata* track = source_metadata->tracks; - SourceMetadata sourceMetadata; - PlaybackTrackMetadata* halMetadata; - - sourceMetadata.tracks.resize(track_count); - halMetadata = sourceMetadata.tracks.data(); - while (track_count && track) { - halMetadata->usage = static_cast(track->usage); - halMetadata->contentType = - static_cast(track->content_type); - halMetadata->gain = track->gain; - LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_) - << ", usage=" << toString(halMetadata->usage) - << ", content=" << toString(halMetadata->contentType) - << ", gain=" << halMetadata->gain; - --track_count; - ++track; - ++halMetadata; - } - auto hal_retval = stack_iface_->updateMetadata(sourceMetadata); - if (!hal_retval.isOk()) { - LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" - << toString(session_type_) << " failed"; - } -} - -// The control function writes stream to FMQ -size_t BluetoothAudioSession::OutWritePcmData(const void* buffer, - size_t bytes) { - if (buffer == nullptr || !bytes) return 0; - size_t totalWritten = 0; - int ms_timeout = kFmqSendTimeoutMs; - do { - std::unique_lock lock(mutex_); - if (!IsSessionReady()) break; - size_t availableToWrite = mDataMQ->availableToWrite(); - if (availableToWrite) { - if (availableToWrite > (bytes - totalWritten)) { - availableToWrite = bytes - totalWritten; - } - - if (!mDataMQ->write(static_cast(buffer) + totalWritten, - availableToWrite)) { - ALOGE("FMQ datapath writing %zu/%zu failed", totalWritten, bytes); - return totalWritten; - } - totalWritten += availableToWrite; - } else if (ms_timeout >= kWritePollMs) { - lock.unlock(); - usleep(kWritePollMs * 1000); - ms_timeout -= kWritePollMs; - } else { - ALOGD("out data %zu/%zu overflow %d ms", totalWritten, bytes, - (kFmqSendTimeoutMs - ms_timeout)); - return totalWritten; - } - } while (totalWritten < bytes); - return totalWritten; -} - -// The control function reads stream from FMQ -size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) { - if (buffer == nullptr || !bytes) return 0; - size_t totalRead = 0; - int ms_timeout = kFmqReceiveTimeoutMs; - do { - std::unique_lock lock(mutex_); - if (!IsSessionReady()) break; - size_t availableToRead = mDataMQ->availableToRead(); - if (availableToRead) { - if (availableToRead > (bytes - totalRead)) { - availableToRead = bytes - totalRead; - } - if (!mDataMQ->read(static_cast(buffer) + totalRead, - availableToRead)) { - ALOGE("FMQ datapath reading %zu/%zu failed", totalRead, bytes); - return totalRead; - } - totalRead += availableToRead; - } else if (ms_timeout >= kReadPollMs) { - lock.unlock(); - usleep(kReadPollMs * 1000); - ms_timeout -= kReadPollMs; - continue; - } else { - ALOGD("in data %zu/%zu overflow %d ms", totalRead, bytes, - (kFmqReceiveTimeoutMs - ms_timeout)); - return totalRead; - } - } while (totalRead < bytes); - return totalRead; -} - -std::unique_ptr - BluetoothAudioSessionInstance::instance_ptr = - std::unique_ptr( - new BluetoothAudioSessionInstance()); - -// API to fetch the session -std::shared_ptr -BluetoothAudioSessionInstance::GetSessionInstance( - const SessionType& session_type) { - std::lock_guard guard(instance_ptr->mutex_); - if (!instance_ptr->sessions_map_.empty()) { - auto entry = instance_ptr->sessions_map_.find(session_type); - if (entry != instance_ptr->sessions_map_.end()) { - return entry->second; - } - } - std::shared_ptr session_ptr = - std::make_shared(session_type); - instance_ptr->sessions_map_[session_type] = session_ptr; - return session_ptr; -} - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h deleted file mode 100644 index 7bc12e6337..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSession.h +++ /dev/null @@ -1,190 +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. - */ - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -namespace android { -namespace bluetooth { -namespace audio { - -using ::android::sp; -using ::android::hardware::kSynchronizedReadWrite; -using ::android::hardware::MessageQueue; -using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; -using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; -using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; -using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort; -using ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration; -using ::android::hardware::bluetooth::audio::V2_1::PcmParameters; -using ::android::hardware::bluetooth::audio::V2_1::SampleRate; -using ::android::hardware::bluetooth::audio::V2_1::SessionType; - -using BluetoothAudioStatus = - ::android::hardware::bluetooth::audio::V2_0::Status; - -using DataMQ = MessageQueue; - -static constexpr uint16_t kObserversCookieSize = 0x0010; // 0x0000 ~ 0x000f -constexpr uint16_t kObserversCookieUndefined = - (static_cast(SessionType::UNKNOWN) << 8 & 0xff00); -inline SessionType ObserversCookieGetSessionType(uint16_t cookie) { - return static_cast(cookie >> 8 & 0x00ff); -} -inline uint16_t ObserversCookieGetInitValue(SessionType session_type) { - return (static_cast(session_type) << 8 & 0xff00); -} -inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) { - return (static_cast(session_type) << 8 & 0xff00) + - kObserversCookieSize; -} - -// This presents the callbacks of started / suspended and session changed, -// and the bluetooth_audio module uses to receive the status notification -struct PortStatusCallbacks { - // 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 - 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 session_changed_cb_; -}; - -class BluetoothAudioSession { - private: - // using recursive_mutex to allow hwbinder to re-enter again. - std::recursive_mutex mutex_; - SessionType session_type_; - - // audio control path to use for both software and offloading - sp stack_iface_; - // Audio path (FMQ) for software encoding/decoded data - std::unique_ptr mDataMQ; - // audio data configuration for both software and offloading - AudioConfiguration audio_config_; - - static AudioConfiguration invalidSoftwareAudioConfiguration; - static AudioConfiguration invalidOffloadAudioConfiguration; - - // saving those registered bluetooth_audio's callbacks - std::unordered_map> - observers_; - - bool UpdateDataPath(const DataMQ::Descriptor* dataMQ); - bool UpdateAudioConfig(const AudioConfiguration& audio_config); - // invoking the registered session_changed_cb_ - void ReportSessionStatus(); - - public: - BluetoothAudioSession(const SessionType& session_type); - - // The function helps to check if this session is ready or not - // @return: true if the Bluetooth stack has started the specified session - bool IsSessionReady(); - - // The report function is used to report that the Bluetooth stack has started - // this session without any failure, and will invoke session_changed_cb_ to - // notify those registered bluetooth_audio outputs - void OnSessionStarted(const sp stack_iface, - const DataMQ::Descriptor* dataMQ, - const AudioConfiguration& audio_config); - - // The report function is used to report that the Bluetooth stack has ended - // the session, and will invoke session_changed_cb_ to notify registered - // bluetooth_audio outputs - void OnSessionEnded(); - - // 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 control function helps the bluetooth_audio module to register - // PortStatusCallbacks - // @return: cookie - the assigned number to this bluetooth_audio output - uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks); - - // The control function helps the bluetooth_audio module to unregister - // PortStatusCallbacks - // @param: cookie - indicates which bluetooth_audio output is - void UnregisterStatusCback(uint16_t cookie); - - // The control function is for the bluetooth_audio module to get the current - // AudioConfiguration - const AudioConfiguration& GetAudioConfig(); - - // Those control functions are for the bluetooth_audio module to start, - // suspend, stop stream, to check position, and to update metadata. - bool StartStream(); - bool SuspendStream(); - void StopStream(); - bool GetPresentationPosition(uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_readed, - timespec* data_position); - void UpdateTracksMetadata(const struct source_metadata* source_metadata); - - // The control function writes stream to FMQ - size_t OutWritePcmData(const void* buffer, size_t bytes); - // The control function read stream from FMQ - size_t InReadPcmData(void* buffer, size_t bytes); - - static constexpr PcmParameters kInvalidPcmParameters = { - .sampleRate = SampleRate::RATE_UNKNOWN, - .channelMode = ChannelMode::UNKNOWN, - .bitsPerSample = BitsPerSample::BITS_UNKNOWN, - .dataIntervalUs = 0, - }; - // can't be constexpr because of non-literal type - static const CodecConfiguration kInvalidCodecConfiguration; - - static constexpr AudioConfiguration& kInvalidSoftwareAudioConfiguration = - invalidSoftwareAudioConfiguration; - static constexpr AudioConfiguration& kInvalidOffloadAudioConfiguration = - invalidOffloadAudioConfiguration; -}; - -class BluetoothAudioSessionInstance { - public: - // The API is to fetch the specified session - static std::shared_ptr GetSessionInstance( - const SessionType& session_type); - - private: - static std::unique_ptr instance_ptr; - std::mutex mutex_; - std::unordered_map> - sessions_map_; -}; - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h deleted file mode 100644 index 017a6115cb..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionControl.h +++ /dev/null @@ -1,154 +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. - */ - -#pragma once - -#include "BluetoothAudioSession.h" - -namespace android { -namespace bluetooth { -namespace audio { - -class BluetoothAudioSessionControl { - public: - // The control API helps to check if session is ready or not - // @return: true if the Bluetooth stack has started th specified session - static bool IsSessionReady(const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->IsSessionReady(); - } - return false; - } - - // The control API helps the bluetooth_audio module to register - // PortStatusCallbacks - // @return: cookie - the assigned number to this bluetooth_audio output - static uint16_t RegisterControlResultCback( - const SessionType& session_type, const PortStatusCallbacks& cbacks) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::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 - // @param: cookie - indicates which bluetooth_audio output is - static void UnregisterControlResultCback(const SessionType& session_type, - uint16_t cookie) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->UnregisterStatusCback(cookie); - } - } - - // The control API for the bluetooth_audio module to get current - // AudioConfiguration - static const AudioConfiguration& GetAudioConfig( - const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->GetAudioConfig(); - } else if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { - return BluetoothAudioSession::kInvalidOffloadAudioConfiguration; - } else { - return BluetoothAudioSession::kInvalidSoftwareAudioConfiguration; - } - } - - // Those control APIs for the bluetooth_audio module to start / suspend / stop - // stream, to check position, and to update metadata. - static bool StartStream(const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->StartStream(); - } - return false; - } - - static bool SuspendStream(const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->SuspendStream(); - } - return false; - } - - static void StopStream(const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->StopStream(); - } - } - - static bool GetPresentationPosition(const SessionType& session_type, - uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_readed, - timespec* data_position) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->GetPresentationPosition( - remote_delay_report_ns, total_bytes_readed, data_position); - } - return false; - } - - static void UpdateTracksMetadata( - const SessionType& session_type, - const struct source_metadata* source_metadata) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->UpdateTracksMetadata(source_metadata); - } - } - - // The control API writes stream to FMQ - static size_t OutWritePcmData(const SessionType& session_type, - const void* buffer, size_t bytes) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->OutWritePcmData(buffer, bytes); - } - return 0; - } - - // The control API reads stream from FMQ - static size_t InReadPcmData(const SessionType& session_type, void* buffer, - size_t bytes) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - return session_ptr->InReadPcmData(buffer, bytes); - } - return 0; - } -}; - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h deleted file mode 100644 index 267bf8fa92..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSessionReport.h +++ /dev/null @@ -1,63 +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. - */ - -#pragma once - -#include "BluetoothAudioSession.h" - -namespace android { -namespace bluetooth { -namespace audio { - -class BluetoothAudioSessionReport { - public: - // The API reports the Bluetooth stack has started the session, and will - // inform registered bluetooth_audio session - static void OnSessionStarted(const SessionType& session_type, - const sp host_iface, - const DataMQ::Descriptor* dataMQ, - const AudioConfiguration& audio_config) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config); - } - } - // The API reports the Bluetooth stack has ended the session, and will - // inform registered bluetooth_audio outputs - static void OnSessionEnded(const SessionType& session_type) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->OnSessionEnded(); - } - } - // The API reports the Bluetooth stack has replied the result of startStream - // or suspendStream, and will inform registered bluetooth_audio outputs - static void ReportControlStatus(const SessionType& session_type, - const bool& start_resp, - const BluetoothAudioStatus& status) { - std::shared_ptr session_ptr = - BluetoothAudioSessionInstance::GetSessionInstance(session_type); - if (session_ptr != nullptr) { - session_ptr->ReportControlStatus(start_resp, status); - } - } -}; - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp deleted file mode 100644 index 0937f441e3..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.cpp +++ /dev/null @@ -1,489 +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. - */ - -#define LOG_TAG "BTAudioProviderSessionCodecsDB" - -#include "BluetoothAudioSupportedCodecsDB.h" - -#include - -namespace android { -namespace bluetooth { -namespace audio { - -using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; -using ::android::hardware::bluetooth::audio::V2_0::AacParameters; -using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; -using ::android::hardware::bluetooth::audio::V2_0::AptxParameters; -using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; -using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; -using ::android::hardware::bluetooth::audio::V2_0::CodecType; -using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; -using ::android::hardware::bluetooth::audio::V2_0::LdacParameters; -using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; -using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; -using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; -using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; -using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; -using ::android::hardware::bluetooth::audio::V2_0::SbcParameters; -using ::android::hardware::bluetooth::audio::V2_1::SampleRate; - -// Default Supported PCM Parameters -static const ::android::hardware::bluetooth::audio::V2_0::PcmParameters - kDefaultSoftwarePcmCapabilities = { - .sampleRate = static_cast< - android::hardware::bluetooth::audio::V2_0::SampleRate>( - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000), - .channelMode = - static_cast(ChannelMode::MONO | ChannelMode::STEREO), - .bitsPerSample = static_cast(BitsPerSample::BITS_16 | - BitsPerSample::BITS_24 | - BitsPerSample::BITS_32)}; - -static const PcmParameters kDefaultSoftwarePcmCapabilities_2_1 = { - .sampleRate = static_cast( - SampleRate::RATE_48000 | SampleRate::RATE_44100 | - SampleRate::RATE_32000 | SampleRate::RATE_24000 | - SampleRate::RATE_16000 | SampleRate::RATE_8000), - .channelMode = - static_cast(ChannelMode::MONO | ChannelMode::STEREO), - .bitsPerSample = static_cast(BitsPerSample::BITS_16)}; - -// Default Supported Codecs -// SBC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(MONO|STEREO) -// all blocks | subbands 8 | Loudness -static const SbcParameters kDefaultOffloadSbcCapability = { - .sampleRate = - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100, - .channelMode = static_cast(SbcChannelMode::MONO | - SbcChannelMode::JOINT_STEREO), - .blockLength = static_cast( - SbcBlockLength::BLOCKS_4 | SbcBlockLength::BLOCKS_8 | - SbcBlockLength::BLOCKS_12 | SbcBlockLength::BLOCKS_16), - .numSubbands = SbcNumSubbands::SUBBAND_8, - .allocMethod = SbcAllocMethod::ALLOC_MD_L, - .bitsPerSample = BitsPerSample::BITS_16, - .minBitpool = 2, - .maxBitpool = 53}; - -// AAC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(STEREO) -static const AacParameters kDefaultOffloadAacCapability = { - .objectType = AacObjectType::MPEG2_LC, - .sampleRate = - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100, - .channelMode = ChannelMode::STEREO, - .variableBitRateEnabled = AacVariableBitRate::ENABLED, - .bitsPerSample = BitsPerSample::BITS_16}; - -// LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32), -// mChannelMode:(DUAL|STEREO) -static const LdacParameters kDefaultOffloadLdacCapability = { - .sampleRate = - static_cast( - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000), - .channelMode = static_cast(LdacChannelMode::DUAL | - LdacChannelMode::STEREO), - .qualityIndex = LdacQualityIndex::QUALITY_HIGH, - .bitsPerSample = static_cast(BitsPerSample::BITS_16 | - BitsPerSample::BITS_24 | - BitsPerSample::BITS_32)}; - -// aptX: mSampleRate:(44100|48000), mBitsPerSample:(16), mChannelMode:(STEREO) -static const AptxParameters kDefaultOffloadAptxCapability = { - .sampleRate = - static_cast( - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000), - .channelMode = ChannelMode::STEREO, - .bitsPerSample = BitsPerSample::BITS_16, -}; - -// aptX HD: mSampleRate:(44100|48000), mBitsPerSample:(24), -// mChannelMode:(STEREO) -static const AptxParameters kDefaultOffloadAptxHdCapability = { - .sampleRate = - static_cast( - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 | - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000), - .channelMode = ChannelMode::STEREO, - .bitsPerSample = BitsPerSample::BITS_24, -}; - -const std::vector kDefaultOffloadA2dpCodecCapabilities = { - {.codecType = CodecType::SBC, .capabilities = {}}, - {.codecType = CodecType::AAC, .capabilities = {}}, - {.codecType = CodecType::LDAC, .capabilities = {}}, - {.codecType = CodecType::APTX, .capabilities = {}}, - {.codecType = CodecType::APTX_HD, .capabilities = {}}}; - -static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield) { - bool single = false; - uint32_t test_bit = 0x00000001; - while (test_bit <= bitmasks && test_bit <= bitfield) { - if (bitfield & test_bit && bitmasks & test_bit) { - if (single) return false; - single = true; - } - if (test_bit == 0x80000000) break; - test_bit <<= 1; - } - return single; -} - -static bool IsOffloadSbcConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific); -static bool IsOffloadAacConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific); -static bool IsOffloadLdacConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific); -static bool IsOffloadAptxConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific); -static bool IsOffloadAptxHdConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific); - -static bool IsOffloadSbcConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific) { - if (codec_specific.getDiscriminator() != - CodecConfiguration::CodecSpecific::hidl_discriminator::sbcConfig) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } - const SbcParameters sbc_data = codec_specific.sbcConfig(); - if (!IsSingleBit(static_cast(sbc_data.sampleRate), 0xff) || - !IsSingleBit(static_cast(sbc_data.channelMode), 0x0f) || - !IsSingleBit(static_cast(sbc_data.blockLength), 0xf0) || - !IsSingleBit(static_cast(sbc_data.numSubbands), 0x0c) || - !IsSingleBit(static_cast(sbc_data.allocMethod), 0x03) || - !IsSingleBit(static_cast(sbc_data.bitsPerSample), 0x07) || - sbc_data.minBitpool > sbc_data.maxBitpool) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } else if ((sbc_data.sampleRate & kDefaultOffloadSbcCapability.sampleRate) && - (sbc_data.channelMode & - kDefaultOffloadSbcCapability.channelMode) && - (sbc_data.blockLength & - kDefaultOffloadSbcCapability.blockLength) && - (sbc_data.numSubbands & - kDefaultOffloadSbcCapability.numSubbands) && - (sbc_data.allocMethod & - kDefaultOffloadSbcCapability.allocMethod) && - (sbc_data.bitsPerSample & - kDefaultOffloadSbcCapability.bitsPerSample) && - (kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool && - sbc_data.maxBitpool <= kDefaultOffloadSbcCapability.maxBitpool)) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported CodecSpecific=" << toString(codec_specific); - return false; -} - -static bool IsOffloadAacConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific) { - if (codec_specific.getDiscriminator() != - CodecConfiguration::CodecSpecific::hidl_discriminator::aacConfig) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } - const AacParameters aac_data = codec_specific.aacConfig(); - if (!IsSingleBit(static_cast(aac_data.objectType), 0xf0) || - !IsSingleBit(static_cast(aac_data.sampleRate), 0xff) || - !IsSingleBit(static_cast(aac_data.channelMode), 0x03) || - !IsSingleBit(static_cast(aac_data.bitsPerSample), 0x07)) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } else if ((aac_data.objectType & kDefaultOffloadAacCapability.objectType) && - (aac_data.sampleRate & kDefaultOffloadAacCapability.sampleRate) && - (aac_data.channelMode & - kDefaultOffloadAacCapability.channelMode) && - (aac_data.variableBitRateEnabled == AacVariableBitRate::DISABLED || - kDefaultOffloadAacCapability.variableBitRateEnabled == - AacVariableBitRate::ENABLED) && - (aac_data.bitsPerSample & - kDefaultOffloadAacCapability.bitsPerSample)) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported CodecSpecific=" << toString(codec_specific); - return false; -} - -static bool IsOffloadLdacConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific) { - if (codec_specific.getDiscriminator() != - CodecConfiguration::CodecSpecific::hidl_discriminator::ldacConfig) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } - const LdacParameters ldac_data = codec_specific.ldacConfig(); - if (!IsSingleBit(static_cast(ldac_data.sampleRate), 0xff) || - !IsSingleBit(static_cast(ldac_data.channelMode), 0x07) || - (ldac_data.qualityIndex > LdacQualityIndex::QUALITY_LOW && - ldac_data.qualityIndex != LdacQualityIndex::QUALITY_ABR) || - !IsSingleBit(static_cast(ldac_data.bitsPerSample), 0x07)) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } else if ((ldac_data.sampleRate & - kDefaultOffloadLdacCapability.sampleRate) && - (ldac_data.channelMode & - kDefaultOffloadLdacCapability.channelMode) && - (ldac_data.bitsPerSample & - kDefaultOffloadLdacCapability.bitsPerSample)) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported CodecSpecific=" << toString(codec_specific); - return false; -} - -static bool IsOffloadAptxConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific) { - if (codec_specific.getDiscriminator() != - CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } - const AptxParameters aptx_data = codec_specific.aptxConfig(); - if (!IsSingleBit(static_cast(aptx_data.sampleRate), 0xff) || - !IsSingleBit(static_cast(aptx_data.channelMode), 0x03) || - !IsSingleBit(static_cast(aptx_data.bitsPerSample), 0x07)) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } else if ((aptx_data.sampleRate & - kDefaultOffloadAptxCapability.sampleRate) && - (aptx_data.channelMode & - kDefaultOffloadAptxCapability.channelMode) && - (aptx_data.bitsPerSample & - kDefaultOffloadAptxCapability.bitsPerSample)) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported CodecSpecific=" << toString(codec_specific); - return false; -} - -static bool IsOffloadAptxHdConfigurationValid( - const CodecConfiguration::CodecSpecific& codec_specific) { - if (codec_specific.getDiscriminator() != - CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } - const AptxParameters aptx_data = codec_specific.aptxConfig(); - if (!IsSingleBit(static_cast(aptx_data.sampleRate), 0xff) || - !IsSingleBit(static_cast(aptx_data.channelMode), 0x03) || - !IsSingleBit(static_cast(aptx_data.bitsPerSample), 0x07)) { - LOG(WARNING) << __func__ - << ": Invalid CodecSpecific=" << toString(codec_specific); - return false; - } else if ((aptx_data.sampleRate & - kDefaultOffloadAptxHdCapability.sampleRate) && - (aptx_data.channelMode & - kDefaultOffloadAptxHdCapability.channelMode) && - (aptx_data.bitsPerSample & - kDefaultOffloadAptxHdCapability.bitsPerSample)) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported CodecSpecific=" << toString(codec_specific); - return false; -} - -std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters> -GetSoftwarePcmCapabilities() { - return std::vector< - ::android::hardware::bluetooth::audio::V2_0::PcmParameters>( - 1, kDefaultSoftwarePcmCapabilities); -} - -std::vector GetSoftwarePcmCapabilities_2_1() { - return std::vector(1, kDefaultSoftwarePcmCapabilities_2_1); -} - -std::vector GetOffloadCodecCapabilities( - const ::android::hardware::bluetooth::audio::V2_0::SessionType& - session_type) { - return GetOffloadCodecCapabilities(static_cast(session_type)); -} - -std::vector GetOffloadCodecCapabilities( - const SessionType& session_type) { - if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { - return std::vector(0); - } - std::vector offload_a2dp_codec_capabilities = - kDefaultOffloadA2dpCodecCapabilities; - for (auto& codec_capability : offload_a2dp_codec_capabilities) { - switch (codec_capability.codecType) { - case CodecType::SBC: - codec_capability.capabilities.sbcCapabilities( - kDefaultOffloadSbcCapability); - break; - case CodecType::AAC: - codec_capability.capabilities.aacCapabilities( - kDefaultOffloadAacCapability); - break; - case CodecType::LDAC: - codec_capability.capabilities.ldacCapabilities( - kDefaultOffloadLdacCapability); - break; - case CodecType::APTX: - codec_capability.capabilities.aptxCapabilities( - kDefaultOffloadAptxCapability); - break; - case CodecType::APTX_HD: - codec_capability.capabilities.aptxCapabilities( - kDefaultOffloadAptxHdCapability); - break; - case CodecType::UNKNOWN: - codec_capability = {}; - break; - } - } - return offload_a2dp_codec_capabilities; -} - -bool IsSoftwarePcmConfigurationValid( - const ::android::hardware::bluetooth::audio::V2_0::PcmParameters& - pcm_config) { - if ((pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 && - pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 && - pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 && - pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 && - pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000 && - pcm_config.sampleRate != - android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000) || - (pcm_config.bitsPerSample != BitsPerSample::BITS_16 && - pcm_config.bitsPerSample != BitsPerSample::BITS_24 && - pcm_config.bitsPerSample != BitsPerSample::BITS_32) || - (pcm_config.channelMode != ChannelMode::MONO && - pcm_config.channelMode != ChannelMode::STEREO)) { - LOG(WARNING) << __func__ - << ": Invalid PCM Configuration=" << toString(pcm_config); - return false; - } else if (pcm_config.sampleRate & - kDefaultSoftwarePcmCapabilities.sampleRate && - pcm_config.bitsPerSample & - kDefaultSoftwarePcmCapabilities.bitsPerSample && - pcm_config.channelMode & - kDefaultSoftwarePcmCapabilities.channelMode) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported PCM Configuration=" << toString(pcm_config); - return false; -} - -bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config) { - if ((pcm_config.sampleRate != SampleRate::RATE_96000 && - pcm_config.sampleRate != SampleRate::RATE_88200 && - pcm_config.sampleRate != SampleRate::RATE_48000 && - pcm_config.sampleRate != SampleRate::RATE_44100 && - pcm_config.sampleRate != SampleRate::RATE_32000 && - pcm_config.sampleRate != SampleRate::RATE_24000 && - pcm_config.sampleRate != SampleRate::RATE_16000 && - pcm_config.sampleRate != SampleRate::RATE_8000) || - (pcm_config.bitsPerSample != BitsPerSample::BITS_16 && - pcm_config.bitsPerSample != BitsPerSample::BITS_24 && - pcm_config.bitsPerSample != BitsPerSample::BITS_32) || - (pcm_config.channelMode != ChannelMode::MONO && - pcm_config.channelMode != ChannelMode::STEREO)) { - LOG(WARNING) << __func__ - << ": Invalid PCM Configuration=" << toString(pcm_config); - return false; - } else if (pcm_config.sampleRate & - kDefaultSoftwarePcmCapabilities_2_1.sampleRate && - pcm_config.bitsPerSample & - kDefaultSoftwarePcmCapabilities_2_1.bitsPerSample && - pcm_config.channelMode & - kDefaultSoftwarePcmCapabilities_2_1.channelMode && - pcm_config.dataIntervalUs != 0) { - return true; - } - LOG(WARNING) << __func__ - << ": Unsupported PCM Configuration=" << toString(pcm_config); - return false; -} - -bool IsOffloadCodecConfigurationValid(const SessionType& session_type, - const CodecConfiguration& codec_config) { - if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { - LOG(ERROR) << __func__ - << ": Invalid SessionType=" << toString(session_type); - return false; - } else if (codec_config.encodedAudioBitrate < 0x00000001 || - 0x00ffffff < codec_config.encodedAudioBitrate) { - LOG(ERROR) << __func__ << ": Unsupported Codec Configuration=" - << toString(codec_config); - return false; - } - const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config; - switch (codec_config.codecType) { - case CodecType::SBC: - if (IsOffloadSbcConfigurationValid(codec_specific)) { - return true; - } - return false; - case CodecType::AAC: - if (IsOffloadAacConfigurationValid(codec_specific)) { - return true; - } - return false; - case CodecType::LDAC: - if (IsOffloadLdacConfigurationValid(codec_specific)) { - return true; - } - return false; - case CodecType::APTX: - if (IsOffloadAptxConfigurationValid(codec_specific)) { - return true; - } - return false; - case CodecType::APTX_HD: - if (IsOffloadAptxHdConfigurationValid(codec_specific)) { - return true; - } - return false; - case CodecType::UNKNOWN: - return false; - } - return false; -} - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h b/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h deleted file mode 100644 index 9b2f68092f..0000000000 --- a/bluetooth/audio/2.1/default/session/BluetoothAudioSupportedCodecsDB.h +++ /dev/null @@ -1,49 +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. - */ - -#pragma once - -#include -#include - -namespace android { -namespace bluetooth { -namespace audio { - -using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities; -using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; -using ::android::hardware::bluetooth::audio::V2_1::PcmParameters; -using ::android::hardware::bluetooth::audio::V2_1::SessionType; - -std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters> -GetSoftwarePcmCapabilities(); -std::vector GetSoftwarePcmCapabilities_2_1(); -std::vector GetOffloadCodecCapabilities( - const SessionType& session_type); -std::vector GetOffloadCodecCapabilities( - const ::android::hardware::bluetooth::audio::V2_0::SessionType& - session_type); - -bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config); -bool IsSoftwarePcmConfigurationValid( - const ::android::hardware::bluetooth::audio::V2_0::PcmParameters& - pcm_config); -bool IsOffloadCodecConfigurationValid(const SessionType& session_type, - const CodecConfiguration& codec_config); - -} // namespace audio -} // namespace bluetooth -} // namespace android diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp index add822e019..35476d285f 100644 --- a/bluetooth/audio/utils/Android.bp +++ b/bluetooth/audio/utils/Android.bp @@ -4,12 +4,15 @@ cc_library_shared { vendor: true, srcs: [ "session/BluetoothAudioSession.cpp", + "session/BluetoothAudioSession_2_1.cpp", "session/BluetoothAudioSupportedCodecsDB.cpp", + "session/BluetoothAudioSupportedCodecsDB_2_1.cpp", ], export_include_dirs: ["session/"], header_libs: ["libhardware_headers"], shared_libs: [ "android.hardware.bluetooth.audio@2.0", + "android.hardware.bluetooth.audio@2.1", "libbase", "libcutils", "libfmq", diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h new file mode 100644 index 0000000000..86af4680a5 --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h @@ -0,0 +1,148 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#include "BluetoothAudioSession_2_1.h" + +namespace android { +namespace bluetooth { +namespace audio { + +class BluetoothAudioSessionControl_2_1 { + using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; + + public: + // The control API helps to check if session is ready or not + // @return: true if the Bluetooth stack has started th specified session + static bool IsSessionReady(const SessionType_2_1& session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->IsSessionReady(); + } + return false; + } + + // The control API helps the bluetooth_audio module to register + // PortStatusCallbacks + // @return: cookie - the assigned number to this bluetooth_audio output + static uint16_t RegisterControlResultCback( + const SessionType_2_1& session_type, const PortStatusCallbacks& cbacks) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->RegisterStatusCback(cbacks); + } + return kObserversCookieUndefined; + } + + // The control API helps the bluetooth_audio module to unregister + // PortStatusCallbacks + // @param: cookie - indicates which bluetooth_audio output is + static void UnregisterControlResultCback(const SessionType_2_1& session_type, + uint16_t cookie) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->GetAudioSession()->UnregisterStatusCback(cookie); + } + } + + // The control API for the bluetooth_audio module to get current + // AudioConfiguration + static const AudioConfiguration& GetAudioConfig( + const SessionType_2_1& session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + // TODO: map 2.1 to 2.0 audio config inside GetAudioConfig? + return session_ptr->GetAudioSession()->GetAudioConfig(); + } else if (session_type == + SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) { + return BluetoothAudioSession::kInvalidOffloadAudioConfiguration; + } else { + return BluetoothAudioSession::kInvalidSoftwareAudioConfiguration; + } + } + + // Those control APIs for the bluetooth_audio module to start / suspend / stop + // stream, to check position, and to update metadata. + static bool StartStream(const SessionType_2_1& session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->StartStream(); + } + return false; + } + + static bool SuspendStream(const SessionType_2_1& session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->SuspendStream(); + } + return false; + } + + static void StopStream(const SessionType_2_1& session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->GetAudioSession()->StopStream(); + } + } + + static bool GetPresentationPosition(const SessionType_2_1& session_type, + uint64_t* remote_delay_report_ns, + uint64_t* total_bytes_readed, + timespec* data_position) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->GetPresentationPosition( + remote_delay_report_ns, total_bytes_readed, data_position); + } + return false; + } + + static void UpdateTracksMetadata( + const SessionType_2_1& session_type, + const struct source_metadata* source_metadata) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->GetAudioSession()->UpdateTracksMetadata(source_metadata); + } + } + + // The control API writes stream to FMQ + static size_t OutWritePcmData(const SessionType_2_1& session_type, + const void* buffer, size_t bytes) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioSession()->OutWritePcmData(buffer, bytes); + } + return 0; + } +}; + +} // namespace audio +} // namespace bluetooth +} // namespace android diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_1.h new file mode 100644 index 0000000000..ab30536d0a --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_1.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#include "BluetoothAudioSession_2_1.h" + +namespace android { +namespace bluetooth { +namespace audio { + +class BluetoothAudioSessionReport_2_1 { + public: + // The API reports the Bluetooth stack has started the session, and will + // inform registered bluetooth_audio outputs + static void OnSessionStarted( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type, + const sp host_iface, + const DataMQ::Descriptor* dataMQ, + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + audio_config) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config); + } + } + // The API reports the Bluetooth stack has ended the session, and will + // inform registered bluetooth_audio outputs + static void OnSessionEnded( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->GetAudioSession()->OnSessionEnded(); + } + } + // The API reports the Bluetooth stack has replied the result of startStream + // or suspendStream, and will inform registered bluetooth_audio outputs + static void ReportControlStatus( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type, + const bool& start_resp, const BluetoothAudioStatus& status) { + std::shared_ptr session_ptr = + BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->GetAudioSession()->ReportControlStatus(start_resp, status); + } + } +}; + +} // namespace audio +} // namespace bluetooth +} // namespace android diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp new file mode 100644 index 0000000000..9e1baf4f6e --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 2018 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. + */ + +#define LOG_TAG "BTAudioProviderSession_2_1" + +#include "BluetoothAudioSession_2_1.h" + +#include +#include + +namespace android { +namespace bluetooth { +namespace audio { +using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; +using SessionType_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SessionType; + +namespace { +bool is_2_0_session_type( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type) { + if (session_type == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH || + session_type == SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH) { + return true; + } else { + return false; + } +} +} // namespace + +BluetoothAudioSession_2_1::BluetoothAudioSession_2_1( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type) + : audio_session(BluetoothAudioSessionInstance::GetSessionInstance( + static_cast(session_type))) { + if (is_2_0_session_type(session_type)) { + session_type_2_1_ = (SessionType_2_1::UNKNOWN); + } else { + session_type_2_1_ = (session_type); + } +} + +std::shared_ptr +BluetoothAudioSession_2_1::GetAudioSession() { + return audio_session; +} + +// The report function is used to report that the Bluetooth stack has started +// this session without any failure, and will invoke session_changed_cb_ to +// notify those registered bluetooth_audio outputs +void BluetoothAudioSession_2_1::OnSessionStarted( + const sp stack_iface, const DataMQ::Descriptor* dataMQ, + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + audio_config) { + if (session_type_2_1_ == SessionType_2_1::UNKNOWN) { + ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration config; + if (audio_config.getDiscriminator() == + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration:: + hidl_discriminator::codecConfig) { + config.codecConfig(audio_config.codecConfig()); + } else { + auto& tmpPcm = audio_config.pcmConfig(); + config.pcmConfig( + ::android::hardware::bluetooth::audio::V2_0::PcmParameters{ + .sampleRate = static_cast(tmpPcm.sampleRate), + .channelMode = tmpPcm.channelMode, + .bitsPerSample = tmpPcm.bitsPerSample + /*dataIntervalUs is not passed to 2.0 */ + }); + } + + audio_session->OnSessionStarted(stack_iface, dataMQ, config); + } else { + LOG(FATAL) << " Not implemented yet!!"; + } +} + +std::unique_ptr + BluetoothAudioSessionInstance_2_1::instance_ptr = + std::unique_ptr( + new BluetoothAudioSessionInstance_2_1()); + +// API to fetch the session of A2DP / Hearing Aid +std::shared_ptr +BluetoothAudioSessionInstance_2_1::GetSessionInstance( + const SessionType_2_1& session_type) { + std::lock_guard guard(instance_ptr->mutex_); + if (!instance_ptr->sessions_map_.empty()) { + auto entry = instance_ptr->sessions_map_.find(session_type); + if (entry != instance_ptr->sessions_map_.end()) { + return entry->second; + } + } + std::shared_ptr session_ptr = + std::make_shared(session_type); + instance_ptr->sessions_map_[session_type] = session_ptr; + return session_ptr; +} + +} // namespace audio +} // namespace bluetooth +} // namespace android diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h new file mode 100644 index 0000000000..0e9c12b849 --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h @@ -0,0 +1,82 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#include +#include "BluetoothAudioSession.h" + +#include +#include + +namespace android { +namespace bluetooth { +namespace audio { + +class BluetoothAudioSession_2_1 { + private: + std::shared_ptr audio_session; + + ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_; + + // audio data configuration for both software and offloading + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration + audio_config_2_1_; + + bool UpdateAudioConfig( + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + audio_config); + + public: + BluetoothAudioSession_2_1( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type); + + std::shared_ptr GetAudioSession(); + + // The report function is used to report that the Bluetooth stack has started + // this session without any failure, and will invoke session_changed_cb_ to + // notify those registered bluetooth_audio outputs + void OnSessionStarted( + const sp stack_iface, + const DataMQ::Descriptor* dataMQ, + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + audio_config); + + // The control function is for the bluetooth_audio module to get the current + // AudioConfiguration + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + GetAudioConfig(); +}; + +class BluetoothAudioSessionInstance_2_1 { + public: + // The API is to fetch the specified session of A2DP / Hearing Aid + static std::shared_ptr GetSessionInstance( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type); + + private: + static std::unique_ptr instance_ptr; + std::mutex mutex_; + std::unordered_map<::android::hardware::bluetooth::audio::V2_1::SessionType, + std::shared_ptr> + sessions_map_; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace android diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp new file mode 100644 index 0000000000..8b0b0f743a --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2018 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. + */ + +#define LOG_TAG "BTAudioProviderSessionCodecsDB_2_1" + +#include "BluetoothAudioSupportedCodecsDB_2_1.h" + +#include + +namespace android { +namespace bluetooth { +namespace audio { + +using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; +using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; + +using SampleRate_2_0 = ::android::hardware::bluetooth::audio::V2_0::SampleRate; +using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate; + +using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; +using SessionType_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SessionType; + +namespace { +bool is_2_0_session_type( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type) { + if (session_type == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH || + session_type == SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH) { + return true; + } else { + return false; + } +} +} // namespace + +static const ::android::hardware::bluetooth::audio::V2_1::PcmParameters + kDefaultSoftwarePcmCapabilities_2_1 = { + .sampleRate = static_cast( + SampleRate_2_1::RATE_44100 | SampleRate_2_1::RATE_48000 | + SampleRate_2_1::RATE_88200 | SampleRate_2_1::RATE_96000 | + SampleRate_2_1::RATE_16000 | SampleRate_2_1::RATE_24000), + .channelMode = + static_cast(ChannelMode::MONO | ChannelMode::STEREO), + .bitsPerSample = static_cast(BitsPerSample::BITS_16 | + BitsPerSample::BITS_24 | + BitsPerSample::BITS_32)}; + +std::vector<::android::hardware::bluetooth::audio::V2_1::PcmParameters> +GetSoftwarePcmCapabilities_2_1() { + return std::vector< + ::android::hardware::bluetooth::audio::V2_1::PcmParameters>( + 1, kDefaultSoftwarePcmCapabilities_2_1); +} + +std::vector GetOffloadCodecCapabilities( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type) { + if (is_2_0_session_type(session_type)) { + return GetOffloadCodecCapabilities( + static_cast(session_type)); + } + return std::vector(0); +} + +bool IsSoftwarePcmConfigurationValid_2_1( + const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& + pcm_config) { + if ((pcm_config.sampleRate != SampleRate_2_1::RATE_44100 && + pcm_config.sampleRate != SampleRate_2_1::RATE_48000 && + pcm_config.sampleRate != SampleRate_2_1::RATE_88200 && + pcm_config.sampleRate != SampleRate_2_1::RATE_96000 && + pcm_config.sampleRate != SampleRate_2_1::RATE_16000 && + pcm_config.sampleRate != SampleRate_2_1::RATE_24000) || + (pcm_config.bitsPerSample != BitsPerSample::BITS_16 && + pcm_config.bitsPerSample != BitsPerSample::BITS_24 && + pcm_config.bitsPerSample != BitsPerSample::BITS_32) || + (pcm_config.channelMode != ChannelMode::MONO && + pcm_config.channelMode != ChannelMode::STEREO)) { + LOG(WARNING) << __func__ + << ": Invalid PCM Configuration=" << toString(pcm_config); + return false; + } else if (pcm_config.sampleRate & + kDefaultSoftwarePcmCapabilities_2_1.sampleRate && + pcm_config.bitsPerSample & + kDefaultSoftwarePcmCapabilities_2_1.bitsPerSample && + pcm_config.channelMode & + kDefaultSoftwarePcmCapabilities_2_1.channelMode && + pcm_config.dataIntervalUs != 0) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported PCM Configuration=" << toString(pcm_config); + return false; +} + +bool IsOffloadCodecConfigurationValid( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type, + const ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration& + codec_config) { + if (is_2_0_session_type(session_type)) { + return IsOffloadCodecConfigurationValid( + static_cast(session_type), codec_config); + } + + return false; +} + +} // namespace audio +} // namespace bluetooth +} // namespace android diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h new file mode 100644 index 0000000000..746d9c05ed --- /dev/null +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#pragma once + +#include "BluetoothAudioSupportedCodecsDB.h" + +#include + +namespace android { +namespace bluetooth { +namespace audio { + +std::vector<::android::hardware::bluetooth::audio::V2_1::PcmParameters> +GetSoftwarePcmCapabilities_2_1(); +std::vector<::android::hardware::bluetooth::audio::V2_0::CodecCapabilities> +GetOffloadCodecCapabilities( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type); + +bool IsSoftwarePcmConfigurationValid_2_1( + const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& + pcm_config); + +bool IsOffloadCodecConfigurationValid( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type, + const ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration& + codec_config); + +} // namespace audio +} // namespace bluetooth +} // namespace android