• 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 
24 #include <mutex>
25 #include <sstream>
26 
27 #include "abstract_message_loop.h"
28 #include "bta/sys/bta_sys.h"
29 #include "btif_av.h"
30 #include "btif_common.h"
31 #include "btif_dm.h"
32 #include "device.h"
33 #include "stack/include/bt_hdr.h"
34 #include "stack/include/btu.h"
35 #include "types/bluetooth/uuid.h"
36 #include "types/raw_address.h"
37 
38 namespace bluetooth {
39 namespace avrcp {
40 // Static variables and interface definitions
41 AvrcpService* AvrcpService::instance_ = nullptr;
42 AvrcpService::ServiceInterfaceImpl* AvrcpService::service_interface_ = nullptr;
43 
do_in_avrcp_jni(const base::Closure & task)44 void do_in_avrcp_jni(const base::Closure& task) {
45   do_in_jni_thread(FROM_HERE, task);
46 }
47 
48 class A2dpInterfaceImpl : public A2dpInterface {
active_peer()49   RawAddress active_peer() override { return btif_av_source_active_peer(); }
50 
is_peer_in_silence_mode(const RawAddress & peer_address)51   bool is_peer_in_silence_mode(const RawAddress& peer_address) override {
52     return btif_av_is_peer_silenced(peer_address);
53   }
54 } a2dp_interface_;
55 
56 class AvrcpInterfaceImpl : public AvrcpInterface {
57  public:
GetAvrcpVersion()58   uint16_t GetAvrcpVersion() {
59     return AVRC_GetProfileVersion();
60   }
61 
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,uint16_t cover_art_psm)62   uint16_t AddRecord(uint16_t service_uuid, const char* p_service_name,
63                      const char* p_provider_name, uint16_t categories,
64                      uint32_t sdp_handle, bool browse_supported,
65                      uint16_t profile_version,
66                      uint16_t cover_art_psm) override {
67     return AVRC_AddRecord(service_uuid, p_service_name, p_provider_name,
68                           categories, sdp_handle, browse_supported,
69                           profile_version, cover_art_psm);
70   }
71 
RemoveRecord(uint32_t sdp_handle)72   uint16_t RemoveRecord(uint32_t sdp_handle) {
73     return AVRC_RemoveRecord(sdp_handle);
74   }
75 
FindService(uint16_t service_uuid,const RawAddress & bd_addr,tAVRC_SDP_DB_PARAMS * p_db,tAVRC_FIND_CBACK p_cback)76   uint16_t FindService(uint16_t service_uuid, const RawAddress& bd_addr,
77                        tAVRC_SDP_DB_PARAMS* p_db,
78                        tAVRC_FIND_CBACK p_cback) override {
79     return AVRC_FindService(service_uuid, bd_addr, p_db, p_cback);
80   }
81 
Open(uint8_t * p_handle,tAVRC_CONN_CB * p_ccb,const RawAddress & bd_addr)82   uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb,
83                 const RawAddress& bd_addr) override {
84     return AVRC_Open(p_handle, p_ccb, bd_addr);
85   }
86 
OpenBrowse(uint8_t handle,uint8_t conn_role)87   uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) override {
88     return AVRC_OpenBrowse(handle, conn_role);
89   }
90 
GetPeerMtu(uint8_t handle)91   uint16_t GetPeerMtu(uint8_t handle) override {
92     return AVCT_GetPeerMtu(handle);
93   }
94 
GetBrowseMtu(uint8_t handle)95   uint16_t GetBrowseMtu(uint8_t handle) override {
96     return AVCT_GetBrowseMtu(handle);
97   }
98 
Close(uint8_t handle)99   uint16_t Close(uint8_t handle) override { return AVRC_Close(handle); }
100 
CloseBrowse(uint8_t handle)101   uint16_t CloseBrowse(uint8_t handle) override {
102     return AVRC_CloseBrowse(handle);
103   }
104 
MsgReq(uint8_t handle,uint8_t label,uint8_t ctype,BT_HDR * p_pkt)105   uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
106                   BT_HDR* p_pkt) override {
107     return AVRC_MsgReq(handle, label, ctype, p_pkt);
108   }
109 
SaveControllerVersion(const RawAddress & bdaddr,uint16_t version)110   void SaveControllerVersion(const RawAddress& bdaddr,
111                              uint16_t version) override {
112     AVRC_SaveControllerVersion(bdaddr, version);
113   }
114 
115 } avrcp_interface_;
116 
117 class SdpInterfaceImpl : public SdpInterface {
118  public:
InitDiscoveryDb(tSDP_DISCOVERY_DB * a,uint32_t b,uint16_t c,const bluetooth::Uuid * d,uint16_t e,uint16_t * f)119   bool InitDiscoveryDb(tSDP_DISCOVERY_DB* a, uint32_t b, uint16_t c,
120                        const bluetooth::Uuid* d, uint16_t e,
121                        uint16_t* f) override {
122     return SDP_InitDiscoveryDb(a, b, c, d, e, f);
123   }
124 
ServiceSearchAttributeRequest(const RawAddress & a,tSDP_DISCOVERY_DB * b,tSDP_DISC_CMPL_CB * c)125   bool ServiceSearchAttributeRequest(const RawAddress& a, tSDP_DISCOVERY_DB* b,
126                                      tSDP_DISC_CMPL_CB* c) override {
127     return SDP_ServiceSearchAttributeRequest(a, b, c);
128   }
129 
FindServiceInDb(tSDP_DISCOVERY_DB * a,uint16_t b,t_sdp_disc_rec * c)130   tSDP_DISC_REC* FindServiceInDb(tSDP_DISCOVERY_DB* a, uint16_t b,
131                                  t_sdp_disc_rec* c) override {
132     return SDP_FindServiceInDb(a, b, c);
133   }
134 
FindAttributeInRec(t_sdp_disc_rec * a,uint16_t b)135   tSDP_DISC_ATTR* FindAttributeInRec(t_sdp_disc_rec* a, uint16_t b) override {
136     return SDP_FindAttributeInRec(a, b);
137   }
138 
FindProfileVersionInRec(t_sdp_disc_rec * a,uint16_t b,uint16_t * c)139   bool FindProfileVersionInRec(t_sdp_disc_rec* a, uint16_t b,
140                                uint16_t* c) override {
141     return SDP_FindProfileVersionInRec(a, b, c);
142   }
143 } sdp_interface_;
144 
145 // A wrapper class for the media callbacks that handles thread
146 // switching/synchronization so the devices don't have to worry about it.
147 class MediaInterfaceWrapper : public MediaInterface {
148  public:
MediaInterfaceWrapper(MediaInterface * cb)149   MediaInterfaceWrapper(MediaInterface* cb) : wrapped_(cb){};
150 
SendKeyEvent(uint8_t key,KeyState state)151   void SendKeyEvent(uint8_t key, KeyState state) override {
152     do_in_avrcp_jni(base::Bind(&MediaInterface::SendKeyEvent,
153                                base::Unretained(wrapped_), key, state));
154   }
155 
GetSongInfo(SongInfoCallback info_cb)156   void GetSongInfo(SongInfoCallback info_cb) override {
157     auto cb_lambda = [](SongInfoCallback cb, SongInfo data) {
158       do_in_main_thread(FROM_HERE, base::Bind(cb, data));
159     };
160 
161     auto bound_cb = base::Bind(cb_lambda, info_cb);
162 
163     do_in_avrcp_jni(base::Bind(&MediaInterface::GetSongInfo,
164                                base::Unretained(wrapped_), bound_cb));
165   }
166 
GetPlayStatus(PlayStatusCallback status_cb)167   void GetPlayStatus(PlayStatusCallback status_cb) override {
168     auto cb_lambda = [](PlayStatusCallback cb, PlayStatus status) {
169       do_in_main_thread(FROM_HERE, base::Bind(cb, status));
170     };
171 
172     auto bound_cb = base::Bind(cb_lambda, status_cb);
173 
174     do_in_avrcp_jni(base::Bind(&MediaInterface::GetPlayStatus,
175                                base::Unretained(wrapped_), bound_cb));
176   }
177 
GetNowPlayingList(NowPlayingCallback now_playing_cb)178   void GetNowPlayingList(NowPlayingCallback now_playing_cb) override {
179     auto cb_lambda = [](NowPlayingCallback cb, std::string curr_media_id,
180                         std::vector<SongInfo> song_list) {
181       do_in_main_thread(FROM_HERE,
182                         base::Bind(cb, curr_media_id, std::move(song_list)));
183     };
184 
185     auto bound_cb = base::Bind(cb_lambda, now_playing_cb);
186 
187     do_in_avrcp_jni(base::Bind(&MediaInterface::GetNowPlayingList,
188                                base::Unretained(wrapped_), bound_cb));
189   }
190 
GetMediaPlayerList(MediaListCallback list_cb)191   void GetMediaPlayerList(MediaListCallback list_cb) override {
192     auto cb_lambda = [](MediaListCallback cb, uint16_t curr_player,
193                         std::vector<MediaPlayerInfo> player_list) {
194       do_in_main_thread(FROM_HERE,
195                         base::Bind(cb, curr_player, std::move(player_list)));
196     };
197 
198     auto bound_cb = base::Bind(cb_lambda, list_cb);
199 
200     do_in_avrcp_jni(base::Bind(&MediaInterface::GetMediaPlayerList,
201                                base::Unretained(wrapped_), bound_cb));
202   }
203 
GetFolderItems(uint16_t player_id,std::string media_id,FolderItemsCallback folder_cb)204   void GetFolderItems(uint16_t player_id, std::string media_id,
205                       FolderItemsCallback folder_cb) override {
206     auto cb_lambda = [](FolderItemsCallback cb,
207                         std::vector<ListItem> item_list) {
208       do_in_main_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
209     };
210 
211     auto bound_cb = base::Bind(cb_lambda, folder_cb);
212 
213     do_in_avrcp_jni(base::Bind(&MediaInterface::GetFolderItems,
214                                base::Unretained(wrapped_), player_id, media_id,
215                                bound_cb));
216   }
217 
SetBrowsedPlayer(uint16_t player_id,SetBrowsedPlayerCallback browse_cb)218   void SetBrowsedPlayer(uint16_t player_id,
219                         SetBrowsedPlayerCallback browse_cb) override {
220     auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success,
221                         std::string root_id, uint32_t num_items) {
222       do_in_main_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
223     };
224 
225     auto bound_cb = base::Bind(cb_lambda, browse_cb);
226 
227     do_in_avrcp_jni(base::Bind(&MediaInterface::SetBrowsedPlayer,
228                                base::Unretained(wrapped_), player_id,
229                                bound_cb));
230   }
231 
PlayItem(uint16_t player_id,bool now_playing,std::string media_id)232   void PlayItem(uint16_t player_id, bool now_playing,
233                 std::string media_id) override {
234     do_in_avrcp_jni(base::Bind(&MediaInterface::PlayItem,
235                                base::Unretained(wrapped_), player_id,
236                                now_playing, media_id));
237   }
238 
SetActiveDevice(const RawAddress & address)239   void SetActiveDevice(const RawAddress& address) override {
240     do_in_avrcp_jni(base::Bind(&MediaInterface::SetActiveDevice,
241                                base::Unretained(wrapped_), address));
242   }
243 
RegisterUpdateCallback(MediaCallbacks * callback)244   void RegisterUpdateCallback(MediaCallbacks* callback) override {
245     wrapped_->RegisterUpdateCallback(callback);
246   }
247 
UnregisterUpdateCallback(MediaCallbacks * callback)248   void UnregisterUpdateCallback(MediaCallbacks* callback) override {
249     wrapped_->UnregisterUpdateCallback(callback);
250   }
251 
252  private:
253   MediaInterface* wrapped_;
254 };
255 
256 // A wrapper class for the media callbacks that handles thread
257 // switching/synchronization so the devices don't have to worry about it.
258 class VolumeInterfaceWrapper : public VolumeInterface {
259  public:
VolumeInterfaceWrapper(VolumeInterface * interface)260   VolumeInterfaceWrapper(VolumeInterface* interface) : wrapped_(interface){};
261 
DeviceConnected(const RawAddress & bdaddr)262   void DeviceConnected(const RawAddress& bdaddr) override {
263     do_in_avrcp_jni(
264         base::Bind(static_cast<void (VolumeInterface::*)(const RawAddress&)>(
265                        &VolumeInterface::DeviceConnected),
266                    base::Unretained(wrapped_), bdaddr));
267   }
268 
DeviceConnected(const RawAddress & bdaddr,VolumeChangedCb cb)269   void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) override {
270     auto cb_lambda = [](VolumeChangedCb cb, int8_t volume) {
271       do_in_main_thread(FROM_HERE, base::Bind(cb, volume));
272     };
273 
274     auto bound_cb = base::Bind(cb_lambda, cb);
275 
276     do_in_avrcp_jni(base::Bind(static_cast<void (VolumeInterface::*)(
277                                    const RawAddress&, VolumeChangedCb)>(
278                                    &VolumeInterface::DeviceConnected),
279                                base::Unretained(wrapped_), bdaddr, bound_cb));
280   }
281 
DeviceDisconnected(const RawAddress & bdaddr)282   void DeviceDisconnected(const RawAddress& bdaddr) override {
283     do_in_avrcp_jni(base::Bind(&VolumeInterface::DeviceDisconnected,
284                                base::Unretained(wrapped_), bdaddr));
285   }
286 
SetVolume(int8_t volume)287   void SetVolume(int8_t volume) override {
288     do_in_avrcp_jni(base::Bind(&VolumeInterface::SetVolume,
289                                base::Unretained(wrapped_), volume));
290   }
291 
292  private:
293   VolumeInterface* wrapped_;
294 };
295 
Init(MediaInterface * media_interface,VolumeInterface * volume_interface)296 void AvrcpService::Init(MediaInterface* media_interface,
297                         VolumeInterface* volume_interface) {
298   LOG(INFO) << "AVRCP Target Service started";
299 
300   profile_version = avrcp_interface_.GetAvrcpVersion();
301 
302   uint16_t supported_features = GetSupportedFeatures(profile_version);
303   sdp_record_handle = SDP_CreateRecord();
304 
305   avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
306                              "AV Remote Control Target", NULL,
307                              supported_features, sdp_record_handle, true,
308                              profile_version, 0);
309   bta_sys_add_uuid(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
310 
311   ct_sdp_record_handle = SDP_CreateRecord();
312 
313   avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REMOTE_CONTROL,
314                              "AV Remote Control", NULL, AVRCP_SUPF_TG_CT,
315                              ct_sdp_record_handle, false, AVRC_REV_1_3, 0);
316   bta_sys_add_uuid(UUID_SERVCLASS_AV_REMOTE_CONTROL);
317 
318   media_interface_ = new MediaInterfaceWrapper(media_interface);
319   media_interface->RegisterUpdateCallback(instance_);
320 
321   VolumeInterfaceWrapper* wrapped_volume_interface = nullptr;
322   if (volume_interface != nullptr) {
323     wrapped_volume_interface = new VolumeInterfaceWrapper(volume_interface);
324   }
325 
326   volume_interface_ = wrapped_volume_interface;
327 
328   ConnectionHandler::Initialize(
329       base::Bind(&AvrcpService::DeviceCallback, base::Unretained(instance_)),
330       &avrcp_interface_, &sdp_interface_, wrapped_volume_interface);
331   connection_handler_ = ConnectionHandler::Get();
332 }
333 
GetSupportedFeatures(uint16_t profile_version)334 uint16_t AvrcpService::GetSupportedFeatures(uint16_t profile_version) {
335   switch (profile_version) {
336     case AVRC_REV_1_6:
337       return AVRCP_SUPF_TG_1_6;
338     case AVRC_REV_1_5:
339       return AVRCP_SUPF_TG_1_5;
340     case AVRC_REV_1_4:
341       return AVRCP_SUPF_TG_1_4;
342     case AVRC_REV_1_3:
343       return AVRCP_SUPF_TG_1_3;
344   }
345   return AVRCP_SUPF_TG_DEFAULT;
346 }
347 
Cleanup()348 void AvrcpService::Cleanup() {
349   LOG(INFO) << "AVRCP Target Service stopped";
350 
351   avrcp_interface_.RemoveRecord(sdp_record_handle);
352   bta_sys_remove_uuid(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
353   sdp_record_handle = -1;
354   avrcp_interface_.RemoveRecord(ct_sdp_record_handle);
355   bta_sys_remove_uuid(UUID_SERVCLASS_AV_REMOTE_CONTROL);
356   ct_sdp_record_handle = -1;
357 
358   connection_handler_->CleanUp();
359   connection_handler_ = nullptr;
360   if (volume_interface_ != nullptr) {
361     delete volume_interface_;
362   }
363   delete media_interface_;
364 }
365 
RegisterBipServer(int psm)366 void AvrcpService::RegisterBipServer(int psm) {
367   LOG(INFO) << "AVRCP Target Service has registered a BIP OBEX server, psm="
368             << psm;
369   avrcp_interface_.RemoveRecord(sdp_record_handle);
370   uint16_t supported_features
371       = GetSupportedFeatures(profile_version) | AVRC_SUPF_TG_PLAYER_COVER_ART;
372   sdp_record_handle = SDP_CreateRecord();
373   avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
374                              "AV Remote Control Target", NULL,
375                              supported_features, sdp_record_handle, true,
376                              profile_version, psm);
377 }
378 
UnregisterBipServer()379 void AvrcpService::UnregisterBipServer() {
380   LOG(INFO) << "AVRCP Target Service has unregistered a BIP OBEX server";
381   avrcp_interface_.RemoveRecord(sdp_record_handle);
382   uint16_t supported_features = GetSupportedFeatures(profile_version);
383   sdp_record_handle = SDP_CreateRecord();
384   avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
385                              "AV Remote Control Target", NULL,
386                              supported_features, sdp_record_handle, true,
387                              profile_version, 0);
388 }
389 
Get()390 AvrcpService* AvrcpService::Get() {
391   CHECK(instance_);
392   return instance_;
393 }
394 
GetServiceInterface()395 ServiceInterface* AvrcpService::GetServiceInterface() {
396   if (service_interface_ == nullptr) {
397     service_interface_ = new ServiceInterfaceImpl();
398   }
399 
400   return service_interface_;
401 }
402 
ConnectDevice(const RawAddress & bdaddr)403 void AvrcpService::ConnectDevice(const RawAddress& bdaddr) {
404   LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
405 
406   connection_handler_->ConnectDevice(bdaddr);
407 }
408 
DisconnectDevice(const RawAddress & bdaddr)409 void AvrcpService::DisconnectDevice(const RawAddress& bdaddr) {
410   LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
411   connection_handler_->DisconnectDevice(bdaddr);
412 }
413 
SetBipClientStatus(const RawAddress & bdaddr,bool connected)414 void AvrcpService::SetBipClientStatus(const RawAddress& bdaddr,
415                                       bool connected) {
416   LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString()
417             << ", connected=" << connected;
418   connection_handler_->SetBipClientStatus(bdaddr, connected);
419 }
420 
SendMediaUpdate(bool track_changed,bool play_state,bool queue)421 void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
422                                    bool queue) {
423   LOG(INFO) << __PRETTY_FUNCTION__ << " track_changed=" << track_changed
424             << " : "
425             << " play_state=" << play_state << " : "
426             << " queue=" << queue;
427 
428   // This function may be called on any thread, we need to make sure that the
429   // device update happens on the main thread.
430   for (const auto& device :
431        instance_->connection_handler_->GetListOfDevices()) {
432     do_in_main_thread(FROM_HERE,
433                       base::Bind(&Device::SendMediaUpdate, device.get()->Get(), track_changed, play_state, queue));
434   }
435 }
436 
SendFolderUpdate(bool available_players,bool addressed_players,bool uids)437 void AvrcpService::SendFolderUpdate(bool available_players,
438                                     bool addressed_players, bool uids) {
439   LOG(INFO) << __PRETTY_FUNCTION__ << " available_players=" << available_players
440             << " : "
441             << " addressed_players=" << addressed_players << " : "
442             << " uids=" << uids;
443 
444   // Ensure that the update is posted to the correct thread
445   for (const auto& device :
446        instance_->connection_handler_->GetListOfDevices()) {
447     do_in_main_thread(FROM_HERE, base::Bind(&Device::SendFolderUpdate, device.get()->Get(), available_players,
448                                             addressed_players, uids));
449   }
450 }
451 
452 // Send out the track changed info to update the playback state for each device
SendActiveDeviceChanged(const RawAddress & address)453 void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) {
454   SendMediaUpdate(false, true, false);
455 }
456 
DeviceCallback(std::shared_ptr<Device> new_device)457 void AvrcpService::DeviceCallback(std::shared_ptr<Device> new_device) {
458   if (new_device == nullptr) return;
459 
460   // TODO (apanicke): Pass the interfaces into the connection handler
461   // so that the devices can be created with any interfaces they need.
462   new_device->RegisterInterfaces(media_interface_, &a2dp_interface_,
463                                  volume_interface_);
464 }
465 
466 // Service Interface
Init(MediaInterface * media_interface,VolumeInterface * volume_interface)467 void AvrcpService::ServiceInterfaceImpl::Init(
468     MediaInterface* media_interface, VolumeInterface* volume_interface) {
469   std::lock_guard<std::mutex> lock(service_interface_lock_);
470 
471   // TODO: This function should block until the service is completely up so
472   // that its possible to call Get() on the service immediately after calling
473   // init without issues.
474 
475   CHECK(instance_ == nullptr);
476   instance_ = new AvrcpService();
477 
478   do_in_main_thread(FROM_HERE,
479                     base::Bind(&AvrcpService::Init, base::Unretained(instance_),
480                                media_interface, volume_interface));
481 }
482 
RegisterBipServer(int psm)483 void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int psm) {
484   std::lock_guard<std::mutex> lock(service_interface_lock_);
485   CHECK(instance_ != nullptr);
486   do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::RegisterBipServer,
487                                           base::Unretained(instance_), psm));
488 }
489 
UnregisterBipServer()490 void AvrcpService::ServiceInterfaceImpl::UnregisterBipServer() {
491   std::lock_guard<std::mutex> lock(service_interface_lock_);
492   CHECK(instance_ != nullptr);
493   do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::UnregisterBipServer,
494                                           base::Unretained(instance_)));
495 }
496 
ConnectDevice(const RawAddress & bdaddr)497 bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
498     const RawAddress& bdaddr) {
499   std::lock_guard<std::mutex> lock(service_interface_lock_);
500   CHECK(instance_ != nullptr);
501   do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
502                                           base::Unretained(instance_), bdaddr));
503   return true;
504 }
505 
DisconnectDevice(const RawAddress & bdaddr)506 bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
507     const RawAddress& bdaddr) {
508   std::lock_guard<std::mutex> lock(service_interface_lock_);
509   CHECK(instance_ != nullptr);
510   do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
511                                           base::Unretained(instance_), bdaddr));
512   return true;
513 }
514 
SetBipClientStatus(const RawAddress & bdaddr,bool connected)515 void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(
516     const RawAddress& bdaddr, bool connected) {
517   std::lock_guard<std::mutex> lock(service_interface_lock_);
518   CHECK(instance_ != nullptr);
519   do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::SetBipClientStatus,
520                                           base::Unretained(instance_), bdaddr,
521                                           connected));
522 }
523 
Cleanup()524 bool AvrcpService::ServiceInterfaceImpl::Cleanup() {
525   std::lock_guard<std::mutex> lock(service_interface_lock_);
526 
527   if (instance_ == nullptr) return false;
528 
529   do_in_main_thread(FROM_HERE,
530                     base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));
531 
532   // Setting instance to nullptr here is fine since it will be deleted on the
533   // other thread.
534   instance_ = nullptr;
535 
536   return true;
537 }
538 
DebugDump(int fd)539 void AvrcpService::DebugDump(int fd) {
540   if (instance_ == nullptr) {
541     dprintf(fd, "\nAVRCP Target Service not started\n");
542     return;
543   }
544 
545   auto handler = instance_->connection_handler_;
546   if (handler == nullptr) {
547     dprintf(fd, "\nAVRCP connection handler is null\n");
548     return;
549   }
550 
551   auto device_list = handler->GetListOfDevices();
552   dprintf(fd, "\nAVRCP Target Native Service: %zu devices\n",
553           device_list.size());
554 
555   std::stringstream stream;
556   {
557     ScopedIndent indent(stream);
558     for (const auto& device : device_list) {
559       stream << *device << std::endl;
560     }
561   }
562 
563   dprintf(fd, "%s", stream.str().c_str());
564 }
565 
566 }  // namespace avrcp
567 }  // namespace bluetooth
568