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