1/*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "bluetooth_a2dp_snk.h"
16#include <cstdint>
17#include "bluetooth_a2dp_sink_observer_stub.h"
18#include "bluetooth_def.h"
19#include "bluetooth_host.h"
20#include "bluetooth_profile_manager.h"
21#include "bluetooth_log.h"
22#include "bluetooth_observer_list.h"
23#include "bluetooth_remote_device.h"
24#include "bluetooth_types.h"
25#include "bluetooth_utils.h"
26#include "functional"
27#include "i_bluetooth_a2dp_sink.h"
28#include "i_bluetooth_a2dp_sink_observer.h"
29#include "i_bluetooth_host.h"
30#include "if_system_ability_manager.h"
31#include "iosfwd"
32#include "iremote_broker.h"
33#include "iremote_object.h"
34#include "iservice_registry.h"
35#include "list"
36#include "memory"
37#include "new"
38#include "raw_address.h"
39#include "refbase.h"
40#include "string"
41#include "system_ability_definition.h"
42#include "vector"
43
44namespace OHOS {
45namespace Bluetooth {
46using namespace OHOS::bluetooth;
47std::mutex g_a2dpSnkProxyMutex;
48struct A2dpSink::impl {
49    impl();
50    ~impl();
51    BluetoothObserverList<A2dpSinkObserver> observers_;
52    class BluetoothA2dpSinkObserverImp;
53    sptr<BluetoothA2dpSinkObserverImp> observerImp_ = nullptr;
54    int32_t profileRegisterId = 0;
55};
56
57class A2dpSink::impl::BluetoothA2dpSinkObserverImp : public BluetoothA2dpSinkObserverStub {
58public:
59    explicit BluetoothA2dpSinkObserverImp(A2dpSink::impl &a2dpSink) : a2dpSink_(a2dpSink)
60    {};
61    ~BluetoothA2dpSinkObserverImp() override
62    {};
63
64    void Register(std::shared_ptr<A2dpSinkObserver> &observer)
65    {
66        HILOGI("enter");
67        a2dpSink_.observers_.Register(observer);
68    }
69
70    void Deregister(std::shared_ptr<A2dpSinkObserver> &observer)
71    {
72        HILOGI("enter");
73        a2dpSink_.observers_.Deregister(observer);
74    }
75
76    void OnConnectionStateChanged(const RawAddress &device, int state, int cause) override
77    {
78        HILOGD("device: %{public}s, state: %{public}d, cause: %{public}d",
79            GET_ENCRYPT_RAW_ADDR(device), state, cause);
80        a2dpSink_.observers_.ForEach([device, state, cause](std::shared_ptr<A2dpSinkObserver> observer) {
81            observer->OnConnectionStateChanged(BluetoothRemoteDevice(device.GetAddress(), 0), state, cause);
82        });
83    }
84
85private:
86    A2dpSink::impl &a2dpSink_;
87    BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSinkObserverImp);
88};
89
90A2dpSink::impl::impl()
91{
92    observerImp_ = new (std::nothrow) BluetoothA2dpSinkObserverImp(*this);
93    CHECK_AND_RETURN_LOG(observerImp_ != nullptr, "observerImp_ is nullptr");
94    profileRegisterId = BluetoothProfileManager::GetInstance().RegisterFunc(PROFILE_A2DP_SINK,
95        [this](sptr<IRemoteObject> remote) {
96        sptr<IBluetoothA2dpSink> proxy = iface_cast<IBluetoothA2dpSink>(remote);
97        CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
98        proxy->RegisterObserver(observerImp_);
99    });
100};
101
102A2dpSink::impl::~impl()
103{
104    HILOGD("start");
105    BluetoothProfileManager::GetInstance().DeregisterFunc(profileRegisterId);
106    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
107    CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
108    proxy->DeregisterObserver(observerImp_);
109}
110
111A2dpSink::A2dpSink()
112{
113    pimpl = std::make_unique<impl>();
114    if (!pimpl) {
115        HILOGE("fails: no pimpl");
116    }
117}
118
119A2dpSink::~A2dpSink()
120{
121    HILOGD("start");
122}
123
124void A2dpSink::RegisterObserver(std::shared_ptr<A2dpSinkObserver> observer)
125{
126    HILOGD("enter");
127    CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
128    pimpl->observers_.Register(observer);
129}
130
131void A2dpSink::DeregisterObserver(std::shared_ptr<A2dpSinkObserver> observer)
132{
133    HILOGD("enter");
134    CHECK_AND_RETURN_LOG(pimpl != nullptr, "pimpl is null.");
135    pimpl->observers_.Deregister(observer);
136}
137
138int A2dpSink::GetDeviceState(const BluetoothRemoteDevice &device) const
139{
140    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
141    if (!IS_BT_ENABLED()) {
142        HILOGE("bluetooth is off.");
143        return RET_BAD_STATUS;
144    }
145    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
146    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "A2dpSink proxy is nullptr");
147    if (!device.IsValidBluetoothRemoteDevice()) {
148        HILOGE("input parameter error.");
149        return RET_BAD_PARAM;
150    }
151
152    return proxy->GetDeviceState(RawAddress(device.GetDeviceAddr()));
153}
154
155std::vector<BluetoothRemoteDevice> A2dpSink::GetDevicesByStates(std::vector<int> states) const
156{
157    HILOGI("enter");
158
159    if (!IS_BT_ENABLED()) {
160        HILOGE("bluetooth is off.");
161        return std::vector<BluetoothRemoteDevice>();
162    }
163
164    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
165    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, std::vector<BluetoothRemoteDevice>(),
166        "A2dpSink proxy is nullptr");
167
168    std::vector<int32_t> convertStates;
169    for (auto state : states) {
170        convertStates.push_back(static_cast<int32_t>(state));
171    }
172    std::vector<BluetoothRemoteDevice> devices;
173    std::vector<RawAddress> rawAddrs = proxy->GetDevicesByStates(convertStates);
174    for (auto rawAddr : rawAddrs) {
175        BluetoothRemoteDevice device(rawAddr.GetAddress(), BTTransport::ADAPTER_BREDR);
176        devices.push_back(device);
177    }
178    return devices;
179}
180
181int A2dpSink::GetPlayingState(const BluetoothRemoteDevice &device) const
182{
183    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
184    if (!IS_BT_ENABLED()) {
185        HILOGE("bluetooth is off.");
186        return RET_BAD_STATUS;
187    }
188
189    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
190    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "A2dpSink proxy is nullptr");
191
192    if (!device.IsValidBluetoothRemoteDevice()) {
193        HILOGE("input parameter error.");
194        return RET_BAD_PARAM;
195    }
196
197    int ret = RET_BAD_STATUS;
198    proxy->GetPlayingState(RawAddress(device.GetDeviceAddr()), ret);
199    return ret;
200}
201
202int A2dpSink::GetPlayingState(const BluetoothRemoteDevice &device, int &state) const
203{
204    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
205    if (!IS_BT_ENABLED()) {
206        HILOGE("bluetooth is off.");
207        return RET_BAD_STATUS;
208    }
209
210    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
211    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "A2dpSink proxy is nullptr");
212
213    if (!device.IsValidBluetoothRemoteDevice()) {
214        HILOGE("input parameter error.");
215        return RET_BAD_PARAM;
216    }
217
218    return proxy->GetPlayingState(RawAddress(device.GetDeviceAddr()), state);
219}
220
221bool A2dpSink::Connect(const BluetoothRemoteDevice &device)
222{
223    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
224    if (!IS_BT_ENABLED()) {
225        HILOGE("bluetooth is off.");
226        return false;
227    }
228
229    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
230    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, false, "A2dpSink proxy is nullptr");
231
232    if (!device.IsValidBluetoothRemoteDevice()) {
233        HILOGE("input parameter error.");
234        return false;
235    }
236
237    int ret = proxy->Connect(RawAddress(device.GetDeviceAddr()));
238    return (ret == RET_NO_ERROR);
239}
240
241bool A2dpSink::Disconnect(const BluetoothRemoteDevice &device)
242{
243    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
244    if (!IS_BT_ENABLED()) {
245        HILOGE("bluetooth is off.");
246        return false;
247    }
248
249    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
250    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, false, "A2dpSink proxy is nullptr");
251
252    if (!device.IsValidBluetoothRemoteDevice()) {
253        HILOGE("input parameter error.");
254        return false;
255    }
256
257    int ret = proxy->Disconnect(RawAddress(device.GetDeviceAddr()));
258    return (ret == RET_NO_ERROR);
259}
260
261A2dpSink *A2dpSink::GetProfile()
262{
263    HILOGI("enter");
264#ifdef DTFUZZ_TEST
265    static BluetoothNoDestructor<A2dpSink> service;
266    return service.get();
267#else
268    static A2dpSink service;
269    return &service;
270#endif
271}
272
273bool A2dpSink::SetConnectStrategy(const BluetoothRemoteDevice &device, int strategy)
274{
275    HILOGI("enter, device: %{public}s, strategy: %{public}d", GET_ENCRYPT_ADDR(device), strategy);
276    if (!IS_BT_ENABLED()) {
277        HILOGE("bluetooth is off.");
278        return false;
279    }
280    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
281    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, false, "A2dpSink proxy is nullptr");
282
283    if ((!device.IsValidBluetoothRemoteDevice()) ||
284        ((strategy != static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)) &&
285            (strategy != static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN)))) {
286        HILOGE("input parameter error.");
287        return false;
288    }
289
290    int ret = proxy->SetConnectStrategy(RawAddress(device.GetDeviceAddr()), strategy);
291    return (ret == RET_NO_ERROR);
292}
293
294int A2dpSink::GetConnectStrategy(const BluetoothRemoteDevice &device) const
295{
296    HILOGI("enter, device: %{public}s", GET_ENCRYPT_ADDR(device));
297    if (!IS_BT_ENABLED()) {
298        HILOGE("bluetooth is off.");
299        return RET_BAD_STATUS;
300    }
301    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
302    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, RET_BAD_STATUS, "A2dpSink proxy is nullptr");
303
304    if (!device.IsValidBluetoothRemoteDevice()) {
305        HILOGE("input parameter error.");
306        return RET_BAD_PARAM;
307    }
308
309    int ret = proxy->GetConnectStrategy(RawAddress(device.GetDeviceAddr()));
310    return ret;
311}
312
313bool A2dpSink::SendDelay(const BluetoothRemoteDevice &device, uint16_t delayValue)
314{
315    HILOGI("enter, device: %{public}s, delayValue: %{public}d", GET_ENCRYPT_ADDR(device), delayValue);
316    if (!IS_BT_ENABLED()) {
317        HILOGE("bluetooth is off.");
318        return false;
319    }
320    sptr<IBluetoothA2dpSink> proxy = GetRemoteProxy<IBluetoothA2dpSink>(PROFILE_A2DP_SINK);
321    CHECK_AND_RETURN_LOG_RET(proxy != nullptr, false, "A2dpSink proxy is nullptr");
322
323    if (!device.IsValidBluetoothRemoteDevice()) {
324        HILOGE("input parameter error.");
325        return false;
326    }
327
328    int ret = proxy->SendDelay(RawAddress(device.GetDeviceAddr()), (int32_t)delayValue);
329    return (ret == RET_NO_ERROR);
330}
331} // namespace Bluetooth
332} // namespace OHOS