header_libs: ["libhardware_headers"],
shared_libs: [
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libaudioutils",
"libbase",
"libbluetooth_audio_session",
#include <log/log.h>
#include <stdlib.h>
-#include "BluetoothAudioSessionControl.h"
+#include "BluetoothAudioSessionControl_2_1.h"
#include "device_port_proxy.h"
#include "stream_apis.h"
#include "utils.h"
namespace audio {
using ::android::base::StringPrintf;
-using ::android::bluetooth::audio::BluetoothAudioSessionControl;
+using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1;
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
BluetoothAudioPortOut::BluetoothAudioPortOut()
: state_(BluetoothStreamState::DISABLED),
- session_type_(SessionType::UNKNOWN),
+ session_type_(SessionType_2_1::UNKNOWN),
cookie_(android::bluetooth::audio::kObserversCookieUndefined) {}
bool BluetoothAudioPortOut::SetUp(audio_devices_t devices) {
::android::bluetooth::audio::PortStatusCallbacks cbacks = {
.control_result_cb_ = control_result_cb,
.session_changed_cb_ = session_changed_cb};
- cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
+ cookie_ = BluetoothAudioSessionControl_2_1::RegisterControlResultCback(
session_type_, cbacks);
LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
<< StringPrintf("%#x", device) << ")";
- session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+ session_type_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
break;
case AUDIO_DEVICE_OUT_HEARING_AID:
LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device)
<< ")";
- session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+ session_type_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
break;
default:
LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
return false;
}
- if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
+ if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_)) {
LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_)
<< " is not ready";
return false;
}
LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
- BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
- cookie_);
+ BluetoothAudioSessionControl_2_1::UnregisterControlResultCback(session_type_,
+ cookie_);
cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
}
}
const AudioConfiguration& hal_audio_cfg =
- BluetoothAudioSessionControl::GetAudioConfig(session_type_);
+ BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_);
if (hal_audio_cfg.getDiscriminator() !=
AudioConfiguration::hidl_discriminator::pcmConfig) {
audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
bool retval = false;
if (state_ == BluetoothStreamState::STANDBY) {
state_ = BluetoothStreamState::STARTING;
- if (BluetoothAudioSessionControl::StartStream(session_type_)) {
+ if (BluetoothAudioSessionControl_2_1::StartStream(session_type_)) {
retval = CondwaitState(BluetoothStreamState::STARTING);
} else {
LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
bool retval = false;
if (state_ == BluetoothStreamState::STARTED) {
state_ = BluetoothStreamState::SUSPENDING;
- if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
+ if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_)) {
retval = CondwaitState(BluetoothStreamState::SUSPENDING);
} else {
LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
<< ", state=" << state_ << " request";
state_ = BluetoothStreamState::DISABLED;
- BluetoothAudioSessionControl::StopStream(session_type_);
+ BluetoothAudioSessionControl_2_1::StopStream(session_type_);
LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
<< ", state=" << state_ << " done";
}
size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const {
if (!in_use()) return 0;
if (!is_stereo_to_mono_) {
- return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
+ return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_,
+ buffer, bytes);
}
// WAR to mix the stereo into Mono (16 bits per sample)
std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
// a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
- return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) * 2;
+ return BluetoothAudioSessionControl_2_1::OutWritePcmData(
+ session_type_, dst.get(), write_frames * 2) *
+ 2;
}
bool BluetoothAudioPortOut::GetPresentationPosition(uint64_t* delay_ns,
LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
return false;
}
- bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
+ bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition(
session_type_, delay_ns, bytes, timestamp);
LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_)
<< ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns
LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
<< ", state=" << state_ << ", " << source_metadata->track_count << " track(s)";
if (source_metadata->track_count == 0) return;
- BluetoothAudioSessionControl::UpdateTracksMetadata(session_type_,
- source_metadata);
+ BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_,
+ source_metadata);
}
BluetoothStreamState BluetoothAudioPortOut::GetState() const { return state_; }
#pragma once
-#include <android/hardware/bluetooth/audio/2.0/types.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
#include <hardware/audio.h>
#include <condition_variable>
#include <mutex>
namespace bluetooth {
namespace audio {
-using ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using SessionType_2_1 =
+ ::android::hardware::bluetooth::audio::V2_1::SessionType;
// Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
// Session Control. All methods are not thread safe, so users must acquire a
void SetState(BluetoothStreamState state);
bool IsA2dp() const {
- return session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+ return session_type_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH;
}
private:
BluetoothStreamState state_;
- SessionType session_type_;
+ SessionType_2_1 session_type_;
uint16_t cookie_;
mutable std::mutex cv_mutex_;
std::condition_variable internal_cv_;
],
shared_libs: [
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libfmq",
"libhidlbase",
],
],
shared_libs: [
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libcutils",
"libfmq",
"libhidlbase",
#define LOG_TAG "BTAudioClientIf"
#include "client_interface.h"
+#include "hal_version_manager.h"
#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
-#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
#include <base/logging.h>
#include <hidl/MQDescriptor.h>
-#include <hidl/ServiceManagement.h>
#include <future>
#include "osi/include/log.h"
using ::android::hardware::Void;
using ::android::hardware::audio::common::V5_0::SourceMetadata;
using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
-using ::android::hardware::bluetooth::audio::V2_0::
- IBluetoothAudioProvidersFactory;
+
using DataMQ = ::android::hardware::MessageQueue<
uint8_t, ::android::hardware::kSynchronizedReadWrite>;
static constexpr int kDefaultDataReadTimeoutMs = 10; // 10 ms
static constexpr int kDefaultDataReadPollIntervalMs = 1; // non-blocking poll
-static constexpr char kFullyQualifiedInterfaceName[] =
- "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";
+
+std::unique_ptr<HalVersionManager> HalVersionManager::instance_ptr =
+ std::unique_ptr<HalVersionManager>(new HalVersionManager());
std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) {
switch (ack) {
bluetooth::common::MessageLoopThread* message_loop)
: sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
- if (IsSupported()) {
+ if (HalVersionManager::GetHalVersion() !=
+ BluetoothAudioHalVersion::VERSION_UNAVAILABLE) {
FetchAudioProvider();
} else {
LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
return capabilities_;
}
-bool BluetoothAudioClientInterface::IsSupported() {
- auto service_manager = android::hardware::defaultServiceManager1_2();
- CHECK(service_manager != nullptr);
- size_t instance_count = 0;
- auto listManifestByInterface_cb =
- [&instance_count](
- const hidl_vec<android::hardware::hidl_string>& instanceNames) {
- instance_count = instanceNames.size();
- LOG(INFO) << "listManifestByInterface_cb returns " << instance_count
- << " instance(s)";
- };
- auto hidl_retval = service_manager->listManifestByInterface(
- kFullyQualifiedInterfaceName, listManifestByInterface_cb);
- if (!hidl_retval.isOk()) {
- LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: "
- << hidl_retval.description();
- return false;
- }
- return (instance_count > 0);
-}
std::vector<AudioCapabilities>
BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) {
std::vector<AudioCapabilities> capabilities(0);
- if (!IsSupported()) return capabilities;
+ if (HalVersionManager::GetHalVersion() ==
+ BluetoothAudioHalVersion::VERSION_UNAVAILABLE) {
+ return capabilities;
+ }
- android::sp<IBluetoothAudioProvidersFactory> providersFactory =
- IBluetoothAudioProvidersFactory::getService();
- CHECK(providersFactory != nullptr)
- << "IBluetoothAudioProvidersFactory::getService() failed";
- LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
- << providersFactory.get()
- << (providersFactory->isRemote() ? " (remote)" : " (local)");
+ android::sp<IBluetoothAudioProvidersFactory_2_0> providersFactory =
+ HalVersionManager::GetProviderFactory_2_0();
auto getProviderCapabilities_cb =
[&capabilities](const hidl_vec<AudioCapabilities>& audioCapabilities) {
LOG(WARNING) << __func__ << ": reflash";
}
- android::sp<IBluetoothAudioProvidersFactory> providersFactory =
- IBluetoothAudioProvidersFactory::getService();
- CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed";
- LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
- << providersFactory.get()
- << (providersFactory->isRemote() ? " (remote)" : " (local)");
+ android::sp<IBluetoothAudioProvidersFactory_2_0> providersFactory =
+ HalVersionManager::GetProviderFactory_2_0();
auto getProviderCapabilities_cb =
[& capabilities = this->capabilities_](
#include <mutex>
#include <vector>
-#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
-#include <android/hardware/bluetooth/audio/2.0/types.h>
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
#include <fmq/MessageQueue.h>
#include <hardware/audio.h>
--- /dev/null
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h>
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <base/logging.h>
+#include <hidl/ServiceManagement.h>
+
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::hidl_vec;
+
+using IBluetoothAudioProvidersFactory_2_0 = ::android::hardware::bluetooth::
+ audio::V2_0::IBluetoothAudioProvidersFactory;
+using IBluetoothAudioProvidersFactory_2_1 = ::android::hardware::bluetooth::
+ audio::V2_1::IBluetoothAudioProvidersFactory;
+
+constexpr char kFullyQualifiedInterfaceName_2_0[] =
+ "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";
+constexpr char kFullyQualifiedInterfaceName_2_1[] =
+ "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory";
+
+enum class BluetoothAudioHalVersion : uint8_t {
+ VERSION_2_0 = 0,
+ VERSION_2_1,
+ VERSION_UNAVAILABLE,
+};
+
+class HalVersionManager {
+ public:
+ static BluetoothAudioHalVersion GetHalVersion() {
+ std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
+ if (instance_ptr->providersFactory_2_1) {
+ return BluetoothAudioHalVersion::VERSION_2_1;
+ } else if (instance_ptr->providersFactory) {
+ return BluetoothAudioHalVersion::VERSION_2_0;
+ }
+ return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
+ }
+
+ static android::sp<IBluetoothAudioProvidersFactory_2_1>
+ GetProviderFactory_2_1() {
+ std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
+ return instance_ptr->providersFactory_2_1;
+ }
+
+ static android::sp<IBluetoothAudioProvidersFactory_2_0>
+ GetProviderFactory_2_0() {
+ std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
+ if (instance_ptr->providersFactory_2_1)
+ return instance_ptr->providersFactory_2_1;
+
+ return instance_ptr->providersFactory;
+ }
+
+ HalVersionManager() {
+ auto service_manager = android::hardware::defaultServiceManager1_2();
+ CHECK(service_manager != nullptr);
+ size_t instance_count = 0;
+ auto listManifestByInterface_cb =
+ [&instance_count](
+ const hidl_vec<android::hardware::hidl_string>& instanceNames) {
+ instance_count = instanceNames.size();
+ };
+ auto hidl_retval = service_manager->listManifestByInterface(
+ kFullyQualifiedInterfaceName_2_1, listManifestByInterface_cb);
+ if (!hidl_retval.isOk()) {
+ LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: "
+ << hidl_retval.description();
+ return;
+ }
+
+ if (instance_count > 0) {
+ providersFactory_2_1 = IBluetoothAudioProvidersFactory_2_1::getService();
+ CHECK(providersFactory_2_1)
+ << "V2_1::IBluetoothAudioProvidersFactory::getService() failed";
+
+ LOG(INFO)
+ << "V2_1::IBluetoothAudioProvidersFactory::getService() returned "
+ << providersFactory_2_1.get()
+ << (providersFactory_2_1->isRemote() ? " (remote)" : " (local)");
+ return;
+ }
+
+ hidl_retval = service_manager->listManifestByInterface(
+ kFullyQualifiedInterfaceName_2_0, listManifestByInterface_cb);
+ if (!hidl_retval.isOk()) {
+ LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: "
+ << hidl_retval.description();
+ return;
+ }
+
+ if (instance_count > 0) {
+ providersFactory = IBluetoothAudioProvidersFactory_2_0::getService();
+ CHECK(providersFactory)
+ << "V2_0::IBluetoothAudioProvidersFactory::getService() failed";
+
+ LOG(INFO)
+ << "V2_0::IBluetoothAudioProvidersFactory::getService() returned "
+ << providersFactory.get()
+ << (providersFactory->isRemote() ? " (remote)" : " (local)");
+ return;
+ }
+
+ LOG(FATAL) << __func__ << " No supported HAL version";
+ }
+
+ private:
+ static std::unique_ptr<HalVersionManager> instance_ptr;
+ std::mutex mutex_;
+
+ android::sp<IBluetoothAudioProvidersFactory_2_0> providersFactory;
+ android::sp<IBluetoothAudioProvidersFactory_2_1> providersFactory_2_1;
+};
+
+} // namespace audio
+} // namespace bluetooth
shared_libs: [
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libaaudio",
"libcrypto",
"libcutils",
"android.hardware.bluetooth@1.0",
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libfmq",
"libhidlbase",
"liblog",
shared_libs: [
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"android.hardware.bluetooth@1.0",
"android.hardware.bluetooth@1.1",
"android.system.suspend.control-V1-ndk",
"android.hardware.bluetooth@1.1",
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libaaudio",
"libcutils",
"libdl",
"android.hardware.bluetooth@1.1",
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"libaaudio",
"libfmq",
"libhidlbase",
shared_libs: [
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"android.hardware.bluetooth@1.0",
"android.hardware.bluetooth@1.1",
"libaaudio",