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