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