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