blob: 7b2765ae63d875cd9cf450a912ac347e5ae16ff4 [file] [log] [blame]
Ajay Panicker8e521032018-02-27 20:51:47 -08001/*
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"
Ajay Panicker8e521032018-02-27 20:51:47 -080025#include "bt_types.h"
26#include "btu.h"
Jakub Pawlowski9e814612018-05-25 09:31:26 -070027#include "packet/avrcp/avrcp_packet.h"
Ajay Panicker8e521032018-02-27 20:51:47 -080028// TODO (apanicke): Remove dependency on this header once we cleanup feature
29// handling.
30#include "bta/include/bta_av_api.h"
Ted0267a332018-08-17 18:49:37 +080031#include "device/include/interop.h"
Ajay Panicker8e521032018-02-27 20:51:47 -080032#include "osi/include/allocator.h"
Ted0267a332018-08-17 18:49:37 +080033#include "osi/include/properties.h"
Ajay Panicker8e521032018-02-27 20:51:47 -080034
35namespace bluetooth {
36namespace avrcp {
37
38ConnectionHandler* ConnectionHandler::instance_ = nullptr;
39
40ConnectionHandler* ConnectionHandler::Get() {
41 CHECK(instance_);
42
43 return instance_;
44}
45
Ted0267a332018-08-17 18:49:37 +080046bool 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
Ajay Panicker8e521032018-02-27 20:51:47 -080060bool ConnectionHandler::Initialize(const ConnectionCallback& callback,
Ajay Panickerca050da2018-04-13 11:49:34 -070061 AvrcpInterface* avrcp, SdpInterface* sdp,
62 VolumeInterface* vol) {
Ajay Panicker8e521032018-02-27 20:51:47 -080063 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;
Ajay Panickerca050da2018-04-13 11:49:34 -070073 instance_->vol_ = vol;
Ajay Panicker8e521032018-02-27 20:51:47 -080074
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
84bool 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
Ajay Panicker74a75492018-04-19 15:17:16 -070095 instance_->weak_ptr_factory_.InvalidateWeakPtrs();
96
Ajay Panicker8e521032018-02-27 20:51:47 -080097 delete instance_;
98 instance_ = nullptr;
99
100 return true;
101}
102
103void ConnectionHandler::InitForTesting(ConnectionHandler* handler) {
104 CHECK(instance_ == nullptr);
105 instance_ = handler;
106}
107
108bool 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));
136}
137
138bool ConnectionHandler::DisconnectDevice(const RawAddress& bdaddr) {
139 for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
140 if (bdaddr == it->second->GetAddress()) {
Ajay Panicker8e521032018-02-27 20:51:47 -0800141 uint8_t handle = it->first;
Ajay Panicker8e521032018-02-27 20:51:47 -0800142 return avrc_->Close(handle) == AVRC_SUCCESS;
143 }
144 }
145
146 return false;
147}
148
149std::vector<std::shared_ptr<Device>> ConnectionHandler::GetListOfDevices()
150 const {
151 std::vector<std::shared_ptr<Device>> list;
Chih-Hung Hsieh01a40402018-12-12 14:30:52 -0800152 for (const auto& device : device_map_) {
Ajay Panicker8e521032018-02-27 20:51:47 -0800153 list.push_back(device.second);
154 }
155 return list;
156}
157
158bool ConnectionHandler::SdpLookup(const RawAddress& bdaddr, SdpCallback cb) {
159 LOG(INFO) << __PRETTY_FUNCTION__;
160
161 tAVRC_SDP_DB_PARAMS db_params;
162 // TODO (apanicke): This needs to be replaced with smarter memory management.
163 tSDP_DISCOVERY_DB* disc_db =
164 (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
165 uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
166 ATTR_ID_BT_PROFILE_DESC_LIST,
167 ATTR_ID_SUPPORTED_FEATURES};
168
169 db_params.db_len =
170 BT_DEFAULT_BUFFER_SIZE; // Some magic number found in the AVRCP code
171 db_params.num_attr = sizeof(attr_list) / sizeof(attr_list[0]);
172 db_params.p_db = disc_db;
173 db_params.p_attrs = attr_list;
174
175 return avrc_->FindService(
176 UUID_SERVCLASS_AV_REMOTE_CONTROL, bdaddr, &db_params,
Ajay Panicker0d33f582018-05-01 17:29:07 -0700177 base::Bind(&ConnectionHandler::SdpCb,
178 weak_ptr_factory_.GetWeakPtr(), bdaddr, cb, disc_db)) ==
179 AVRC_SUCCESS;
Ajay Panicker8e521032018-02-27 20:51:47 -0800180}
181
182bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) {
183 LOG(INFO) << "Connect to device " << bdaddr.ToString();
184
185 tAVRC_CONN_CB open_cb;
186 if (initiator) {
187 open_cb.ctrl_cback = base::Bind(&ConnectionHandler::InitiatorControlCb,
Ajay Panicker74a75492018-04-19 15:17:16 -0700188 weak_ptr_factory_.GetWeakPtr());
Ajay Panicker8e521032018-02-27 20:51:47 -0800189 } else {
190 open_cb.ctrl_cback = base::Bind(&ConnectionHandler::AcceptorControlCb,
Ajay Panicker74a75492018-04-19 15:17:16 -0700191 weak_ptr_factory_.GetWeakPtr());
Ajay Panicker8e521032018-02-27 20:51:47 -0800192 }
193 open_cb.msg_cback =
Ajay Panicker0d33f582018-05-01 17:29:07 -0700194 base::Bind(&ConnectionHandler::MessageCb, weak_ptr_factory_.GetWeakPtr());
Ajay Panicker8e521032018-02-27 20:51:47 -0800195 open_cb.company_id = AVRC_CO_GOOGLE;
196 open_cb.conn = initiator ? AVRC_CONN_INT
197 : AVRC_CONN_ACP; // 0 if initiator, 1 if acceptor
198 // TODO (apanicke): We shouldn't need RCCT to do absolute volume. The current
199 // AVRC_API requires it though.
200 open_cb.control = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA;
201
202 uint8_t handle = 0;
203 uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr);
204 LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
205 << " status= " << loghex(status);
206 return status == AVRC_SUCCESS;
207}
208
209void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event,
210 uint16_t result,
211 const RawAddress* peer_addr) {
212 DCHECK(!connection_cb_.is_null());
Ajay Panicker8e521032018-02-27 20:51:47 -0800213
214 LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
215 << " result=" << loghex(result)
216 << " addr=" << (peer_addr ? peer_addr->ToString() : "none");
217
218 switch (event) {
219 case AVRC_OPEN_IND_EVT: {
220 LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";
221
222 const auto& feature_iter = feature_map_.find(*peer_addr);
223 if (feature_iter == feature_map_.end()) {
224 LOG(ERROR) << "Features do not exist even though SDP should have been "
225 "done first";
226 return;
227 }
228
229 bool supports_browsing = feature_iter->second & BTA_AV_FEAT_BROWSE;
230
231 if (supports_browsing) {
232 avrc_->OpenBrowse(handle, AVCT_INT);
233 }
234
235 // TODO (apanicke): Implement a system to cache SDP entries. For most
236 // devices SDP is completed after the device connects AVRCP so that
237 // information isn't very useful when trying to control our
238 // capabilities. For now always use AVRCP 1.6.
Ajay Panickere6552092018-03-31 14:38:53 -0700239 auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
240 base::Unretained(this), handle);
241 auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
242 auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
243 std::shared_ptr<Device> newDevice = std::make_shared<Device>(
244 *peer_addr, !supports_browsing, callback, ctrl_mtu, browse_mtu);
245
Ajay Panicker8e521032018-02-27 20:51:47 -0800246 device_map_[handle] = newDevice;
247 // TODO (apanicke): Create the device with all of the interfaces it
248 // needs. Return the new device where the service will register the
249 // interfaces it needs.
250 connection_cb_.Run(newDevice);
251
252 if (feature_iter->second & BTA_AV_FEAT_ADV_CTRL) {
253 newDevice->RegisterVolumeChanged();
Ajay Panickerca050da2018-04-13 11:49:34 -0700254 } else if (instance_->vol_ != nullptr) {
255 instance_->vol_->DeviceConnected(newDevice->GetAddress());
Ajay Panicker8e521032018-02-27 20:51:47 -0800256 }
Ajay Panickerca050da2018-04-13 11:49:34 -0700257
Ajay Panicker8e521032018-02-27 20:51:47 -0800258 } break;
259
260 case AVRC_CLOSE_IND_EVT: {
261 LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";
262
Ajay Panickerf8e3f452018-04-17 14:15:30 -0700263 if (device_map_.find(handle) == device_map_.end()) {
Ajay Panicker8e521032018-02-27 20:51:47 -0800264 LOG(WARNING)
265 << "Connection Close received from device that doesn't exist";
266 return;
267 }
Ajay Panicker473b4ca2018-04-10 19:24:51 -0700268 avrc_->Close(handle);
Ajay Panickerce1a2b32018-03-16 17:13:50 -0700269 feature_map_.erase(device_map_[handle]->GetAddress());
Ajay Panicker8e521032018-02-27 20:51:47 -0800270 device_map_[handle]->DeviceDisconnected();
271 device_map_.erase(handle);
272 } break;
273
Ajay Panicker950d9cc2018-08-24 10:32:07 -0700274 case AVRC_BROWSE_OPEN_IND_EVT: {
Ajay Panicker8e521032018-02-27 20:51:47 -0800275 LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
276 // NOTE (apanicke): We don't need to explicitly handle this message
277 // since the AVCTP Layer will still send us browsing messages
278 // regardless. It would be useful to note this though for future
279 // compatibility issues.
Ajay Panicker950d9cc2018-08-24 10:32:07 -0700280 if (device_map_.find(handle) == device_map_.end()) {
281 LOG(WARNING) << "Browse Opened received from device that doesn't exist";
282 return;
283 }
284
285 auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
286 device_map_[handle]->SetBrowseMtu(browse_mtu);
287 } break;
Ajay Panicker8e521032018-02-27 20:51:47 -0800288 case AVRC_BROWSE_CLOSE_IND_EVT:
289 LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
290 break;
291 default:
292 LOG(ERROR) << "Unknown AVRCP Control event";
293 break;
294 }
295}
296
297void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event,
298 uint16_t result,
299 const RawAddress* peer_addr) {
300 DCHECK(!connection_cb_.is_null());
Ajay Panicker8e521032018-02-27 20:51:47 -0800301
302 LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
303 << " result=" << loghex(result)
304 << " addr=" << (peer_addr ? peer_addr->ToString() : "none");
305
306 switch (event) {
307 case AVRC_OPEN_IND_EVT: {
308 LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";
309
Ajay Panickere6552092018-03-31 14:38:53 -0700310 auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
Ajay Panicker0d33f582018-05-01 17:29:07 -0700311 weak_ptr_factory_.GetWeakPtr(), handle);
Ajay Panickere6552092018-03-31 14:38:53 -0700312 auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
313 auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
314 std::shared_ptr<Device> newDevice = std::make_shared<Device>(
315 *peer_addr, false, callback, ctrl_mtu, browse_mtu);
316
Ajay Panicker8e521032018-02-27 20:51:47 -0800317 device_map_[handle] = newDevice;
318 connection_cb_.Run(newDevice);
319
320 LOG(INFO) << __PRETTY_FUNCTION__
321 << ": Performing SDP on connected device. address="
322 << peer_addr->ToString();
323 auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle,
324 uint16_t status, uint16_t version,
325 uint16_t features) {
326 if (instance_->device_map_.find(handle) ==
327 instance_->device_map_.end()) {
328 LOG(WARNING) << __PRETTY_FUNCTION__
329 << ": No device found for handle: " << loghex(handle);
330 return;
331 }
332
333 auto device = instance_->device_map_[handle];
334 instance_->feature_map_.emplace(device->GetAddress(), features);
335
336 // TODO (apanicke): Report to the VolumeInterface that a new Device is
337 // connected that doesn't support absolute volume.
338 if (features & BTA_AV_FEAT_ADV_CTRL) {
339 device->RegisterVolumeChanged();
Ajay Panickerca050da2018-04-13 11:49:34 -0700340 } else if (instance_->vol_ != nullptr) {
341 instance_->vol_->DeviceConnected(device->GetAddress());
Ajay Panicker8e521032018-02-27 20:51:47 -0800342 }
343 };
344
345 SdpLookup(*peer_addr, base::Bind(sdp_lambda, this, handle));
346
347 avrc_->OpenBrowse(handle, AVCT_ACP);
348 AvrcpConnect(false, RawAddress::kAny);
349 } break;
350
351 case AVRC_CLOSE_IND_EVT: {
352 LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";
353
Ajay Panickerf8e3f452018-04-17 14:15:30 -0700354 if (device_map_.find(handle) == device_map_.end()) {
Ajay Panicker8e521032018-02-27 20:51:47 -0800355 LOG(WARNING)
356 << "Connection Close received from device that doesn't exist";
357 return;
358 }
Ajay Panicker473b4ca2018-04-10 19:24:51 -0700359 avrc_->Close(handle);
Ajay Panickerce1a2b32018-03-16 17:13:50 -0700360 feature_map_.erase(device_map_[handle]->GetAddress());
Ajay Panicker8e521032018-02-27 20:51:47 -0800361 device_map_[handle]->DeviceDisconnected();
362 device_map_.erase(handle);
363 } break;
364
Ajay Panicker950d9cc2018-08-24 10:32:07 -0700365 case AVRC_BROWSE_OPEN_IND_EVT: {
Ajay Panicker8e521032018-02-27 20:51:47 -0800366 LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
367 // NOTE (apanicke): We don't need to explicitly handle this message
368 // since the AVCTP Layer will still send us browsing messages
369 // regardless. It would be useful to note this though for future
370 // compatibility issues.
Ajay Panicker950d9cc2018-08-24 10:32:07 -0700371 if (device_map_.find(handle) == device_map_.end()) {
372 LOG(WARNING) << "Browse Opened received from device that doesn't exist";
373 return;
374 }
375
376 auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
377 device_map_[handle]->SetBrowseMtu(browse_mtu);
378 } break;
Ajay Panicker8e521032018-02-27 20:51:47 -0800379 case AVRC_BROWSE_CLOSE_IND_EVT:
380 LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
381 break;
382 default:
383 LOG(ERROR) << "Unknown AVRCP Control event";
384 break;
385 }
386}
387
388void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
389 tAVRC_MSG* p_msg) {
Ted Wang48af6202019-03-29 16:20:27 +0800390 if (device_map_.find(handle) == device_map_.end()) {
Ajay Panicker8e521032018-02-27 20:51:47 -0800391 LOG(ERROR) << "Message received for unconnected device: handle="
392 << loghex(handle);
393 return;
394 }
395
396 auto pkt = AvrcpMessageConverter::Parse(p_msg);
397
398 if (opcode == AVRC_OP_BROWSE) {
399 VLOG(4) << "Browse Message received on handle " << (unsigned int)handle;
400 device_map_[handle]->BrowseMessageReceived(label, BrowsePacket::Parse(pkt));
401 return;
402 }
403
404 VLOG(4) << "Message received on handle " << (unsigned int)handle;
405 device_map_[handle]->MessageReceived(label, Packet::Parse(pkt));
406}
407
408void ConnectionHandler::SdpCb(const RawAddress& bdaddr, SdpCallback cb,
409 tSDP_DISCOVERY_DB* disc_db, uint16_t status) {
410 LOG(INFO) << __PRETTY_FUNCTION__ << ": SDP lookup callback received";
411
412 if (status != AVRC_SUCCESS) {
413 LOG(ERROR) << __PRETTY_FUNCTION__
414 << ": SDP Failure: status = " << (unsigned int)status;
415 cb.Run(status, 0, 0);
416 osi_free(disc_db);
417 return;
418 }
419
420 // Check the peer features
421 tSDP_DISC_REC* sdp_record = nullptr;
422 uint16_t peer_features = 0;
423 uint16_t peer_avrcp_version = 0;
424
425 // TODO (apanicke): Replace this in favor of our own supported features.
426 sdp_record =
427 sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, nullptr);
428 if (sdp_record != nullptr) {
429 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
430 << " supports remote control";
431 peer_features |= BTA_AV_FEAT_RCCT;
432
433 if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
434 NULL) {
435 /* get profile version (if failure, version parameter is not updated) */
436 sdp_->FindProfileVersionInRec(
437 sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_version);
438 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
439 << " peer avrcp version=" << loghex(peer_avrcp_version);
440
441 if (peer_avrcp_version >= AVRC_REV_1_3) {
442 // These are the standard features, another way to check this is to
443 // search for CAT1 on the remote device
444 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
445 << " supports metadata";
446 peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
447 }
448 if (peer_avrcp_version >= AVRC_REV_1_4) {
449 /* get supported categories */
450 LOG(INFO) << __PRETTY_FUNCTION__ << " Get Supported categories";
451 tSDP_DISC_ATTR* sdp_attribute =
452 sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
453 if (sdp_attribute != NULL) {
454 LOG(INFO) << __PRETTY_FUNCTION__
455 << "Get Supported categories SDP ATTRIBUTES != null";
456 uint16_t categories = sdp_attribute->attr_value.v.u16;
457 if (categories & AVRC_SUPF_CT_CAT2) {
458 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
459 << " supports advanced control";
Ted0267a332018-08-17 18:49:37 +0800460 if (IsAbsoluteVolumeEnabled(&bdaddr)) {
461 peer_features |= (BTA_AV_FEAT_ADV_CTRL);
462 }
Ajay Panicker8e521032018-02-27 20:51:47 -0800463 }
464 if (categories & AVRC_SUPF_CT_BROWSE) {
465 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
466 << " supports browsing";
467 peer_features |= (BTA_AV_FEAT_BROWSE);
468 }
469 }
470 }
471 }
472 }
473
474 sdp_record = sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
475 nullptr);
476 if (sdp_record != nullptr) {
477 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
478 << " supports remote control target";
479
480 uint16_t peer_avrcp_target_version = 0;
481 sdp_->FindProfileVersionInRec(sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL,
482 &peer_avrcp_target_version);
483 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
484 << " peer avrcp target version="
485 << loghex(peer_avrcp_target_version);
486
487 if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
488 NULL) {
489 if (peer_avrcp_target_version >= AVRC_REV_1_4) {
490 /* get supported categories */
491 LOG(INFO) << __PRETTY_FUNCTION__ << " Get Supported categories";
492 tSDP_DISC_ATTR* sdp_attribute =
493 sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
494 if (sdp_attribute != NULL) {
495 LOG(INFO) << __PRETTY_FUNCTION__
496 << "Get Supported categories SDP ATTRIBUTES != null";
497 uint16_t categories = sdp_attribute->attr_value.v.u16;
498 if (categories & AVRC_SUPF_CT_CAT2) {
499 LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
500 << " supports advanced control";
Ted0267a332018-08-17 18:49:37 +0800501 if (IsAbsoluteVolumeEnabled(&bdaddr)) {
502 peer_features |= (BTA_AV_FEAT_ADV_CTRL);
503 }
Ajay Panicker8e521032018-02-27 20:51:47 -0800504 }
505 }
506 }
507 }
508 }
509
510 osi_free(disc_db);
511
512 cb.Run(status, peer_avrcp_version, peer_features);
513}
514
515void ConnectionHandler::SendMessage(
516 uint8_t handle, uint8_t label, bool browse,
517 std::unique_ptr<::bluetooth::PacketBuilder> message) {
518 std::shared_ptr<::bluetooth::Packet> packet = VectorPacket::Make();
519 message->Serialize(packet);
520
521 uint8_t ctype = AVRC_RSP_ACCEPT;
522 if (!browse) {
523 ctype =
524 (uint8_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetCType());
525 }
526
527 DLOG(INFO) << "SendMessage to handle=" << loghex(handle);
528
529 BT_HDR* pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
530
531 pkt->offset = AVCT_MSG_OFFSET;
532 // TODO (apanicke): Update this constant. Currently this is a unique event
533 // used to tell the AVRCP API layer that the data is properly formatted and
534 // doesn't need to be processed. In the future, this is the only place sending
535 // the packet so none of these layer specific fields will be used.
536 pkt->event = 0xFFFF;
JiLin Wan6c270cb2019-05-13 11:45:18 +0800537 /* Handle for AVRCP fragment */
538 uint16_t op_code = (uint16_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetOpcode());
539 if (!browse && (op_code == (uint16_t)(Opcode::VENDOR))) {
540 pkt->event = op_code;
541 }
Ajay Panicker8e521032018-02-27 20:51:47 -0800542
543 // TODO (apanicke): This layer specific stuff can go away once we move over
544 // to the new service.
545 pkt->layer_specific = AVCT_DATA_CTRL;
546 if (browse) {
547 pkt->layer_specific = AVCT_DATA_BROWSE;
548 }
549
550 pkt->len = packet->size();
551 uint8_t* p_data = (uint8_t*)(pkt + 1) + pkt->offset;
552 for (auto it = packet->begin(); it != packet->end(); it++) {
553 *p_data++ = *it;
554 }
555
556 avrc_->MsgReq(handle, label, ctype, pkt);
557}
558
559} // namespace avrcp
Ajay Panickerf8e3f452018-04-17 14:15:30 -0700560} // namespace bluetooth