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