/* * 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. */ #include #include #include #include "bluetooth_def.h" #include "bluetooth_avrcp_tg_proxy.h" #include "bluetooth_avrcp_tg_observer_stub.h" #include "bluetooth_host.h" #include "bluetooth_host_proxy.h" #include "bluetooth_load_system_ability.h" #include "bluetooth_log.h" #include "bluetooth_utils.h" #include "bluetooth_observer_list.h" #include "iservice_registry.h" #include "raw_address.h" #include "system_ability_definition.h" #include "bluetooth_avrcp_tg.h" namespace OHOS { namespace Bluetooth { std::mutex g_avrcpTgMutex; struct AvrcpTarget::impl { public: class ObserverImpl : public BluetoothAvrcpTgObserverStub { public: explicit ObserverImpl(AvrcpTarget::impl *impl) : impl_(impl) {} ~ObserverImpl() override = default; void OnConnectionStateChanged(const BluetoothRawAddress &addr, int32_t state) override { HILOGD("enter, address: %{public}s, state: %{public}d", GetEncryptAddr(addr.GetAddress()).c_str(), state); BluetoothRemoteDevice device(addr.GetAddress(), BTTransport::ADAPTER_BREDR); impl_->OnConnectionStateChanged(device, static_cast(state)); return; } private: AvrcpTarget::impl *impl_; }; class AvrcpTgDeathRecipient final : public IRemoteObject::DeathRecipient { public: explicit AvrcpTgDeathRecipient(AvrcpTarget::impl &avrcpTgServer) : avrcpTgServer_(avrcpTgServer) {}; ~AvrcpTgDeathRecipient() final = default; BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(AvrcpTgDeathRecipient); void OnRemoteDied(const wptr &remote) final { HILOGI("starts"); std::lock_guard lock(g_avrcpTgMutex); if (!avrcpTgServer_.proxy_) { return; } avrcpTgServer_.proxy_ = nullptr; } private: AvrcpTarget::impl &avrcpTgServer_; }; impl() { if (proxy_) { return; } BluetootLoadSystemAbility::GetInstance().RegisterNotifyMsg(PROFILE_ID_AVRCP_TG); if (!BluetootLoadSystemAbility::GetInstance().HasSubscribedBluetoothSystemAbility()) { BluetootLoadSystemAbility::GetInstance().SubScribeBluetoothSystemAbility(); return; } InitAvrcpTgProxy(); } ~impl() { HILOGI("enter"); if (proxy_ != nullptr) { proxy_->UnregisterObserver(observer_); proxy_->AsObject()->RemoveDeathRecipient(deathRecipient_); } } bool InitAvrcpTgProxy(void) { std::lock_guard lock(g_avrcpTgMutex); if (proxy_) { return true; } proxy_ = GetRemoteProxy(PROFILE_AVRCP_TG); if (!proxy_) { HILOGE("get AvrcpTarget proxy failed"); return false; } observer_ = new (std::nothrow) ObserverImpl(this); if (observer_ != nullptr) { proxy_->RegisterObserver(observer_); } deathRecipient_ = new AvrcpTgDeathRecipient(*this); if (deathRecipient_ != nullptr) { proxy_->AsObject()->AddDeathRecipient(deathRecipient_); } return true; } bool IsEnabled(void) { HILOGI("enter"); return (proxy_ != nullptr && !BluetoothHost::GetDefaultHost().IsBtDiscovering()); } void OnConnectionStateChanged(const BluetoothRemoteDevice &device, int state) { HILOGI("enter, device: %{public}s, state: %{public}d", GET_ENCRYPT_ADDR(device), state); std::lock_guard lock(observerMutex_); observers_.ForEach([device, state](std::shared_ptr observer) { observer->OnConnectionStateChanged(device, state); }); } std::mutex observerMutex_; sptr proxy_; BluetoothObserverList observers_; sptr observer_; sptr deathRecipient_; }; AvrcpTarget *AvrcpTarget::GetProfile(void) { HILOGI("enter"); static AvrcpTarget instance; return &instance; } void AvrcpTarget::Init() { if (!pimpl) { HILOGE("fails: no pimpl"); return; } if (!pimpl->InitAvrcpTgProxy()) { HILOGE("AvrcpTarget proxy is nullptr"); return; } } /****************************************************************** * REGISTER / UNREGISTER OBSERVER * ******************************************************************/ void AvrcpTarget::RegisterObserver(AvrcpTarget::IObserver *observer) { HILOGI("enter"); std::lock_guard lock(pimpl->observerMutex_); std::shared_ptr observerPtr(observer, [](IObserver *) {}); pimpl->observers_.Register(observerPtr); } void AvrcpTarget::UnregisterObserver(AvrcpTarget::IObserver *observer) { HILOGI("enter"); std::lock_guard lock(pimpl->observerMutex_); std::shared_ptr observerPtr(observer, [](IObserver *) {}); pimpl->observers_.Deregister(observerPtr); } /****************************************************************** * CONNECTION * ******************************************************************/ void AvrcpTarget::SetActiveDevice(const BluetoothRemoteDevice &device) { HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device)); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } BluetoothRawAddress rawAddr(device.GetDeviceAddr()); pimpl->proxy_->SetActiveDevice(rawAddr); } std::vector AvrcpTarget::GetConnectedDevices(void) { if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return std::vector(); } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return std::vector(); } std::vector devices; std::vector rawAddrs = pimpl->proxy_->GetConnectedDevices(); for (auto rawAddr : rawAddrs) { BluetoothRemoteDevice device(rawAddr.GetAddress(), BTTransport::ADAPTER_BREDR); devices.push_back(device); } return devices; } std::vector AvrcpTarget::GetDevicesByStates(std::vector states) { if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return std::vector(); } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return std::vector(); } std::vector convertStates; for (auto state : states) { convertStates.push_back(static_cast(state)); } std::vector devices; std::vector rawAddrs = pimpl->proxy_->GetDevicesByStates(convertStates); for (auto rawAddr : rawAddrs) { BluetoothRemoteDevice device(rawAddr.GetAddress(), BTTransport::ADAPTER_BREDR); devices.push_back(device); } return devices; } int AvrcpTarget::GetDeviceState(const BluetoothRemoteDevice &device) { HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device)); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return static_cast(BTConnectState::DISCONNECTED); } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return static_cast(BTConnectState::DISCONNECTED); } BluetoothRawAddress rawAddr(device.GetDeviceAddr()); int32_t result = pimpl->proxy_->GetDeviceState(rawAddr); return static_cast(result); } bool AvrcpTarget::Connect(const BluetoothRemoteDevice &device) { HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device)); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return RET_BAD_STATUS; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return RET_BAD_STATUS; } BluetoothRawAddress rawAddr(device.GetDeviceAddr()); int result = pimpl->proxy_->Connect(rawAddr); return result == RET_NO_ERROR; } bool AvrcpTarget::Disconnect(const BluetoothRemoteDevice &device) { HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device)); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return RET_BAD_STATUS; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return RET_BAD_STATUS; } BluetoothRawAddress rawAddr(device.GetDeviceAddr()); int result = pimpl->proxy_->Disconnect(rawAddr); return result == RET_NO_ERROR; } /****************************************************************** * NOTIFICATION * ******************************************************************/ void AvrcpTarget::NotifyPlaybackStatusChanged(uint8_t playStatus, uint32_t playbackPos) { HILOGI("enter, playStatus: %{public}d, playbackPos: %{public}d", playStatus, playbackPos); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyPlaybackStatusChanged(static_cast(playStatus), static_cast(playbackPos)); } void AvrcpTarget::NotifyTrackChanged(uint64_t uid, uint32_t playbackPos) { HILOGI("enter, playbackPos: %{public}d", playbackPos); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyTrackChanged(static_cast(uid), static_cast(playbackPos)); } void AvrcpTarget::NotifyTrackReachedEnd(uint32_t playbackPos) { HILOGI("enter, playbackPos: %{public}d", playbackPos); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyTrackReachedEnd(static_cast(playbackPos)); } void AvrcpTarget::NotifyTrackReachedStart(uint32_t playbackPos) { HILOGI("enter, playbackPos: %{public}d", playbackPos); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyTrackReachedStart(static_cast(playbackPos)); } void AvrcpTarget::NotifyPlaybackPosChanged(uint32_t playbackPos) { HILOGI("enter, playbackPos: %{public}d", playbackPos); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyPlaybackPosChanged(static_cast(playbackPos)); } void AvrcpTarget::NotifyPlayerAppSettingChanged(const std::vector &attributes, const std::vector &values) { HILOGI("enter"); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } std::vector attrs; for (auto attribute : attributes) { attrs.push_back(attribute); } std::vector vals; for (auto value : values) { vals.push_back(value); } pimpl->proxy_->NotifyPlayerAppSettingChanged(attrs, vals); } void AvrcpTarget::NotifyNowPlayingContentChanged(void) { HILOGI("enter"); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyNowPlayingContentChanged(); } void AvrcpTarget::NotifyAvailablePlayersChanged(void) { HILOGI("enter"); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyAvailablePlayersChanged(); } void AvrcpTarget::NotifyAddressedPlayerChanged(uint16_t playerId, uint16_t uidCounter) { HILOGI("enter, playerId: %{public}d, uidCounter: %{public}d", playerId, uidCounter); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyAddressedPlayerChanged(static_cast(playerId), static_cast(uidCounter)); } void AvrcpTarget::NotifyUidChanged(uint16_t uidCounter) { HILOGI("enter, uidCounter: %{public}d", uidCounter); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyUidChanged(static_cast(uidCounter)); } void AvrcpTarget::NotifyVolumeChanged(uint8_t volume) { HILOGI("enter, volume: %{public}d", volume); if (!IS_BT_ENABLED()) { HILOGE("bluetooth is off."); return; } if (pimpl == nullptr || !pimpl->proxy_) { HILOGE("pimpl or avrcpTarget proxy is nullptr"); return; } pimpl->proxy_->NotifyVolumeChanged(static_cast(volume)); } AvrcpTarget::AvrcpTarget(void) { HILOGI("enter"); pimpl = std::make_unique(); } AvrcpTarget::~AvrcpTarget(void) { HILOGI("enter"); if (!pimpl || !pimpl->proxy_) { return; } pimpl->proxy_->AsObject()->RemoveDeathRecipient(pimpl->deathRecipient_); pimpl = nullptr; } } // namespace Bluetooth } // namespace OHOS