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