* Copyright (C) 2021-2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef LOG_TAG
#define LOG_TAG "bt_fwk_a2dp_src"
#endif
#include "bluetooth_a2dp_src.h"
#include <unistd.h>
#include "bluetooth_a2dp_codec.h"
#include "bluetooth_a2dp_src_proxy.h"
#include "bluetooth_a2dp_src_observer_stub.h"
#include "bluetooth_device.h"
#include "bluetooth_host_proxy.h"
#include "bluetooth_profile_manager.h"
#include "bluetooth_observer_list.h"
#include "raw_address.h"
#include "bluetooth_def.h"
#include "bluetooth_host.h"
#include "bluetooth_log.h"
#include "bluetooth_utils.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
namespace OHOS {
namespace Bluetooth {
using namespace OHOS::bluetooth;
std::mutex g_a2dpProxyMutex;
struct A2dpSource::impl {
impl();
~impl();
BluetoothObserverList<A2dpSourceObserver> observers_;
class BluetoothA2dpSourceObserverImp;
sptr<BluetoothA2dpSourceObserverImp> observerImp_ = nullptr;
int32_t profileRegisterId = 0;
};
class A2dpSource::impl::BluetoothA2dpSourceObserverImp : public BluetoothA2dpSrcObserverStub {
public:
explicit BluetoothA2dpSourceObserverImp(A2dpSource::impl &a2dpSource) : a2dpSource_(a2dpSource) {};
~BluetoothA2dpSourceObserverImp() override{};
void Register(std::shared_ptr<A2dpSourceObserver> &observer)
{
HILOGI("enter");
a2dpSource_.observers_.Register(observer);
}
void Deregister(std::shared_ptr<A2dpSourceObserver> &observer)
{
HILOGI("enter");
a2dpSource_.observers_.Deregister(observer);
}
void OnConnectionStateChanged(const RawAddress &device, int state, int cause) override
{
HILOGD("a2dpSrc conn state, device: %{public}s, state: %{public}s, cause: %{public}d",
GET_ENCRYPT_RAW_ADDR(device), GetProfileConnStateName(state).c_str(), cause);
a2dpSource_.observers_.ForEach([device, state, cause](std::shared_ptr<A2dpSourceObserver> observer) {
observer->OnConnectionStateChanged(BluetoothRemoteDevice(device.GetAddress(), 0), state, cause);
});
}
void OnCaptureConnectionStateChanged(const RawAddress &device, int state,
const BluetoothA2dpCodecInfo &info) override
{
HILOGD("hdap conn state, device: %{public}s, state: %{public}d", GET_ENCRYPT_RAW_ADDR(device), state);
a2dpSource_.observers_.ForEach([device, state, info](std::shared_ptr<A2dpSourceObserver> observer) {
A2dpCodecInfo codecInfo{};
codecInfo.bitsPerSample = info.bitsPerSample;
codecInfo.channelMode = info.channelMode;
codecInfo.codecType = info.codecType;
codecInfo.sampleRate = info.sampleRate;
observer->OnCaptureConnectionStateChanged(BluetoothRemoteDevice(device.GetAddress(), 0), state, codecInfo);
});
}
void OnPlayingStatusChanged(const RawAddress &device, int playingState, int error) override
{
HILOGI("device: %{public}s, playingState: %{public}d, error: %{public}d",
GetEncryptAddr(device.GetAddress()).c_str(), playingState, error);
a2dpSource_.observers_.ForEach([device, playingState, error](std::shared_ptr<A2dpSourceObserver> observer) {
observer->OnPlayingStatusChanged(BluetoothRemoteDevice(device.GetAddress(), 0), playingState, error);
});
}
void OnConfigurationChanged(const RawAddress &device, const BluetoothA2dpCodecInfo &info, int error) override
{
HILOGD("device: %{public}s, error: %{public}d", GetEncryptAddr(device.GetAddress()).c_str(), error);
a2dpSource_.observers_.ForEach([device, info, error](std::shared_ptr<A2dpSourceObserver> observer) {
A2dpCodecInfo codecInfo;
codecInfo.bitsPerSample = info.bitsPerSample;
codecInfo.channelMode = info.channelMode;
codecInfo.codecPriority = info.codecPriority;
codecInfo.codecType = info.codecType;
codecInfo.sampleRate = info.sampleRate;
observer->OnConfigurationChanged(BluetoothRemoteDevice(device.GetAddress(), 0), codecInfo, error);
});
};
void OnMediaStackChanged(const RawAddress &device, int action) override
{
HILOGI("device: %{public}s, action: %{public}s",
GET_ENCRYPT_RAW_ADDR(device), GetUpdateOutputStackActionName(action).c_str());
a2dpSource_.observers_.ForEach([device, action](std::shared_ptr<A2dpSourceObserver> observer) {
observer->OnMediaStackChanged(BluetoothRemoteDevice(device.GetAddress(), 0), action);
});
}
void OnVirtualDeviceChanged(int action, std::string address) override
{
HILOGI("device: %{public}s, action: %{public}d", GetEncryptAddr(address).c_str(), action);
a2dpSource_.observers_.ForEach([action, address](std::shared_ptr<A2dpSourceObserver> observer) {
observer->OnVirtualDeviceChanged(action, address);
});
}
private:
A2dpSource::impl &a2dpSource_;
BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSourceObserverImp);
};
A2dpSource::impl::impl()
{
observerImp_ = new (std::nothrow) BluetoothA2dpSourceObserverImp(*this);
CHECK_AND_RETURN_LOG(observerImp_ != nullptr, "observerImp_ is nullptr");
profileRegisterId = BluetoothProfileManager::GetInstance().RegisterFunc(PROFILE_A2DP_SRC,
[this](sptr<IRemoteObject> remote) {
sptr<IBluetoothA2dpSrc> proxy = iface_cast<IBluetoothA2dpSrc>(remote);
CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
proxy->RegisterObserver(observerImp_);
});
};
A2dpSource::impl::~impl()
{
HILOGD("start");
BluetoothProfileManager::GetInstance().DeregisterFunc(profileRegisterId);
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
proxy->DeregisterObserver(observerImp_);
}
A2dpSource::A2dpSource()
{
pimpl = std::make_unique<impl>();
if (!pimpl) {
HILOGE("fails: no pimpl");
}
}
A2dpSource::~A2dpSource()
{
HILOGD("start");
}
void A2dpSource::RegisterObserver(std::shared_ptr<A2dpSourceObserver> observer)
{
HILOGD("enter");
CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
CHECK_AND_RETURN_LOG(observer != nullptr, "observer is null.");
pimpl->observers_.Register(observer);
}
void A2dpSource::DeregisterObserver(std::shared_ptr<A2dpSourceObserver> observer)
{
HILOGD("enter");
CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
pimpl->observers_.Deregister(observer);
}
int A2dpSource::GetDevicesByStates(const std::vector<int> &states, std::vector<BluetoothRemoteDevice> &devices) const
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
std::vector<int32_t> convertStates;
for (auto state : states) {
convertStates.push_back(static_cast<int32_t>(state));
}
std::vector<RawAddress> rawAddrs;
int ret = proxy->GetDevicesByStates(convertStates, rawAddrs);
if (ret != BT_NO_ERROR) {
HILOGE("GetDevicesByStates return error.");
return ret;
}
for (auto rawAddr : rawAddrs) {
BluetoothRemoteDevice device(rawAddr.GetAddress(), BTTransport::ADAPTER_BREDR);
devices.push_back(device);
}
return BT_NO_ERROR;
}
int A2dpSource::GetDeviceState(const BluetoothRemoteDevice &device, int &state) const
{
HILOGD("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
int ret = proxy->GetDeviceState(RawAddress(device.GetDeviceAddr()), state);
HILOGD("state: %{public}d", ret);
return ret;
}
int32_t A2dpSource::GetPlayingState(const BluetoothRemoteDevice &device) const
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
int ret = RET_NO_ERROR;
proxy->GetPlayingState(RawAddress(device.GetDeviceAddr()), ret);
HILOGI("state: %{public}d", ret);
return ret;
}
int32_t A2dpSource::GetPlayingState(const BluetoothRemoteDevice &device, int &state) const
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
return proxy->GetPlayingState(RawAddress(device.GetDeviceAddr()), state);
}
int32_t A2dpSource::Connect(const BluetoothRemoteDevice &device)
{
HILOGI("a2dp connect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
return proxy->Connect(RawAddress(device.GetDeviceAddr()));
}
int32_t A2dpSource::Disconnect(const BluetoothRemoteDevice &device)
{
HILOGI("a2dp disconnect remote device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
return proxy->Disconnect(RawAddress(device.GetDeviceAddr()));
}
A2dpSource *A2dpSource::GetProfile()
{
HILOGD("enter");
#ifdef DTFUZZ_TEST
static BluetoothNoDestructor<A2dpSource> service;
return service.get();
#else
static A2dpSource service;
return &service;
#endif
}
int A2dpSource::SetActiveSinkDevice(const BluetoothRemoteDevice &device)
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
return proxy->SetActiveSinkDevice(RawAddress(device.GetDeviceAddr()));
}
const BluetoothRemoteDevice &A2dpSource::GetActiveSinkDevice() const
{
HILOGI("enter");
static BluetoothRemoteDevice deviceInfo;
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return deviceInfo;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, deviceInfo, "failed: no proxy");
BluetoothRawAddress rawAddress = proxy->GetActiveSinkDevice();
deviceInfo = BluetoothRemoteDevice(rawAddress.GetAddress(), 0);
return deviceInfo;
}
int A2dpSource::SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
{
HILOGI("device: %{public}s, strategy: %{public}d", GET_ENCRYPT_ADDR(device), strategy);
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY, "failed: no proxy");
if ((!device.IsValidBluetoothRemoteDevice()) || (
(strategy != static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)) &&
(strategy != static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN)))) {
HILOGI("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
return proxy->SetConnectStrategy(RawAddress(device.GetDeviceAddr()), strategy);
}
int A2dpSource::GetConnectStrategy(const BluetoothRemoteDevice &device, int &strategy) const
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INVALID_STATE, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGI("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
return proxy->GetConnectStrategy(RawAddress(device.GetDeviceAddr()), strategy);
}
A2dpCodecStatus A2dpSource::GetCodecStatus(const BluetoothRemoteDevice &device) const
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
A2dpCodecStatus ret;
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return ret;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, ret, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return ret;
}
BluetoothA2dpCodecStatus codecStatus = proxy->GetCodecStatus(RawAddress(device.GetDeviceAddr()));
ret.codecInfo.codecType = codecStatus.codecInfo.codecType;
ret.codecInfo.sampleRate = codecStatus.codecInfo.sampleRate;
ret.codecInfo.channelMode = codecStatus.codecInfo.channelMode;
ret.codecInfo.codecPriority = codecStatus.codecInfo.codecPriority;
ret.codecInfo.bitsPerSample = codecStatus.codecInfo.bitsPerSample;
ret.codecInfo.codecSpecific3 = codecStatus.codecInfo.codecSpecific3;
ret.codecInfo.codecSpecific4 = codecStatus.codecInfo.codecSpecific4;
A2dpCodecInfo serviceInfo;
for (auto it = codecStatus.codecInfoConfirmCap.begin(); it != codecStatus.codecInfoConfirmCap.end(); it++) {
serviceInfo.codecType = it->codecType;
serviceInfo.sampleRate = it->sampleRate;
serviceInfo.channelMode = it->channelMode;
serviceInfo.codecPriority = it->codecPriority;
serviceInfo.bitsPerSample = it->bitsPerSample;
serviceInfo.codecSpecific3 = it->codecSpecific3;
serviceInfo.codecSpecific4 = it->codecSpecific4;
ret.codecInfoConfirmedCap.push_back(serviceInfo);
}
for (auto it = codecStatus.codecInfoLocalCap.begin(); it != codecStatus.codecInfoLocalCap.end(); it++) {
serviceInfo.codecType = it->codecType;
serviceInfo.sampleRate = it->sampleRate;
serviceInfo.channelMode = it->channelMode;
serviceInfo.codecPriority = it->codecPriority;
serviceInfo.bitsPerSample = it->bitsPerSample;
serviceInfo.codecSpecific3 = it->codecSpecific3;
serviceInfo.codecSpecific4 = it->codecSpecific4;
ret.codecInfoLocalCap.push_back(serviceInfo);
}
return ret;
}
int A2dpSource::GetCodecPreference(const BluetoothRemoteDevice &device, A2dpCodecInfo &info)
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
BluetoothA2dpCodecInfo serviceInfo;
int ret = proxy->GetCodecPreference(RawAddress(device.GetDeviceAddr()), serviceInfo);
if (ret != BT_NO_ERROR) {
HILOGE("GetCodecPreference error.");
return ret;
}
info.codecType = serviceInfo.codecType;
info.sampleRate = serviceInfo.sampleRate;
info.channelMode = serviceInfo.channelMode;
info.bitsPerSample = serviceInfo.bitsPerSample;
info.codecSpecific3 = serviceInfo.codecSpecific3;
info.codecSpecific4 = serviceInfo.codecSpecific4;
return ret;
}
int A2dpSource::SetCodecPreference(const BluetoothRemoteDevice &device, const A2dpCodecInfo &info)
{
HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return BT_ERR_INVALID_PARAM;
}
BluetoothA2dpCodecInfo serviceInfo;
serviceInfo.codecType = info.codecType;
serviceInfo.sampleRate = info.sampleRate;
serviceInfo.channelMode = info.channelMode;
serviceInfo.bitsPerSample = info.bitsPerSample;
serviceInfo.codecPriority = info.codecPriority;
serviceInfo.codecSpecific1 = info.codecSpecific1;
serviceInfo.codecSpecific2 = info.codecSpecific2;
serviceInfo.codecSpecific3 = info.codecSpecific3;
serviceInfo.codecSpecific4 = info.codecSpecific4;
return proxy->SetCodecPreference(RawAddress(device.GetDeviceAddr()), serviceInfo);
}
void A2dpSource::SwitchOptionalCodecs(const BluetoothRemoteDevice &device, bool isEnable)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return;
}
proxy->SwitchOptionalCodecs(RawAddress(device.GetDeviceAddr()), isEnable);
}
int A2dpSource::GetOptionalCodecsSupportState(const BluetoothRemoteDevice &device) const
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
return proxy->GetOptionalCodecsSupportState(RawAddress(device.GetDeviceAddr()));
}
int A2dpSource::StartPlaying(const BluetoothRemoteDevice &device)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
return proxy->StartPlaying(RawAddress(device.GetDeviceAddr()));
}
int A2dpSource::SuspendPlaying(const BluetoothRemoteDevice &device)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
return proxy->SuspendPlaying(RawAddress(device.GetDeviceAddr()));
}
int A2dpSource::StopPlaying(const BluetoothRemoteDevice &device)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("input parameter error.");
return RET_BAD_PARAM;
}
return proxy->StopPlaying(RawAddress(device.GetDeviceAddr()));
}
int A2dpSource::WriteFrame(const uint8_t *data, uint32_t size)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "failed: no proxy");
return proxy->WriteFrame(data, size);
}
int A2dpSource::GetRenderPosition(const BluetoothRemoteDevice &device, uint32_t &delayValue, uint64_t &sendDataSize,
uint32_t &timeStamp)
{
HILOGI("enter");
if (!IS_BT_ENABLED()) {
HILOGE("bluetooth is off.");
return RET_BAD_STATUS;
}
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "device err");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
return proxy->GetRenderPosition(RawAddress(device.GetDeviceAddr()), delayValue, sendDataSize, timeStamp);
}
int A2dpSource::OffloadStartPlaying(const BluetoothRemoteDevice &device, const std::vector<int32_t> &sessionsId)
{
HILOGI("enter, start playing device:%{public}s", GET_ENCRYPT_ADDR(device));
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "device err");
CHECK_AND_RETURN_LOG_RET(device.GetDeviceAddr() != INVALID_MAC_ADDRESS, BT_ERR_INVALID_PARAM, "invaild mac");
CHECK_AND_RETURN_LOG_RET(sessionsId.size() != 0, BT_ERR_INVALID_PARAM, "session size zero.");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY,
"a2dpSrc proxy is nullptr");
return proxy->OffloadStartPlaying(RawAddress(device.GetDeviceAddr()), sessionsId);
}
int A2dpSource::OffloadStopPlaying(const BluetoothRemoteDevice &device, const std::vector<int32_t> &sessionsId)
{
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "device err");
CHECK_AND_RETURN_LOG_RET(device.GetDeviceAddr() != INVALID_MAC_ADDRESS, BT_ERR_INVALID_PARAM, "invaild mac");
CHECK_AND_RETURN_LOG_RET(sessionsId.size() != 0, BT_ERR_INVALID_PARAM, "session size zero.");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_UNAVAILABLE_PROXY,
"a2dpSrc proxy is nullptr");
return proxy->OffloadStopPlaying(RawAddress(device.GetDeviceAddr()), sessionsId);
}
int A2dpSource::A2dpOffloadSessionRequest(const BluetoothRemoteDevice &device, const std::vector<A2dpStreamInfo> &info)
{
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), A2DP_STREAM_ENCODE_UNKNOWN, "device err");
CHECK_AND_RETURN_LOG_RET(device.GetDeviceAddr() != INVALID_MAC_ADDRESS, A2DP_STREAM_ENCODE_UNKNOWN, "invaild mac");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), A2DP_STREAM_ENCODE_UNKNOWN, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, A2DP_STREAM_ENCODE_UNKNOWN, "a2dpSrc proxy is nullptr");
std::vector<BluetoothA2dpStreamInfo> streamsInfo = {};
BluetoothA2dpStreamInfo streamInfo;
for (auto stream : info) {
streamInfo.sessionId = stream.sessionId;
streamInfo.streamType = stream.streamType;
streamInfo.sampleRate = stream.sampleRate;
streamInfo.isSpatialAudio = stream.isSpatialAudio;
streamsInfo.push_back(streamInfo);
}
return proxy->A2dpOffloadSessionPathRequest(RawAddress(device.GetDeviceAddr()), streamsInfo);
}
A2dpOffloadCodecStatus::A2dpOffloadCodecStatus(const BluetoothA2dpOffloadCodecStatus &status)
{
offloadInfo.mediaPacketHeader = status.offloadInfo.mediaPacketHeader;
offloadInfo.mPt = status.offloadInfo.mPt;
offloadInfo.ssrc = status.offloadInfo.ssrc;
offloadInfo.boundaryFlag = status.offloadInfo.boundaryFlag;
offloadInfo.broadcastFlag = status.offloadInfo.broadcastFlag;
offloadInfo.codecType = status.offloadInfo.codecType;
offloadInfo.maxLatency = status.offloadInfo.maxLatency;
offloadInfo.scmsTEnable = status.offloadInfo.scmsTEnable;
offloadInfo.sampleRate = status.offloadInfo.sampleRate;
offloadInfo.encodedAudioBitrate = status.offloadInfo.encodedAudioBitrate;
offloadInfo.bitsPerSample = status.offloadInfo.bitsPerSample;
offloadInfo.chMode = status.offloadInfo.chMode;
offloadInfo.aclHdl = status.offloadInfo.aclHdl;
offloadInfo.l2cRcid = status.offloadInfo.l2cRcid;
offloadInfo.mtu = status.offloadInfo.mtu;
offloadInfo.codecSpecific0 = status.offloadInfo.codecSpecific0;
offloadInfo.codecSpecific1 = status.offloadInfo.codecSpecific1;
offloadInfo.codecSpecific2 = status.offloadInfo.codecSpecific2;
offloadInfo.codecSpecific3 = status.offloadInfo.codecSpecific3;
offloadInfo.codecSpecific4 = status.offloadInfo.codecSpecific4;
offloadInfo.codecSpecific5 = status.offloadInfo.codecSpecific5;
offloadInfo.codecSpecific6 = status.offloadInfo.codecSpecific6;
offloadInfo.codecSpecific7 = status.offloadInfo.codecSpecific7;
}
A2dpOffloadCodecStatus A2dpSource::GetOffloadCodecStatus(const BluetoothRemoteDevice &device) const
{
HILOGI("enter");
A2dpOffloadCodecStatus ret;
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), ret, "input device err");
CHECK_AND_RETURN_LOG_RET(device.GetDeviceAddr() != INVALID_MAC_ADDRESS, ret, "invaild mac");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), ret, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, ret, "a2dpSrc proxy is nullptr");
BluetoothA2dpOffloadCodecStatus offloadStatus(proxy->GetOffloadCodecStatus(RawAddress(device.GetDeviceAddr())));
A2dpOffloadCodecStatus status(offloadStatus);
HILOGI("codecType:%{public}x,mtu:%{public}d", status.offloadInfo.codecType, status.offloadInfo.mtu);
return status;
}
int A2dpSource::EnableAutoPlay(const BluetoothRemoteDevice &device)
{
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "input device err");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INVALID_STATE, "a2dpSrc proxy is nullptr");
return proxy->EnableAutoPlay(RawAddress(device.GetDeviceAddr()));
}
int A2dpSource::DisableAutoPlay(const BluetoothRemoteDevice &device, const int duration)
{
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "input device err");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INVALID_STATE, "a2dpSrc proxy is nullptr");
return proxy->DisableAutoPlay(RawAddress(device.GetDeviceAddr()), duration);
}
int A2dpSource::GetAutoPlayDisabledDuration(const BluetoothRemoteDevice &device, int &duration)
{
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INVALID_PARAM, "input device err");
CHECK_AND_RETURN_LOG_RET(IS_BT_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INVALID_STATE, "a2dpSrc proxy is nullptr");
return proxy->GetAutoPlayDisabledDuration(RawAddress(device.GetDeviceAddr()), duration);
}
void A2dpSource::GetVirtualDeviceList(std::vector<std::string> &devices)
{
CHECK_AND_RETURN_LOG(IS_BT_ENABLED(), "bluetooth is off.");
sptr<IBluetoothA2dpSrc> proxy = GetRemoteProxy<IBluetoothA2dpSrc>(PROFILE_A2DP_SRC);
CHECK_AND_RETURN_LOG(proxy != nullptr, "a2dpSrc proxy is nullptr");
proxy->GetVirtualDeviceList(devices);
}
}
}