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