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