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