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