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 #define LOG_TAG "avrcp"
18
19 #include "connection_handler.h"
20
21 #include <base/functional/bind.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24
25 #include <map>
26 #include <mutex>
27
28 #include "avrc_defs.h"
29 #include "avrcp_message_converter.h"
30 #include "bta/include/bta_av_api.h"
31 #include "device/include/interop.h"
32 #include "internal_include/bt_target.h"
33 #include "osi/include/allocator.h"
34 #include "osi/include/properties.h"
35 #include "packet/avrcp/avrcp_packet.h"
36 #include "stack/include/bt_hdr.h"
37 #include "stack/include/bt_uuid16.h"
38 #include "types/raw_address.h"
39
40 extern bool btif_av_peer_is_connected_sink(const RawAddress& peer_address);
41 extern bool btif_av_peer_is_connected_source(const RawAddress& peer_address);
42 extern bool btif_av_both_enable(void);
43 extern bool btif_av_src_sink_coexist_enabled(void);
44 extern bool btif_av_peer_is_source(const RawAddress& peer_address);
45
46 namespace bluetooth {
47 namespace avrcp {
48
49 ConnectionHandler* ConnectionHandler::instance_ = nullptr;
50
51 // ConnectionHandler::CleanUp take the lock and calls
52 // ConnectionHandler::AcceptorControlCB with AVRC_CLOSE_IND_EVT
53 // which also takes the lock, so use a recursive_mutex.
54 std::recursive_mutex device_map_lock;
55
Get()56 ConnectionHandler* ConnectionHandler::Get() {
57 log::assert_that(instance_ != nullptr, "assert failed: instance_ != nullptr");
58
59 return instance_;
60 }
61
IsAbsoluteVolumeEnabled(const RawAddress * bdaddr)62 bool IsAbsoluteVolumeEnabled(const RawAddress* bdaddr) {
63 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
64 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
65 if (strncmp(volume_disabled, "true", 4) == 0) {
66 log::info("Absolute volume disabled by property");
67 return false;
68 }
69 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, bdaddr)) {
70 log::info("Absolute volume disabled by IOP table");
71 return false;
72 }
73 return true;
74 }
75
Initialize(const ConnectionCallback & callback,AvrcpInterface * avrcp,SdpInterface * sdp,VolumeInterface * vol)76 bool ConnectionHandler::Initialize(const ConnectionCallback& callback,
77 AvrcpInterface* avrcp, SdpInterface* sdp,
78 VolumeInterface* vol) {
79 log::assert_that(instance_ == nullptr, "assert failed: instance_ == nullptr");
80 log::assert_that(avrcp != nullptr, "assert failed: avrcp != nullptr");
81 log::assert_that(sdp != nullptr, "assert failed: sdp != nullptr");
82
83 // TODO (apanicke): When transitioning to using this service, implement
84 // SDP Initialization for AVRCP Here.
85 instance_ = new ConnectionHandler();
86 instance_->connection_cb_ = callback;
87 instance_->avrc_ = avrcp;
88 instance_->sdp_ = sdp;
89 instance_->vol_ = vol;
90
91 // Set up the AVRCP acceptor connection
92 if (!instance_->AvrcpConnect(false, RawAddress::kAny)) {
93 instance_->CleanUp();
94 return false;
95 }
96
97 return true;
98 }
99
CleanUp()100 bool ConnectionHandler::CleanUp() {
101 log::assert_that(instance_ != nullptr, "assert failed: instance_ != nullptr");
102
103 // TODO (apanicke): Cleanup the SDP Entries here
104 std::lock_guard<std::recursive_mutex> lock(device_map_lock);
105 for (auto entry = instance_->device_map_.begin();
106 entry != instance_->device_map_.end();) {
107 auto curr = entry;
108 entry++;
109 curr->second->DeviceDisconnected();
110 instance_->avrc_->Close(curr->first);
111 }
112 instance_->device_map_.clear();
113 instance_->feature_map_.clear();
114
115 instance_->weak_ptr_factory_.InvalidateWeakPtrs();
116
117 delete instance_;
118 instance_ = nullptr;
119
120 return true;
121 }
122
InitForTesting(ConnectionHandler * handler)123 void ConnectionHandler::InitForTesting(ConnectionHandler* handler) {
124 log::assert_that(instance_ == nullptr, "assert failed: instance_ == nullptr");
125 instance_ = handler;
126 }
127
ConnectDevice(const RawAddress & bdaddr)128 bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) {
129 log::info("Attempting to connect to device {}", bdaddr);
130
131 for (const auto& pair : device_map_) {
132 if (bdaddr == pair.second->GetAddress()) {
133 log::warn("Already connected to device with address {}", bdaddr);
134 return false;
135 }
136 }
137
138 auto connection_lambda = [](ConnectionHandler* instance_,
139 const RawAddress& bdaddr, uint16_t status,
140 uint16_t version, uint16_t features) {
141 log::info("SDP Completed features=0x{:x}", features);
142 if (status != AVRC_SUCCESS || !(features & BTA_AV_FEAT_RCCT)) {
143 log::error(
144 "Failed to do SDP: status=0x{:x} features=0x{:x} supports "
145 "controller: {}",
146 status, features, features & BTA_AV_FEAT_RCCT);
147 instance_->connection_cb_.Run(std::shared_ptr<Device>());
148 }
149
150 instance_->feature_map_[bdaddr] = features;
151 instance_->AvrcpConnect(true, bdaddr);
152 return;
153 };
154
155 return SdpLookup(bdaddr, base::Bind(connection_lambda, this, bdaddr), false);
156 }
157
DisconnectDevice(const RawAddress & bdaddr)158 bool ConnectionHandler::DisconnectDevice(const RawAddress& bdaddr) {
159 for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
160 if (bdaddr == it->second->GetAddress()) {
161 uint8_t handle = it->first;
162 return avrc_->Close(handle) == AVRC_SUCCESS;
163 }
164 }
165
166 return false;
167 }
168
SetBipClientStatus(const RawAddress & bdaddr,bool connected)169 void ConnectionHandler::SetBipClientStatus(const RawAddress& bdaddr,
170 bool connected) {
171 for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
172 if (bdaddr == it->second->GetAddress()) {
173 it->second->SetBipClientStatus(connected);
174 return;
175 }
176 }
177 }
178
GetListOfDevices() const179 std::vector<std::shared_ptr<Device>> ConnectionHandler::GetListOfDevices()
180 const {
181 std::vector<std::shared_ptr<Device>> list;
182 std::lock_guard<std::recursive_mutex> lock(device_map_lock);
183 for (const auto& device : device_map_) {
184 list.push_back(device.second);
185 }
186 return list;
187 }
188
SdpLookup(const RawAddress & bdaddr,SdpCallback cb,bool retry)189 bool ConnectionHandler::SdpLookup(const RawAddress& bdaddr, SdpCallback cb,
190 bool retry) {
191 log::info("");
192
193 tAVRC_SDP_DB_PARAMS db_params;
194 // TODO (apanicke): This needs to be replaced with smarter memory management.
195 tSDP_DISCOVERY_DB* disc_db =
196 (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
197 uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
198 ATTR_ID_BT_PROFILE_DESC_LIST,
199 ATTR_ID_SUPPORTED_FEATURES};
200
201 db_params.db_len =
202 BT_DEFAULT_BUFFER_SIZE; // Some magic number found in the AVRCP code
203 db_params.num_attr = sizeof(attr_list) / sizeof(attr_list[0]);
204 db_params.p_db = disc_db;
205 db_params.p_attrs = attr_list;
206
207 return avrc_->FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, bdaddr,
208 &db_params,
209 base::Bind(&ConnectionHandler::SdpCb,
210 weak_ptr_factory_.GetWeakPtr(), bdaddr,
211 cb, disc_db, retry)) == AVRC_SUCCESS;
212 }
213
AvrcpConnect(bool initiator,const RawAddress & bdaddr)214 bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) {
215 log::info("Connect to device {}", bdaddr);
216
217 tAVRC_CONN_CB open_cb;
218 if (initiator) {
219 open_cb.ctrl_cback = base::Bind(&ConnectionHandler::InitiatorControlCb,
220 weak_ptr_factory_.GetWeakPtr());
221 } else {
222 open_cb.ctrl_cback = base::Bind(&ConnectionHandler::AcceptorControlCb,
223 weak_ptr_factory_.GetWeakPtr());
224 }
225 open_cb.msg_cback =
226 base::Bind(&ConnectionHandler::MessageCb, weak_ptr_factory_.GetWeakPtr());
227 open_cb.company_id = AVRC_CO_GOOGLE;
228 open_cb.conn = initiator ? AVRC_CONN_INT
229 : AVRC_CONN_ACP; // 0 if initiator, 1 if acceptor
230 // TODO (apanicke): We shouldn't need RCCT to do absolute volume. The current
231 // AVRC_API requires it though.
232 open_cb.control = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA |
233 AVRC_CT_PASSIVE;
234
235 uint8_t handle = 0;
236 uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr);
237 log::info("handle=0x{:x} status= 0x{:x}", handle, status);
238 return status == AVRC_SUCCESS;
239 }
240
InitiatorControlCb(uint8_t handle,uint8_t event,uint16_t result,const RawAddress * peer_addr)241 void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event,
242 uint16_t result,
243 const RawAddress* peer_addr) {
244 DCHECK(!connection_cb_.is_null());
245
246 log::info("handle=0x{:x} result=0x{:x} addr={}", handle, result,
247 peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none");
248
249 switch (event) {
250 case AVRC_OPEN_IND_EVT: {
251 log::info("Connection Opened Event");
252
253 const auto& feature_iter = feature_map_.find(*peer_addr);
254 if (feature_iter == feature_map_.end()) {
255 log::error(
256 "Features do not exist even though SDP should have been "
257 "done first");
258 return;
259 }
260
261 bool supports_browsing = feature_iter->second & BTA_AV_FEAT_BROWSE;
262
263 if (supports_browsing) {
264 avrc_->OpenBrowse(handle, AVCT_INT);
265 }
266
267 // TODO (apanicke): Implement a system to cache SDP entries. For most
268 // devices SDP is completed after the device connects AVRCP so that
269 // information isn't very useful when trying to control our
270 // capabilities. For now always use AVRCP 1.6.
271 auto&& callback = base::BindRepeating(&ConnectionHandler::SendMessage,
272 base::Unretained(this), handle);
273 auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
274 auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
275 std::shared_ptr<Device> newDevice = std::make_shared<Device>(
276 *peer_addr, !supports_browsing, callback, ctrl_mtu, browse_mtu);
277
278 device_map_[handle] = newDevice;
279 // TODO (apanicke): Create the device with all of the interfaces it
280 // needs. Return the new device where the service will register the
281 // interfaces it needs.
282 connection_cb_.Run(newDevice);
283
284 if (!btif_av_src_sink_coexist_enabled() ||
285 (btif_av_src_sink_coexist_enabled() &&
286 btif_av_peer_is_connected_sink(newDevice->GetAddress()))) {
287 if (feature_iter->second & BTA_AV_FEAT_ADV_CTRL) {
288 newDevice->RegisterVolumeChanged();
289 } else if (instance_->vol_ != nullptr) {
290 instance_->vol_->DeviceConnected(newDevice->GetAddress());
291 }
292 }
293
294 } break;
295
296 case AVRC_CLOSE_IND_EVT: {
297 log::info("Connection Closed Event");
298
299 if (device_map_.find(handle) == device_map_.end()) {
300 log::warn("Connection Close received from device that doesn't exist");
301 return;
302 }
303 std::lock_guard<std::recursive_mutex> lock(device_map_lock);
304 avrc_->Close(handle);
305 feature_map_.erase(device_map_[handle]->GetAddress());
306 device_map_[handle]->DeviceDisconnected();
307 device_map_.erase(handle);
308 } break;
309
310 case AVRC_BROWSE_OPEN_IND_EVT: {
311 log::info("Browse Open Event");
312 // NOTE (apanicke): We don't need to explicitly handle this message
313 // since the AVCTP Layer will still send us browsing messages
314 // regardless. It would be useful to note this though for future
315 // compatibility issues.
316 if (device_map_.find(handle) == device_map_.end()) {
317 log::warn("Browse Opened received from device that doesn't exist");
318 return;
319 }
320
321 auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
322 device_map_[handle]->SetBrowseMtu(browse_mtu);
323 } break;
324 case AVRC_BROWSE_CLOSE_IND_EVT:
325 log::info("Browse Close Event");
326 break;
327 default:
328 log::error("Unknown AVRCP Control event");
329 break;
330 }
331 }
332
AcceptorControlCb(uint8_t handle,uint8_t event,uint16_t result,const RawAddress * peer_addr)333 void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event,
334 uint16_t result,
335 const RawAddress* peer_addr) {
336 DCHECK(!connection_cb_.is_null());
337
338 log::info("handle=0x{:x} result=0x{:x} addr={}", handle, result,
339 peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none");
340
341 switch (event) {
342 case AVRC_OPEN_IND_EVT: {
343 log::info("Connection Opened Event");
344 if (peer_addr == NULL) {
345 return;
346 }
347 if (btif_av_src_sink_coexist_enabled() &&
348 btif_av_peer_is_connected_source(*peer_addr)) {
349 log::warn("peer is src, close new avrcp cback");
350 if (device_map_.find(handle) != device_map_.end()) {
351 std::lock_guard<std::recursive_mutex> lock(device_map_lock);
352 feature_map_.erase(device_map_[handle]->GetAddress());
353 device_map_[handle]->DeviceDisconnected();
354 device_map_.erase(handle);
355 }
356 avrc_->Close(handle);
357 AvrcpConnect(false, RawAddress::kAny);
358 return;
359 }
360 auto&& callback =
361 base::BindRepeating(&ConnectionHandler::SendMessage,
362 weak_ptr_factory_.GetWeakPtr(), handle);
363 auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
364 auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
365 std::shared_ptr<Device> newDevice = std::make_shared<Device>(
366 *peer_addr, false, callback, ctrl_mtu, browse_mtu);
367
368 device_map_[handle] = newDevice;
369 connection_cb_.Run(newDevice);
370
371 log::info("Performing SDP on connected device. address={}", *peer_addr);
372 auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle,
373 uint16_t status, uint16_t version,
374 uint16_t features) {
375 if (instance_->device_map_.find(handle) ==
376 instance_->device_map_.end()) {
377 log::warn("No device found for handle: 0x{:x}", handle);
378 return;
379 }
380
381 auto device = instance_->device_map_[handle];
382 instance_->feature_map_[device->GetAddress()] = features;
383
384 // TODO (apanicke): Report to the VolumeInterface that a new Device is
385 // connected that doesn't support absolute volume.
386 if (!btif_av_src_sink_coexist_enabled() ||
387 (btif_av_src_sink_coexist_enabled() &&
388 btif_av_peer_is_connected_sink(device->GetAddress()))) {
389 if (features & BTA_AV_FEAT_ADV_CTRL) {
390 device->RegisterVolumeChanged();
391 } else if (instance_->vol_ != nullptr) {
392 instance_->vol_->DeviceConnected(device->GetAddress());
393 }
394 }
395 };
396
397 if (SdpLookup(*peer_addr, base::Bind(sdp_lambda, this, handle), false)) {
398 avrc_->OpenBrowse(handle, AVCT_ACP);
399 } else {
400 // SDP search failed, this could be due to a collision between outgoing
401 // and incoming connection. In any case, we need to reject the current
402 // connection.
403 log::error("SDP search failed for handle: 0x{:x}, closing connection",
404 handle);
405 DisconnectDevice(*peer_addr);
406 }
407 // Open for the next incoming connection. The handle will not be the same
408 // as this one which will be closed when the device is disconnected.
409 AvrcpConnect(false, RawAddress::kAny);
410
411 if (com::android::bluetooth::flags::avrcp_connect_a2dp_delayed()) {
412 // Check peer audio role: src or sink and connect A2DP after 3 seconds
413 SdpLookupAudioRole(handle);
414 }
415 } break;
416
417 case AVRC_CLOSE_IND_EVT: {
418 log::info("Connection Closed Event");
419
420 if (device_map_.find(handle) == device_map_.end()) {
421 log::warn("Connection Close received from device that doesn't exist");
422 return;
423 }
424 {
425 std::lock_guard<std::recursive_mutex> lock(device_map_lock);
426 feature_map_.erase(device_map_[handle]->GetAddress());
427 device_map_[handle]->DeviceDisconnected();
428 device_map_.erase(handle);
429 }
430 avrc_->Close(handle);
431 } break;
432
433 case AVRC_BROWSE_OPEN_IND_EVT: {
434 log::info("Browse Open Event");
435 // NOTE (apanicke): We don't need to explicitly handle this message
436 // since the AVCTP Layer will still send us browsing messages
437 // regardless. It would be useful to note this though for future
438 // compatibility issues.
439 if (device_map_.find(handle) == device_map_.end()) {
440 log::warn("Browse Opened received from device that doesn't exist");
441 return;
442 }
443
444 auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
445 device_map_[handle]->SetBrowseMtu(browse_mtu);
446 } break;
447 case AVRC_BROWSE_CLOSE_IND_EVT:
448 log::info("Browse Close Event");
449 break;
450 default:
451 log::error("Unknown AVRCP Control event");
452 break;
453 }
454 }
455
MessageCb(uint8_t handle,uint8_t label,uint8_t opcode,tAVRC_MSG * p_msg)456 void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
457 tAVRC_MSG* p_msg) {
458 if (device_map_.find(handle) == device_map_.end()) {
459 log::error("Message received for unconnected device: handle=0x{:x}",
460 handle);
461 return;
462 }
463
464 auto pkt = AvrcpMessageConverter::Parse(p_msg);
465
466 if (opcode == AVRC_OP_BROWSE) {
467 if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
468 if (p_msg->browse.hdr.ctype == AVCT_RSP) {
469 log::verbose("ignore response handle {}", (unsigned int)handle);
470 return;
471 }
472 }
473 log::verbose("Browse Message received on handle {}", (unsigned int)handle);
474 device_map_[handle]->BrowseMessageReceived(label, BrowsePacket::Parse(pkt));
475 return;
476 }
477
478 log::verbose("Message received on handle {}", (unsigned int)handle);
479 device_map_[handle]->MessageReceived(label, Packet::Parse(pkt));
480 }
481
SdpCb(RawAddress bdaddr,SdpCallback cb,tSDP_DISCOVERY_DB * disc_db,bool retry,uint16_t status)482 void ConnectionHandler::SdpCb(RawAddress bdaddr, SdpCallback cb,
483 tSDP_DISCOVERY_DB* disc_db, bool retry,
484 uint16_t status) {
485 log::verbose("SDP lookup callback received");
486
487 if (status == SDP_CONN_FAILED && !retry) {
488 log::warn("SDP Failure retry again");
489 SdpLookup(bdaddr, cb, true);
490 return;
491 } else if (status != AVRC_SUCCESS) {
492 log::error("SDP Failure: status = {}", (unsigned int)status);
493 cb.Run(status, 0, 0);
494 osi_free(disc_db);
495 return;
496 }
497
498 // Check the peer features
499 tSDP_DISC_REC* sdp_record = nullptr;
500 uint16_t peer_features = 0;
501 uint16_t peer_avrcp_version = 0;
502
503 // TODO (apanicke): Replace this in favor of our own supported features.
504 sdp_record =
505 sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, nullptr);
506 if (sdp_record != nullptr) {
507 log::info("Device {} supports remote control", bdaddr);
508 peer_features |= BTA_AV_FEAT_RCCT;
509
510 if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
511 NULL) {
512 /* get profile version (if failure, version parameter is not updated) */
513 sdp_->FindProfileVersionInRec(
514 sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_version);
515 log::verbose("Device {} peer avrcp version=0x{:x}", bdaddr,
516 peer_avrcp_version);
517
518 if (peer_avrcp_version >= AVRC_REV_1_3) {
519 // These are the standard features, another way to check this is to
520 // search for CAT1 on the remote device
521 log::verbose("Device {} supports metadata", bdaddr);
522 peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
523 }
524 if (peer_avrcp_version >= AVRC_REV_1_4) {
525 /* get supported categories */
526 log::verbose("Get Supported categories");
527 tSDP_DISC_ATTR* sdp_attribute =
528 sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
529 if (sdp_attribute != NULL &&
530 SDP_DISC_ATTR_TYPE(sdp_attribute->attr_len_type) == UINT_DESC_TYPE &&
531 SDP_DISC_ATTR_LEN(sdp_attribute->attr_len_type) >= 2) {
532 log::verbose("Get Supported categories SDP ATTRIBUTES != null");
533 uint16_t categories = sdp_attribute->attr_value.v.u16;
534 if (categories & AVRC_SUPF_CT_CAT2) {
535 log::verbose("Device {} supports advanced control", bdaddr);
536 if (IsAbsoluteVolumeEnabled(&bdaddr)) {
537 peer_features |= (BTA_AV_FEAT_ADV_CTRL);
538 }
539 }
540 if (categories & AVRC_SUPF_CT_BROWSE) {
541 log::verbose("Device {} supports browsing", bdaddr);
542 peer_features |= (BTA_AV_FEAT_BROWSE);
543 }
544 }
545 }
546
547 if (osi_property_get_bool(AVRC_DYNAMIC_AVRCP_ENABLE_PROPERTY, true)) {
548 avrc_->SaveControllerVersion(bdaddr, peer_avrcp_version);
549 }
550 }
551 }
552
553 sdp_record = sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
554 nullptr);
555 if (sdp_record != nullptr) {
556 log::verbose("Device {} supports remote control target", bdaddr);
557
558 uint16_t peer_avrcp_target_version = 0;
559 sdp_->FindProfileVersionInRec(sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL,
560 &peer_avrcp_target_version);
561 log::verbose("Device {} peer avrcp target version=0x{:x}", bdaddr,
562 peer_avrcp_target_version);
563
564 if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
565 NULL) {
566 if (peer_avrcp_target_version >= AVRC_REV_1_4) {
567 /* get supported categories */
568 log::verbose("Get Supported categories");
569 tSDP_DISC_ATTR* sdp_attribute =
570 sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
571 if (sdp_attribute != NULL &&
572 SDP_DISC_ATTR_TYPE(sdp_attribute->attr_len_type) == UINT_DESC_TYPE &&
573 SDP_DISC_ATTR_LEN(sdp_attribute->attr_len_type) >= 2) {
574 log::verbose("Get Supported categories SDP ATTRIBUTES != null");
575 uint16_t categories = sdp_attribute->attr_value.v.u16;
576 if (categories & AVRC_SUPF_CT_CAT2) {
577 log::verbose("Device {} supports advanced control", bdaddr);
578 if (IsAbsoluteVolumeEnabled(&bdaddr)) {
579 peer_features |= (BTA_AV_FEAT_ADV_CTRL);
580 }
581 }
582 }
583 }
584 }
585 }
586
587 osi_free(disc_db);
588
589 cb.Run(status, peer_avrcp_version, peer_features);
590 }
591
SendMessage(uint8_t handle,uint8_t label,bool browse,std::unique_ptr<::bluetooth::PacketBuilder> message)592 void ConnectionHandler::SendMessage(
593 uint8_t handle, uint8_t label, bool browse,
594 std::unique_ptr<::bluetooth::PacketBuilder> message) {
595 std::shared_ptr<::bluetooth::Packet> packet = VectorPacket::Make();
596 message->Serialize(packet);
597
598 uint8_t ctype = AVRC_RSP_ACCEPT;
599 if (!browse) {
600 ctype =
601 (uint8_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetCType());
602 }
603
604 log::info("SendMessage to handle=0x{:x}", handle);
605
606 BT_HDR* pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
607
608 pkt->offset = AVCT_MSG_OFFSET;
609 // TODO (apanicke): Update this constant. Currently this is a unique event
610 // used to tell the AVRCP API layer that the data is properly formatted and
611 // doesn't need to be processed. In the future, this is the only place sending
612 // the packet so none of these layer specific fields will be used.
613 pkt->event = 0xFFFF;
614 /* Handle for AVRCP fragment */
615 uint16_t op_code =
616 (uint16_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetOpcode());
617 if (!browse && (op_code == (uint16_t)(Opcode::VENDOR))) {
618 pkt->event = op_code;
619 }
620
621 // TODO (apanicke): This layer specific stuff can go away once we move over
622 // to the new service.
623 pkt->layer_specific = AVCT_DATA_CTRL;
624 if (browse) {
625 pkt->layer_specific = AVCT_DATA_BROWSE;
626 }
627
628 pkt->len = packet->size();
629 uint8_t* p_data = (uint8_t*)(pkt + 1) + pkt->offset;
630 for (auto it = packet->begin(); it != packet->end(); it++) {
631 *p_data++ = *it;
632 }
633
634 avrc_->MsgReq(handle, label, ctype, pkt);
635 }
636
RegisterVolChanged(const RawAddress & bdaddr)637 void ConnectionHandler::RegisterVolChanged(const RawAddress& bdaddr) {
638 log::info("Attempting to RegisterVolChanged device {}", bdaddr);
639 for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
640 if (bdaddr == it->second->GetAddress()) {
641 const auto& feature_iter = feature_map_.find(bdaddr);
642 if (feature_iter->second & BTA_AV_FEAT_ADV_CTRL) {
643 it->second->RegisterVolumeChanged();
644 } else if (instance_->vol_ != nullptr) {
645 instance_->vol_->DeviceConnected(bdaddr);
646 }
647 break;
648 }
649 }
650 }
651
SdpLookupAudioRole(uint16_t handle)652 bool ConnectionHandler::SdpLookupAudioRole(uint16_t handle) {
653 if (device_map_.find(handle) == device_map_.end()) {
654 log::warn("No device found for handle: {}", loghex(handle));
655 return false;
656 }
657 auto device = device_map_[handle];
658
659 log::info(
660 "Performing SDP for AUDIO_SINK on connected device: address={}, "
661 "handle={}",
662 ADDRESS_TO_LOGGABLE_STR(device->GetAddress()), handle);
663
664 return device->find_sink_service(
665 base::Bind(&ConnectionHandler::SdpLookupAudioRoleCb,
666 weak_ptr_factory_.GetWeakPtr(), handle));
667 }
668
SdpLookupAudioRoleCb(uint16_t handle,bool found,tA2DP_Service * p_service,const RawAddress & peer_address)669 void ConnectionHandler::SdpLookupAudioRoleCb(uint16_t handle, bool found,
670 tA2DP_Service* p_service,
671 const RawAddress& peer_address) {
672 if (device_map_.find(handle) == device_map_.end()) {
673 log::warn("No device found for handle: {}", loghex(handle));
674 return;
675 }
676 auto device = device_map_[handle];
677
678 log::debug("SDP callback for address={}, handle={}, AUDIO_SINK {}",
679 ADDRESS_TO_LOGGABLE_STR(device->GetAddress()), handle,
680 found ? "found" : "not found");
681
682 if (found) {
683 device->connect_a2dp_sink_delayed(handle);
684 }
685 }
686
687 } // namespace avrcp
688 } // namespace bluetooth
689