• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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