1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "avrcp_service.h"
18 
19 #include <base/bind.h>
20 #include <base/logging.h>
21 #include <base/task/cancelable_task_tracker.h>
22 #include <base/threading/thread.h>
23 #include <mutex>
24 #include <sstream>
25 
26 #include "bta_closure_api.h"
27 #include "btif_av.h"
28 #include "btif_common.h"
29 #include "device.h"
30 
31 namespace bluetooth {
32 namespace avrcp {
33 // Static variables and interface definitions
34 AvrcpService* AvrcpService::instance_ = nullptr;
35 AvrcpService::ServiceInterfaceImpl* AvrcpService::service_interface_ = nullptr;
36 
37 std::mutex jni_mutex_;
38 base::MessageLoop* jni_message_loop_ = nullptr;
39 base::CancelableTaskTracker task_tracker_;
40 
do_in_avrcp_jni(const base::Closure & task)41 void do_in_avrcp_jni(const base::Closure& task) {
42   std::lock_guard<std::mutex> lock(jni_mutex_);
43 
44   if (jni_message_loop_ == nullptr) {
45     LOG(WARNING) << __func__ << ": jni_message_loop_ is null";
46     return;
47   }
48 
49   task_tracker_.PostTask(jni_message_loop_->task_runner().get(), FROM_HERE,
50                          task);
51 }
52 
53 class A2dpInterfaceImpl : public A2dpInterface {
active_peer()54   RawAddress active_peer() override { return btif_av_source_active_peer(); }
55 } a2dp_interface_;
56 
57 class AvrcpInterfaceImpl : public AvrcpInterface {
58  public:
AddRecord(uint16_t service_uuid,const char * p_service_name,const char * p_provider_name,uint16_t categories,uint32_t sdp_handle,bool browse_supported,uint16_t profile_version)59   uint16_t AddRecord(uint16_t service_uuid, const char* p_service_name,
60                      const char* p_provider_name, uint16_t categories,
61                      uint32_t sdp_handle, bool browse_supported,
62                      uint16_t profile_version) override {
63     return AVRC_AddRecord(service_uuid, p_service_name, p_provider_name,
64                           categories, sdp_handle, browse_supported,
65                           profile_version);
66   }
67 
FindService(uint16_t service_uuid,const RawAddress & bd_addr,tAVRC_SDP_DB_PARAMS * p_db,tAVRC_FIND_CBACK p_cback)68   uint16_t FindService(uint16_t service_uuid, const RawAddress& bd_addr,
69                        tAVRC_SDP_DB_PARAMS* p_db,
70                        tAVRC_FIND_CBACK p_cback) override {
71     return AVRC_FindService(service_uuid, bd_addr, p_db, p_cback);
72   }
73 
Open(uint8_t * p_handle,tAVRC_CONN_CB * p_ccb,const RawAddress & bd_addr)74   uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb,
75                 const RawAddress& bd_addr) override {
76     return AVRC_Open(p_handle, p_ccb, bd_addr);
77   }
78 
OpenBrowse(uint8_t handle,uint8_t conn_role)79   uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) override {
80     return AVRC_OpenBrowse(handle, conn_role);
81   }
82 
GetPeerMtu(uint8_t handle)83   uint16_t GetPeerMtu(uint8_t handle) override {
84     return AVCT_GetPeerMtu(handle);
85   }
86 
GetBrowseMtu(uint8_t handle)87   uint16_t GetBrowseMtu(uint8_t handle) override {
88     return AVCT_GetBrowseMtu(handle);
89   }
90 
Close(uint8_t handle)91   uint16_t Close(uint8_t handle) override { return AVRC_Close(handle); }
92 
CloseBrowse(uint8_t handle)93   uint16_t CloseBrowse(uint8_t handle) override {
94     return AVRC_CloseBrowse(handle);
95   }
96 
MsgReq(uint8_t handle,uint8_t label,uint8_t ctype,BT_HDR * p_pkt)97   uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
98                   BT_HDR* p_pkt) override {
99     return AVRC_MsgReq(handle, label, ctype, p_pkt);
100   }
101 } avrcp_interface_;
102 
103 class SdpInterfaceImpl : public SdpInterface {
104  public:
InitDiscoveryDb(tSDP_DISCOVERY_DB * a,uint32_t b,uint16_t c,const bluetooth::Uuid * d,uint16_t e,uint16_t * f)105   bool InitDiscoveryDb(tSDP_DISCOVERY_DB* a, uint32_t b, uint16_t c,
106                        const bluetooth::Uuid* d, uint16_t e,
107                        uint16_t* f) override {
108     return SDP_InitDiscoveryDb(a, b, c, d, e, f);
109   }
110 
ServiceSearchAttributeRequest(const RawAddress & a,tSDP_DISCOVERY_DB * b,tSDP_DISC_CMPL_CB * c)111   bool ServiceSearchAttributeRequest(const RawAddress& a, tSDP_DISCOVERY_DB* b,
112                                      tSDP_DISC_CMPL_CB* c) override {
113     return SDP_ServiceSearchAttributeRequest(a, b, c);
114   }
115 
FindServiceInDb(tSDP_DISCOVERY_DB * a,uint16_t b,t_sdp_disc_rec * c)116   tSDP_DISC_REC* FindServiceInDb(tSDP_DISCOVERY_DB* a, uint16_t b,
117                                  t_sdp_disc_rec* c) override {
118     return SDP_FindServiceInDb(a, b, c);
119   }
120 
FindAttributeInRec(t_sdp_disc_rec * a,uint16_t b)121   tSDP_DISC_ATTR* FindAttributeInRec(t_sdp_disc_rec* a, uint16_t b) override {
122     return SDP_FindAttributeInRec(a, b);
123   }
124 
FindProfileVersionInRec(t_sdp_disc_rec * a,uint16_t b,uint16_t * c)125   bool FindProfileVersionInRec(t_sdp_disc_rec* a, uint16_t b,
126                                uint16_t* c) override {
127     return SDP_FindProfileVersionInRec(a, b, c);
128   }
129 } sdp_interface_;
130 
131 // A wrapper class for the media callbacks that handles thread
132 // switching/synchronization so the devices don't have to worry about it.
133 class MediaInterfaceWrapper : public MediaInterface {
134  public:
MediaInterfaceWrapper(MediaInterface * cb)135   MediaInterfaceWrapper(MediaInterface* cb) : wrapped_(cb){};
136 
SendKeyEvent(uint8_t key,KeyState state)137   void SendKeyEvent(uint8_t key, KeyState state) override {
138     do_in_avrcp_jni(base::Bind(&MediaInterface::SendKeyEvent,
139                                base::Unretained(wrapped_), key, state));
140   }
141 
GetSongInfo(SongInfoCallback info_cb)142   void GetSongInfo(SongInfoCallback info_cb) override {
143     auto cb_lambda = [](SongInfoCallback cb, SongInfo data) {
144       do_in_bta_thread(FROM_HERE, base::Bind(cb, data));
145     };
146 
147     auto bound_cb = base::Bind(cb_lambda, info_cb);
148 
149     do_in_avrcp_jni(base::Bind(&MediaInterface::GetSongInfo,
150                                base::Unretained(wrapped_), bound_cb));
151   }
152 
GetPlayStatus(PlayStatusCallback status_cb)153   void GetPlayStatus(PlayStatusCallback status_cb) override {
154     auto cb_lambda = [](PlayStatusCallback cb, PlayStatus status) {
155       do_in_bta_thread(FROM_HERE, base::Bind(cb, status));
156     };
157 
158     auto bound_cb = base::Bind(cb_lambda, status_cb);
159 
160     do_in_avrcp_jni(base::Bind(&MediaInterface::GetPlayStatus,
161                                base::Unretained(wrapped_), bound_cb));
162   }
163 
GetNowPlayingList(NowPlayingCallback now_playing_cb)164   void GetNowPlayingList(NowPlayingCallback now_playing_cb) override {
165     auto cb_lambda = [](NowPlayingCallback cb, std::string curr_media_id,
166                         std::vector<SongInfo> song_list) {
167       do_in_bta_thread(FROM_HERE,
168                        base::Bind(cb, curr_media_id, std::move(song_list)));
169     };
170 
171     auto bound_cb = base::Bind(cb_lambda, now_playing_cb);
172 
173     do_in_avrcp_jni(base::Bind(&MediaInterface::GetNowPlayingList,
174                                base::Unretained(wrapped_), bound_cb));
175   }
176 
GetMediaPlayerList(MediaListCallback list_cb)177   void GetMediaPlayerList(MediaListCallback list_cb) override {
178     auto cb_lambda = [](MediaListCallback cb, uint16_t curr_player,
179                         std::vector<MediaPlayerInfo> player_list) {
180       do_in_bta_thread(FROM_HERE,
181                        base::Bind(cb, curr_player, std::move(player_list)));
182     };
183 
184     auto bound_cb = base::Bind(cb_lambda, list_cb);
185 
186     do_in_avrcp_jni(base::Bind(&MediaInterface::GetMediaPlayerList,
187                                base::Unretained(wrapped_), bound_cb));
188   }
189 
GetFolderItems(uint16_t player_id,std::string media_id,FolderItemsCallback folder_cb)190   void GetFolderItems(uint16_t player_id, std::string media_id,
191                       FolderItemsCallback folder_cb) override {
192     auto cb_lambda = [](FolderItemsCallback cb,
193                         std::vector<ListItem> item_list) {
194       do_in_bta_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
195     };
196 
197     auto bound_cb = base::Bind(cb_lambda, folder_cb);
198 
199     do_in_avrcp_jni(base::Bind(&MediaInterface::GetFolderItems,
200                                base::Unretained(wrapped_), player_id, media_id,
201                                bound_cb));
202   }
203 
SetBrowsedPlayer(uint16_t player_id,SetBrowsedPlayerCallback browse_cb)204   void SetBrowsedPlayer(uint16_t player_id,
205                         SetBrowsedPlayerCallback browse_cb) override {
206     auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success,
207                         std::string root_id, uint32_t num_items) {
208       do_in_bta_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
209     };
210 
211     auto bound_cb = base::Bind(cb_lambda, browse_cb);
212 
213     do_in_avrcp_jni(base::Bind(&MediaInterface::SetBrowsedPlayer,
214                                base::Unretained(wrapped_), player_id,
215                                bound_cb));
216   }
217 
PlayItem(uint16_t player_id,bool now_playing,std::string media_id)218   void PlayItem(uint16_t player_id, bool now_playing,
219                 std::string media_id) override {
220     do_in_avrcp_jni(base::Bind(&MediaInterface::PlayItem,
221                                base::Unretained(wrapped_), player_id,
222                                now_playing, media_id));
223   }
224 
SetActiveDevice(const RawAddress & address)225   void SetActiveDevice(const RawAddress& address) override {
226     do_in_avrcp_jni(base::Bind(&MediaInterface::SetActiveDevice,
227                                base::Unretained(wrapped_), address));
228   }
229 
RegisterUpdateCallback(MediaCallbacks * callback)230   void RegisterUpdateCallback(MediaCallbacks* callback) override {
231     wrapped_->RegisterUpdateCallback(callback);
232   }
233 
UnregisterUpdateCallback(MediaCallbacks * callback)234   void UnregisterUpdateCallback(MediaCallbacks* callback) override {
235     wrapped_->UnregisterUpdateCallback(callback);
236   }
237 
238  private:
239   MediaInterface* wrapped_;
240 };
241 
242 // A wrapper class for the media callbacks that handles thread
243 // switching/synchronization so the devices don't have to worry about it.
244 class VolumeInterfaceWrapper : public VolumeInterface {
245  public:
VolumeInterfaceWrapper(VolumeInterface * interface)246   VolumeInterfaceWrapper(VolumeInterface* interface) : wrapped_(interface){};
247 
DeviceConnected(const RawAddress & bdaddr)248   void DeviceConnected(const RawAddress& bdaddr) override {
249     do_in_avrcp_jni(
250         base::Bind(static_cast<void (VolumeInterface::*)(const RawAddress&)>(
251                        &VolumeInterface::DeviceConnected),
252                    base::Unretained(wrapped_), bdaddr));
253   }
254 
DeviceConnected(const RawAddress & bdaddr,VolumeChangedCb cb)255   void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) override {
256     auto cb_lambda = [](VolumeChangedCb cb, int8_t volume) {
257       do_in_bta_thread(FROM_HERE, base::Bind(cb, volume));
258     };
259 
260     auto bound_cb = base::Bind(cb_lambda, cb);
261 
262     do_in_avrcp_jni(base::Bind(static_cast<void (VolumeInterface::*)(
263                                    const RawAddress&, VolumeChangedCb)>(
264                                    &VolumeInterface::DeviceConnected),
265                                base::Unretained(wrapped_), bdaddr, bound_cb));
266   }
267 
DeviceDisconnected(const RawAddress & bdaddr)268   void DeviceDisconnected(const RawAddress& bdaddr) override {
269     do_in_avrcp_jni(base::Bind(&VolumeInterface::DeviceDisconnected,
270                                base::Unretained(wrapped_), bdaddr));
271   }
272 
SetVolume(int8_t volume)273   void SetVolume(int8_t volume) override {
274     do_in_avrcp_jni(base::Bind(&VolumeInterface::SetVolume,
275                                base::Unretained(wrapped_), volume));
276   }
277 
278  private:
279   VolumeInterface* wrapped_;
280 };
281 
Init(MediaInterface * media_interface,VolumeInterface * volume_interface)282 void AvrcpService::Init(MediaInterface* media_interface,
283                         VolumeInterface* volume_interface) {
284   LOG(INFO) << "AVRCP Target Service started";
285 
286   // TODO (apanicke): Add a function that sets up the SDP records once we
287   // remove the AVRCP SDP setup in AVDTP (bta_av_main.cc)
288 
289   media_interface_ = new MediaInterfaceWrapper(media_interface);
290   media_interface->RegisterUpdateCallback(instance_);
291 
292   VolumeInterfaceWrapper* wrapped_volume_interface = nullptr;
293   if (volume_interface != nullptr) {
294     wrapped_volume_interface = new VolumeInterfaceWrapper(volume_interface);
295   }
296 
297   volume_interface_ = wrapped_volume_interface;
298 
299   ConnectionHandler::Initialize(
300       base::Bind(&AvrcpService::DeviceCallback, base::Unretained(instance_)),
301       &avrcp_interface_, &sdp_interface_, wrapped_volume_interface);
302   connection_handler_ = ConnectionHandler::Get();
303 }
304 
Cleanup()305 void AvrcpService::Cleanup() {
306   LOG(INFO) << "AVRCP Target Service stopped";
307 
308   connection_handler_->CleanUp();
309   connection_handler_ = nullptr;
310   if (volume_interface_ != nullptr) {
311     delete volume_interface_;
312   }
313   delete media_interface_;
314 }
315 
Get()316 AvrcpService* AvrcpService::Get() {
317   CHECK(instance_);
318   return instance_;
319 }
320 
GetServiceInterface()321 ServiceInterface* AvrcpService::GetServiceInterface() {
322   if (service_interface_ == nullptr) {
323     service_interface_ = new ServiceInterfaceImpl();
324   }
325 
326   return service_interface_;
327 }
328 
ConnectDevice(const RawAddress & bdaddr)329 void AvrcpService::ConnectDevice(const RawAddress& bdaddr) {
330   LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
331 
332   connection_handler_->ConnectDevice(bdaddr);
333 }
334 
DisconnectDevice(const RawAddress & bdaddr)335 void AvrcpService::DisconnectDevice(const RawAddress& bdaddr) {
336   LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
337   connection_handler_->DisconnectDevice(bdaddr);
338 }
339 
SendMediaUpdate(bool track_changed,bool play_state,bool queue)340 void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
341                                    bool queue) {
342   LOG(INFO) << __PRETTY_FUNCTION__ << " track_changed=" << track_changed
343             << " : "
344             << " play_state=" << play_state << " : "
345             << " queue=" << queue;
346 
347   // This function may be called on any thread, we need to make sure that the
348   // device update happens on the main thread.
349   for (auto device : instance_->connection_handler_->GetListOfDevices()) {
350     do_in_bta_thread(FROM_HERE, base::Bind(&Device::SendMediaUpdate,
351                                            base::Unretained(device.get()),
352                                            track_changed, play_state, queue));
353   }
354 }
355 
SendFolderUpdate(bool available_players,bool addressed_players,bool uids)356 void AvrcpService::SendFolderUpdate(bool available_players,
357                                     bool addressed_players, bool uids) {
358   LOG(INFO) << __PRETTY_FUNCTION__ << " available_players=" << available_players
359             << " : "
360             << " addressed_players=" << addressed_players << " : "
361             << " uids=" << uids;
362 
363   // Ensure that the update is posted to the correct thread
364   for (auto device : instance_->connection_handler_->GetListOfDevices()) {
365     do_in_bta_thread(
366         FROM_HERE,
367         base::Bind(&Device::SendFolderUpdate, base::Unretained(device.get()),
368                    available_players, addressed_players, uids));
369   }
370 }
371 
372 // Send out the track changed info to update the playback state for each device
SendActiveDeviceChanged(const RawAddress & address)373 void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) {
374   SendMediaUpdate(false, true, false);
375 }
376 
DeviceCallback(std::shared_ptr<Device> new_device)377 void AvrcpService::DeviceCallback(std::shared_ptr<Device> new_device) {
378   if (new_device == nullptr) return;
379 
380   // TODO (apanicke): Pass the interfaces into the connection handler
381   // so that the devices can be created with any interfaces they need.
382   new_device->RegisterInterfaces(media_interface_, &a2dp_interface_,
383                                  volume_interface_);
384 }
385 
386 // Service Interface
Init(MediaInterface * media_interface,VolumeInterface * volume_interface)387 void AvrcpService::ServiceInterfaceImpl::Init(
388     MediaInterface* media_interface, VolumeInterface* volume_interface) {
389   std::lock_guard<std::mutex> lock(service_interface_lock_);
390 
391   // TODO: This function should block until the service is completely up so
392   // that its possible to call Get() on the service immediately after calling
393   // init without issues.
394 
395   CHECK(instance_ == nullptr);
396   instance_ = new AvrcpService();
397 
398   {
399     std::lock_guard<std::mutex> jni_lock(jni_mutex_);
400     jni_message_loop_ = get_jni_message_loop();
401   }
402 
403   do_in_bta_thread(FROM_HERE,
404                    base::Bind(&AvrcpService::Init, base::Unretained(instance_),
405                               media_interface, volume_interface));
406 }
407 
ConnectDevice(const RawAddress & bdaddr)408 bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
409     const RawAddress& bdaddr) {
410   std::lock_guard<std::mutex> lock(service_interface_lock_);
411   CHECK(instance_ != nullptr);
412   do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
413                                          base::Unretained(instance_), bdaddr));
414   return true;
415 }
416 
DisconnectDevice(const RawAddress & bdaddr)417 bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
418     const RawAddress& bdaddr) {
419   std::lock_guard<std::mutex> lock(service_interface_lock_);
420   CHECK(instance_ != nullptr);
421   do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
422                                          base::Unretained(instance_), bdaddr));
423   return true;
424 }
425 
Cleanup()426 bool AvrcpService::ServiceInterfaceImpl::Cleanup() {
427   std::lock_guard<std::mutex> lock(service_interface_lock_);
428 
429   if (instance_ == nullptr) return false;
430 
431   {
432     std::lock_guard<std::mutex> jni_lock(jni_mutex_);
433     task_tracker_.TryCancelAll();
434     jni_message_loop_ = nullptr;
435   }
436 
437   do_in_bta_thread(FROM_HERE,
438                    base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));
439 
440   // Setting instance to nullptr here is fine since it will be deleted on the
441   // other thread.
442   instance_ = nullptr;
443 
444   return true;
445 }
446 
DebugDump(int fd)447 void AvrcpService::DebugDump(int fd) {
448   if (instance_ == nullptr) {
449     dprintf(fd, "\nAVRCP Target Service not started\n");
450     return;
451   }
452 
453   auto device_list = instance_->connection_handler_->GetListOfDevices();
454   dprintf(fd, "\nAVRCP Target Native Service: %zu devices\n",
455           device_list.size());
456 
457   std::stringstream stream;
458   for (auto device : device_list) {
459     stream << *device << std::endl;
460   }
461   dprintf(fd, "%s", stream.str().c_str());
462 }
463 
464 }  // namespace avrcp
465 }  // namespace bluetooth