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