1 /*
2 * Copyright 2015 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 /*****************************************************************************
18 *
19 * Filename: btif_rc.cc
20 *
21 * Description: Bluetooth AVRC implementation
22 *
23 *****************************************************************************/
24
25 #define LOG_TAG "bt_btif_avrc"
26
27 #include "btif_rc.h"
28
29 #include <base/functional/bind.h>
30 #include <bluetooth/log.h>
31 #include <hardware/bluetooth.h>
32 #include <hardware/bt_rc.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <time.h>
36
37 #include <cstdint>
38 #include <cstdio>
39 #include <mutex>
40 #include <sstream>
41 #include <string>
42
43 #include "bta/include/bta_av_api.h"
44 #include "btif/avrcp/avrcp_service.h"
45 #include "btif_av.h"
46 #include "btif_common.h"
47 #include "btif_util.h"
48 #include "device/include/interop.h"
49 #include "os/logging/log_adapter.h"
50 #include "osi/include/alarm.h"
51 #include "osi/include/allocator.h"
52 #include "osi/include/list.h"
53 #include "osi/include/osi.h"
54 #include "osi/include/properties.h"
55 #include "stack/include/avrc_api.h"
56 #include "stack/include/avrc_defs.h"
57 #include "stack/include/bt_hdr.h"
58 #include "stack/include/bt_types.h"
59 #include "types/raw_address.h"
60
61 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
62
63 /*****************************************************************************
64 * Constants & Macros
65 *****************************************************************************/
66
67 /* cod value for Headsets */
68 #define COD_AV_HEADSETS 0x0404
69 /* for AVRC 1.4 need to change this */
70 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
71
72 #define IDX_GET_PLAY_STATUS_RSP 0
73 #define IDX_LIST_APP_ATTR_RSP 1
74 #define IDX_LIST_APP_VALUE_RSP 2
75 #define IDX_GET_CURR_APP_VAL_RSP 3
76 #define IDX_SET_APP_VAL_RSP 4
77 #define IDX_GET_APP_ATTR_TXT_RSP 5
78 #define IDX_GET_APP_VAL_TXT_RSP 6
79 #define IDX_GET_ELEMENT_ATTR_RSP 7
80 #define IDX_SET_ADDR_PLAYER_RSP 8
81 #define IDX_SET_BROWSED_PLAYER_RSP 9
82 #define IDX_GET_FOLDER_ITEMS_RSP 10
83 #define IDX_CHG_PATH_RSP 11
84 #define IDX_GET_ITEM_ATTR_RSP 12
85 #define IDX_PLAY_ITEM_RSP 13
86 #define IDX_GET_TOTAL_NUM_OF_ITEMS_RSP 14
87 #define IDX_SEARCH_RSP 15
88 #define IDX_ADD_TO_NOW_PLAYING_RSP 16
89
90 /* Update MAX value whenever IDX will be changed */
91 #define MAX_CMD_QUEUE_LEN 17
92
93 #define MAX_VOLUME 128
94 #define MAX_LABEL 16
95 #define MAX_TRANSACTIONS_PER_SESSION 16
96 #define PLAY_STATUS_PLAYING 1
97 #define BTIF_RC_NUM_CONN BT_RC_NUM_APP
98
99 #define CHECK_RC_CONNECTED(p_dev) \
100 do { \
101 if ((p_dev) == NULL || !(p_dev)->rc_connected) { \
102 log::warn("called when RC is not connected"); \
103 return BT_STATUS_NOT_READY; \
104 } \
105 } while (0)
106
107 #define CHECK_BR_CONNECTED(p_dev) \
108 do { \
109 if ((p_dev) == NULL || !(p_dev)->br_connected) { \
110 log::warn("called when BR is not connected"); \
111 return BT_STATUS_NOT_READY; \
112 } \
113 } while (0)
114
115 using namespace bluetooth;
116
117 /*****************************************************************************
118 * Local type definitions
119 *****************************************************************************/
120 typedef struct {
121 uint8_t bNotify;
122 uint8_t label;
123 } btif_rc_reg_notifications_t;
124
125 typedef struct {
126 uint8_t label;
127 uint8_t ctype;
128 bool is_rsp_pending;
129 } btif_rc_cmd_ctxt_t;
130
131 /* 2 second timeout to get command response, then we free label */
132 #define BTIF_RC_TIMEOUT_MS (2 * 1000)
133
134 typedef enum { eNOT_REGISTERED, eREGISTERED, eINTERIM } btif_rc_nfn_reg_status_t;
135
136 typedef struct {
137 uint8_t event_id;
138 uint8_t label;
139 btif_rc_nfn_reg_status_t status;
140 } btif_rc_supported_event_t;
141
142 #define BTIF_RC_STS_TIMEOUT 0xFE
143
144 typedef struct {
145 bool query_started;
146 uint8_t num_attrs;
147 uint8_t num_ext_attrs;
148
149 uint8_t attr_index;
150 uint8_t ext_attr_index;
151 uint8_t ext_val_index;
152 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE];
153 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE];
154 } btif_rc_player_app_settings_t;
155
156 // The context associated with a passthru command
157 typedef struct {
158 uint8_t rc_id;
159 uint8_t key_state;
160 uint8_t custom_id;
161 } rc_passthru_context_t;
162
163 // The context associated with a vendor command
164 typedef struct {
165 uint8_t pdu_id;
166 uint8_t event_id;
167 } rc_vendor_context_t;
168
169 // The context associated with a browsing command
170 typedef struct {
171 uint8_t pdu_id;
172 } rc_browse_context_t;
173
174 typedef union {
175 rc_vendor_context_t vendor;
176 rc_browse_context_t browse;
177 rc_passthru_context_t passthru;
178 } rc_command_context_t;
179
180 // The context associated with any command transaction requiring a label.
181 // The opcode determines how to determine the data in the union. Context is
182 // used to track which requests have which labels
183 typedef struct {
184 RawAddress rc_addr;
185 uint8_t label;
186 uint8_t opcode;
187 rc_command_context_t command;
188 } rc_transaction_context_t;
189 typedef struct {
190 bool in_use;
191 uint8_t label;
192 rc_transaction_context_t context;
193 alarm_t* timer;
194 } rc_transaction_t;
195
196 typedef struct {
197 std::recursive_mutex label_lock;
198 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
199 } rc_transaction_set_t;
200
201 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single
202 * struct */
203 typedef struct {
204 bool rc_connected;
205 bool br_connected; // Browsing channel.
206 uint8_t rc_handle;
207 tBTA_AV_FEAT rc_features;
208 uint16_t rc_cover_art_psm; // AVRCP-BIP psm
209 btrc_connection_state_t rc_state;
210 RawAddress rc_addr;
211 uint16_t rc_pending_play;
212 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
213 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
214 unsigned int rc_volume;
215 uint8_t rc_vol_label;
216 list_t* rc_supported_event_list;
217 btif_rc_player_app_settings_t rc_app_settings;
218 alarm_t* rc_play_status_timer;
219 bool rc_features_processed;
220 uint64_t rc_playing_uid;
221 bool rc_procedure_complete;
222 rc_transaction_set_t transaction_set;
223 tBTA_AV_FEAT peer_ct_features;
224 tBTA_AV_FEAT peer_tg_features;
225 uint8_t launch_cmd_pending; /* true: getcap/regvolume */
226 } btif_rc_device_cb_t;
227
228 #define RC_PENDING_ACT_GET_CAP (1 << 0)
229 #define RC_PENDING_ACT_REG_VOL (1 << 1)
230 #define RC_PENDING_ACT_REPORT_CONN (1 << 2)
231
232 typedef struct {
233 std::mutex lock;
234 btif_rc_device_cb_t rc_multi_cb[BTIF_RC_NUM_CONN];
235 } rc_cb_t;
236
237 typedef struct {
238 uint8_t handle;
239 } btif_rc_handle_t;
240
241 static void sleep_ms(uint64_t timeout_ms);
242
243 /* Response status code - Unknown Error - this is changed to "reserved" */
244 #define BTIF_STS_GEN_ERROR 0x06
245
246 /* Utility table to map hal status codes to bta status codes for the response
247 * status */
248 static const uint8_t status_code_map[] = {
249 /* BTA_Status codes HAL_Status codes */
250 AVRC_STS_BAD_CMD, /* BTRC_STS_BAD_CMD */
251 AVRC_STS_BAD_PARAM, /* BTRC_STS_BAD_PARAM */
252 AVRC_STS_NOT_FOUND, /* BTRC_STS_NOT_FOUND */
253 AVRC_STS_INTERNAL_ERR, /* BTRC_STS_INTERNAL_ERR */
254 AVRC_STS_NO_ERROR, /* BTRC_STS_NO_ERROR */
255 AVRC_STS_UID_CHANGED, /* BTRC_STS_UID_CHANGED */
256 BTIF_STS_GEN_ERROR, /* BTRC_STS_RESERVED */
257 AVRC_STS_BAD_DIR, /* BTRC_STS_INV_DIRN */
258 AVRC_STS_NOT_DIR, /* BTRC_STS_INV_DIRECTORY */
259 AVRC_STS_NOT_EXIST, /* BTRC_STS_INV_ITEM */
260 AVRC_STS_BAD_SCOPE, /* BTRC_STS_INV_SCOPE */
261 AVRC_STS_BAD_RANGE, /* BTRC_STS_INV_RANGE */
262 AVRC_STS_UID_IS_DIR, /* BTRC_STS_DIRECTORY */
263 AVRC_STS_IN_USE, /* BTRC_STS_MEDIA_IN_USE */
264 AVRC_STS_NOW_LIST_FULL, /* BTRC_STS_PLAY_LIST_FULL */
265 AVRC_STS_SEARCH_NOT_SUP, /* BTRC_STS_SRCH_NOT_SPRTD */
266 AVRC_STS_SEARCH_BUSY, /* BTRC_STS_SRCH_IN_PROG */
267 AVRC_STS_BAD_PLAYER_ID, /* BTRC_STS_INV_PLAYER */
268 AVRC_STS_PLAYER_N_BR, /* BTRC_STS_PLAY_NOT_BROW */
269 AVRC_STS_PLAYER_N_ADDR, /* BTRC_STS_PLAY_NOT_ADDR */
270 AVRC_STS_BAD_SEARCH_RES, /* BTRC_STS_INV_RESULTS */
271 AVRC_STS_NO_AVAL_PLAYER, /* BTRC_STS_NO_AVBL_PLAY */
272 AVRC_STS_ADDR_PLAYER_CHG, /* BTRC_STS_ADDR_PLAY_CHGD */
273 };
274
275 static void initialize_device(btif_rc_device_cb_t* p_dev);
276 static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu, uint8_t status,
277 uint8_t opcode);
278 static uint8_t opcode_from_pdu(uint8_t pdu);
279 static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index, uint8_t label,
280 tBTA_AV_CODE code, tAVRC_RESPONSE* pmetamsg_resp);
281 static void register_volumechange(btif_rc_device_cb_t* p_dev);
282 static void init_all_transactions(btif_rc_device_cb_t* p_dev);
283 static bt_status_t get_transaction(btif_rc_device_cb_t* p_dev, rc_transaction_context_t& context,
284 rc_transaction_t** ptransaction);
285 static void start_transaction_timer(btif_rc_device_cb_t* p_dev, uint8_t label, uint64_t timeout_ms);
286 static void btif_rc_transaction_timer_timeout(void* data);
287 static void release_transaction(btif_rc_device_cb_t* p_dev, uint8_t label);
288 static std::string dump_transaction(const rc_transaction_t* const transaction);
289 static rc_transaction_t* get_transaction_by_lbl(btif_rc_device_cb_t* p_dev, uint8_t label);
290 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg, btif_rc_device_cb_t* p_dev);
291
292 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg);
293 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg);
294 static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event, tAVRC_COMMAND* pavrc_cmd, uint8_t label,
295 btif_rc_device_cb_t* p_dev);
296 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev);
297 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
298 btif_rc_device_cb_t* p_dev);
299 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_GET_CAPS_RSP* p_rsp);
300 static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_LIST_APP_ATTR_RSP* p_rsp);
301 static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_LIST_APP_VALUES_RSP* p_rsp);
302 static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg,
303 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp);
304 static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg,
305 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
306 static void handle_app_attr_val_txt_response(tBTA_AV_META_MSG* pmeta_msg,
307 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
308 static void cleanup_app_attr_val_txt_response(btif_rc_player_app_settings_t* p_app_settings);
309 static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
310 tAVRC_GET_PLAY_STATUS_RSP* p_rsp);
311 static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* p_rsp);
312 static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items, uint8_t item_count);
313 static void handle_get_metadata_attr_response(tBTA_AV_META_MSG* pmeta_msg,
314 tAVRC_GET_ATTRS_RSP* p_rsp);
315 static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* p_rsp);
316 static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev);
317 static bt_status_t get_player_app_setting_attr_text_cmd(uint8_t* attrs, uint8_t num_attrs,
318 btif_rc_device_cb_t* p_dev);
319 static bt_status_t get_player_app_setting_value_text_cmd(uint8_t* vals, uint8_t num_vals,
320 btif_rc_device_cb_t* p_dev);
321 static bt_status_t register_notification_cmd(uint8_t event_id, uint32_t event_value,
322 btif_rc_device_cb_t* p_dev);
323 static bt_status_t get_metadata_attribute_cmd(uint8_t num_attribute, const uint32_t* p_attr_ids,
324 btif_rc_device_cb_t* p_dev);
325 static bt_status_t get_element_attribute_cmd(uint8_t num_attribute, const uint32_t* p_attr_ids,
326 btif_rc_device_cb_t* p_dev);
327 static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope, uint8_t num_attribute,
328 const uint32_t* p_attr_ids, btif_rc_device_cb_t* p_dev);
329 static bt_status_t getcapabilities_cmd(uint8_t cap_id, btif_rc_device_cb_t* p_dev);
330 static bt_status_t list_player_app_setting_attrib_cmd(btif_rc_device_cb_t* p_dev);
331 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id, btif_rc_device_cb_t* p_dev);
332 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids,
333 btif_rc_device_cb_t* p_dev);
334 static void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item);
335 static void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
336 btrc_folder_items_t* btrc_item);
337 static void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
338 btrc_folder_items_t* btrc_item);
339 static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr, uint8_t scope,
340 uint32_t start_item, uint32_t end_item);
341
342 static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* p_param, uint8_t ctype,
343 uint8_t label, btif_rc_device_cb_t* p_dev);
344
345 static void btif_rc_upstreams_rsp_evt(uint16_t event, tAVRC_RESPONSE* pavrc_resp, uint8_t ctype,
346 uint8_t label, btif_rc_device_cb_t* p_dev);
347
348 static bool absolute_volume_disabled(void);
349
350 /*****************************************************************************
351 * Static variables
352 *****************************************************************************/
353 static rc_cb_t btif_rc_cb;
354 static btrc_callbacks_t* bt_rc_callbacks = NULL;
355 static btrc_ctrl_callbacks_t* bt_rc_ctrl_callbacks = NULL;
356
357 // List of desired media attribute keys to request by default
358 static const uint32_t media_attr_list[] = {
359 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST,
360 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM,
361 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE,
362 AVRC_MEDIA_ATTR_ID_PLAYING_TIME, AVRC_MEDIA_ATTR_ID_COVER_ARTWORK_HANDLE};
363 static const uint8_t media_attr_list_size = sizeof(media_attr_list) / sizeof(uint32_t);
364
365 // List of desired media attribute keys to request if cover artwork is not a
366 // supported feature
367 static const uint32_t media_attr_list_no_cover_art[] = {
368 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST, AVRC_MEDIA_ATTR_ID_ALBUM,
369 AVRC_MEDIA_ATTR_ID_TRACK_NUM, AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE,
370 AVRC_MEDIA_ATTR_ID_PLAYING_TIME};
371 static const uint8_t media_attr_list_no_cover_art_size =
372 sizeof(media_attr_list_no_cover_art) / sizeof(uint32_t);
373
374 /*****************************************************************************
375 * Static functions
376 *****************************************************************************/
377
378 /*****************************************************************************
379 * Externs
380 *****************************************************************************/
381
btif_rc_get_addr_by_handle(uint8_t handle,RawAddress & rc_addr)382 void btif_rc_get_addr_by_handle(uint8_t handle, RawAddress& rc_addr) {
383 log::verbose("handle: 0x{:x}", handle);
384 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
385 if ((btif_rc_cb.rc_multi_cb[idx].rc_state != BTRC_CONNECTION_STATE_DISCONNECTED) &&
386 (btif_rc_cb.rc_multi_cb[idx].rc_handle == handle)) {
387 log::verbose("btif_rc_cb.rc_multi_cb[idx].rc_handle: 0x{:x}",
388 btif_rc_cb.rc_multi_cb[idx].rc_handle);
389 rc_addr = btif_rc_cb.rc_multi_cb[idx].rc_addr;
390 return;
391 }
392 }
393 log::error("returning NULL");
394 rc_addr = RawAddress::kEmpty;
395 return;
396 }
397
398 /*****************************************************************************
399 * Functions
400 *****************************************************************************/
alloc_device()401 static btif_rc_device_cb_t* alloc_device() {
402 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
403 if (btif_rc_cb.rc_multi_cb[idx].rc_state == BTRC_CONNECTION_STATE_DISCONNECTED) {
404 return &btif_rc_cb.rc_multi_cb[idx];
405 }
406 }
407 return NULL;
408 }
409
initialize_device(btif_rc_device_cb_t * p_dev)410 static void initialize_device(btif_rc_device_cb_t* p_dev) {
411 if (p_dev == nullptr) {
412 return;
413 }
414
415 p_dev->rc_connected = false;
416 p_dev->br_connected = false;
417 p_dev->rc_handle = 0;
418 p_dev->rc_features = 0;
419 p_dev->rc_cover_art_psm = 0;
420 p_dev->rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
421 p_dev->rc_addr = RawAddress::kEmpty;
422 p_dev->rc_pending_play = false;
423 for (int i = 0; i < MAX_CMD_QUEUE_LEN; ++i) {
424 p_dev->rc_pdu_info[i].ctype = 0;
425 p_dev->rc_pdu_info[i].label = 0;
426 p_dev->rc_pdu_info[i].is_rsp_pending = false;
427 }
428 if (p_dev->rc_supported_event_list != nullptr) {
429 list_clear(p_dev->rc_supported_event_list);
430 }
431 p_dev->rc_supported_event_list = nullptr;
432 p_dev->rc_volume = MAX_VOLUME;
433 p_dev->rc_vol_label = MAX_LABEL;
434 memset(&p_dev->rc_app_settings, 0, sizeof(btif_rc_player_app_settings_t));
435 p_dev->rc_play_status_timer = nullptr;
436 p_dev->rc_features_processed = false;
437 p_dev->rc_playing_uid = 0;
438 p_dev->rc_procedure_complete = false;
439 p_dev->peer_ct_features = 0;
440 p_dev->peer_tg_features = 0;
441 p_dev->launch_cmd_pending = 0;
442
443 // Reset the transaction set for this device. If this initialize_device() call
444 // is made due to a disconnect event, this cancels any pending timers too.
445 init_all_transactions(p_dev);
446 }
447
get_connected_device(int index)448 static btif_rc_device_cb_t* get_connected_device(int index) {
449 log::verbose("index: {}", index);
450 if (index >= BTIF_RC_NUM_CONN) {
451 log::error("can't support more than {} connections", BTIF_RC_NUM_CONN);
452 return NULL;
453 }
454 if (btif_rc_cb.rc_multi_cb[index].rc_state != BTRC_CONNECTION_STATE_CONNECTED) {
455 log::error("returning NULL");
456 return NULL;
457 }
458 return &btif_rc_cb.rc_multi_cb[index];
459 }
460
btif_rc_get_device_by_bda(const RawAddress & bd_addr)461 static btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress& bd_addr) {
462 log::verbose("bd_addr: {}", bd_addr);
463
464 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
465 if ((btif_rc_cb.rc_multi_cb[idx].rc_state != BTRC_CONNECTION_STATE_DISCONNECTED) &&
466 btif_rc_cb.rc_multi_cb[idx].rc_addr == bd_addr) {
467 return &btif_rc_cb.rc_multi_cb[idx];
468 }
469 }
470 log::error("device not found, returning NULL!");
471 return NULL;
472 }
473
btif_rc_get_device_by_handle(uint8_t handle)474 static btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) {
475 log::verbose("handle: 0x{:x}", handle);
476 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
477 if ((btif_rc_cb.rc_multi_cb[idx].rc_state != BTRC_CONNECTION_STATE_DISCONNECTED) &&
478 (btif_rc_cb.rc_multi_cb[idx].rc_handle == handle)) {
479 log::verbose("btif_rc_cb.rc_multi_cb[idx].rc_handle: 0x{:x}",
480 btif_rc_cb.rc_multi_cb[idx].rc_handle);
481 return &btif_rc_cb.rc_multi_cb[idx];
482 }
483 }
484 log::error("returning NULL");
485 return NULL;
486 }
487
get_requested_attributes_list(btif_rc_device_cb_t * p_dev)488 static const uint32_t* get_requested_attributes_list(btif_rc_device_cb_t* p_dev) {
489 return p_dev->rc_features & BTA_AV_FEAT_COVER_ARTWORK ? media_attr_list
490 : media_attr_list_no_cover_art;
491 }
492
get_requested_attributes_list_size(btif_rc_device_cb_t * p_dev)493 static uint8_t get_requested_attributes_list_size(btif_rc_device_cb_t* p_dev) {
494 return p_dev->rc_features & BTA_AV_FEAT_COVER_ARTWORK ? media_attr_list_size
495 : media_attr_list_no_cover_art_size;
496 }
497
fill_pdu_queue(int index,uint8_t ctype,uint8_t label,bool pending,btif_rc_device_cb_t * p_dev)498 static void fill_pdu_queue(int index, uint8_t ctype, uint8_t label, bool pending,
499 btif_rc_device_cb_t* p_dev) {
500 p_dev->rc_pdu_info[index].ctype = ctype;
501 p_dev->rc_pdu_info[index].label = label;
502 p_dev->rc_pdu_info[index].is_rsp_pending = pending;
503 }
504
fill_avrc_attr_entry(tAVRC_ATTR_ENTRY * attr_vals,int num_attrs,btrc_element_attr_val_t * p_attrs)505 static void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs,
506 btrc_element_attr_val_t* p_attrs) {
507 for (int attr_cnt = 0; attr_cnt < num_attrs; attr_cnt++) {
508 attr_vals[attr_cnt].attr_id = p_attrs[attr_cnt].attr_id;
509 attr_vals[attr_cnt].name.charset_id = AVRC_CHARSET_ID_UTF8;
510 attr_vals[attr_cnt].name.str_len = (uint16_t)strlen((char*)p_attrs[attr_cnt].text);
511 attr_vals[attr_cnt].name.p_str = p_attrs[attr_cnt].text;
512 log::verbose("attr_id: 0x{:x}, charset_id: 0x{:x}, str_len: {}, str: {}",
513 (unsigned int)attr_vals[attr_cnt].attr_id, attr_vals[attr_cnt].name.charset_id,
514 attr_vals[attr_cnt].name.str_len,
515 reinterpret_cast<char const*>(attr_vals[attr_cnt].name.p_str));
516 }
517 }
518
handle_rc_ctrl_features_all(btif_rc_device_cb_t * p_dev)519 static void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) {
520 if (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCTG) &&
521 (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCCT) ||
522 !(p_dev->peer_tg_features & BTA_AV_FEAT_ADV_CTRL))) {
523 return;
524 }
525
526 int rc_features = 0;
527
528 log::verbose(
529 "peer_tg_features: 0x{:x}, rc_features_processed={}, connected={}, "
530 "peer_is_src:{}",
531 p_dev->peer_tg_features, p_dev->rc_features_processed,
532 btif_av_is_connected_addr(p_dev->rc_addr, A2dpType::kSink),
533 btif_av_peer_is_source(p_dev->rc_addr));
534
535 if ((p_dev->peer_tg_features & BTA_AV_FEAT_ADV_CTRL) &&
536 (p_dev->peer_tg_features & BTA_AV_FEAT_RCCT)) {
537 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
538 }
539
540 if ((p_dev->peer_tg_features & BTA_AV_FEAT_METADATA) &&
541 (p_dev->peer_tg_features & BTA_AV_FEAT_VENDOR) && (p_dev->rc_features_processed != true)) {
542 rc_features |= BTRC_FEAT_METADATA;
543
544 /* Mark rc features processed to avoid repeating
545 * the AVRCP procedure every time on receiving this
546 * update.
547 */
548 p_dev->rc_features_processed = true;
549 }
550
551 if (btif_av_is_connected_addr(p_dev->rc_addr, A2dpType::kSink)) {
552 if (btif_av_peer_is_source(p_dev->rc_addr)) {
553 p_dev->rc_features = p_dev->peer_tg_features;
554 if ((p_dev->peer_tg_features & BTA_AV_FEAT_METADATA) &&
555 (p_dev->peer_tg_features & BTA_AV_FEAT_VENDOR)) {
556 getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
557 }
558 }
559 } else {
560 log::verbose("{} is not connected, pending", p_dev->rc_addr);
561 p_dev->launch_cmd_pending |= (RC_PENDING_ACT_GET_CAP | RC_PENDING_ACT_REG_VOL);
562 }
563
564 /* Add browsing feature capability */
565 if (p_dev->peer_tg_features & BTA_AV_FEAT_BROWSE) {
566 rc_features |= BTRC_FEAT_BROWSE;
567 }
568
569 /* Add cover art feature capability */
570 if (p_dev->peer_tg_features & BTA_AV_FEAT_COVER_ARTWORK) {
571 rc_features |= BTRC_FEAT_COVER_ARTWORK;
572 }
573
574 if (bt_rc_ctrl_callbacks != NULL) {
575 log::verbose("Update rc features to CTRL: {}", rc_features);
576 do_in_jni_thread(
577 base::BindOnce(bt_rc_ctrl_callbacks->getrcfeatures_cb, p_dev->rc_addr, rc_features));
578 }
579 }
580
handle_rc_ctrl_features(btif_rc_device_cb_t * p_dev)581 static void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) {
582 if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
583 handle_rc_ctrl_features_all(p_dev);
584 return;
585 }
586
587 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG) &&
588 (!(p_dev->rc_features & BTA_AV_FEAT_RCCT) || !(p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL))) {
589 return;
590 }
591
592 int rc_features = 0;
593
594 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) && (p_dev->rc_features & BTA_AV_FEAT_RCCT)) {
595 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
596 }
597
598 if (p_dev->rc_features & BTA_AV_FEAT_METADATA) {
599 rc_features |= BTRC_FEAT_METADATA;
600 }
601
602 if ((p_dev->rc_features & BTA_AV_FEAT_VENDOR) && (p_dev->rc_features_processed != true)) {
603 /* Mark rc features processed to avoid repeating
604 * the AVRCP procedure every time on receiving this
605 * update.
606 */
607 p_dev->rc_features_processed = true;
608 if (btif_av_is_sink_enabled()) {
609 getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
610 }
611 }
612
613 /* Add browsing feature capability */
614 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) {
615 rc_features |= BTRC_FEAT_BROWSE;
616 }
617
618 /* Add cover art feature capability */
619 if (p_dev->rc_features & BTA_AV_FEAT_COVER_ARTWORK) {
620 rc_features |= BTRC_FEAT_COVER_ARTWORK;
621 }
622
623 log::verbose("Update rc features to CTRL: {}", rc_features);
624 do_in_jni_thread(
625 base::BindOnce(bt_rc_ctrl_callbacks->getrcfeatures_cb, p_dev->rc_addr, rc_features));
626 }
btif_rc_check_pending_cmd(const RawAddress & peer_address)627 void btif_rc_check_pending_cmd(const RawAddress& peer_address) {
628 btif_rc_device_cb_t* p_dev = NULL;
629 p_dev = btif_rc_get_device_by_bda(peer_address);
630 if (p_dev == NULL) {
631 log::error("p_dev NULL");
632 return;
633 }
634
635 log::verbose(
636 "launch_cmd_pending={}, rc_connected={}, peer_ct_features=0x{:x}, "
637 "peer_tg_features=0x{:x}",
638 p_dev->launch_cmd_pending, p_dev->rc_connected, p_dev->peer_ct_features,
639 p_dev->peer_tg_features);
640 if (p_dev->launch_cmd_pending && p_dev->rc_connected) {
641 if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_REG_VOL) &&
642 btif_av_peer_is_sink(p_dev->rc_addr)) {
643 if (bluetooth::avrcp::AvrcpService::Get() != nullptr) {
644 bluetooth::avrcp::AvrcpService::Get()->RegisterVolChanged(peer_address);
645 }
646 }
647 if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_GET_CAP) &&
648 btif_av_peer_is_source(p_dev->rc_addr)) {
649 p_dev->rc_features = p_dev->peer_tg_features;
650 getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
651 }
652 if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_REPORT_CONN) &&
653 btif_av_peer_is_source(p_dev->rc_addr)) {
654 if (bt_rc_ctrl_callbacks != NULL) {
655 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true, false,
656 p_dev->rc_addr));
657 }
658 }
659 }
660 p_dev->launch_cmd_pending = 0;
661 }
662
handle_rc_ctrl_psm(btif_rc_device_cb_t * p_dev)663 static void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) {
664 uint16_t cover_art_psm = p_dev->rc_cover_art_psm;
665 log::verbose("Update rc cover art psm to CTRL: {}", cover_art_psm);
666 if (bt_rc_ctrl_callbacks != NULL) {
667 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->get_cover_art_psm_cb, p_dev->rc_addr,
668 cover_art_psm));
669 }
670 }
671
handle_rc_features(btif_rc_device_cb_t * p_dev)672 static void handle_rc_features(btif_rc_device_cb_t* p_dev) {
673 log::assert_that(bt_rc_callbacks != nullptr, "assert failed: bt_rc_callbacks != nullptr");
674
675 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
676 RawAddress avdtp_source_active_peer_addr = btif_av_source_active_peer();
677 RawAddress avdtp_sink_active_peer_addr = btif_av_sink_active_peer();
678
679 log::verbose(
680 "AVDTP Source Active Peer Address: {} AVDTP Sink Active Peer Address: {} "
681 "AVCTP address: {}",
682 avdtp_source_active_peer_addr, avdtp_sink_active_peer_addr, p_dev->rc_addr);
683
684 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &p_dev->rc_addr) ||
685 absolute_volume_disabled() ||
686 (avdtp_source_active_peer_addr != p_dev->rc_addr &&
687 avdtp_sink_active_peer_addr != p_dev->rc_addr)) {
688 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
689 }
690
691 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) {
692 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_BROWSE);
693 }
694
695 if (p_dev->rc_features & BTA_AV_FEAT_METADATA) {
696 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_METADATA);
697 }
698
699 if (!avrcp_absolute_volume_is_enabled()) {
700 return;
701 }
702
703 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) && (p_dev->rc_features & BTA_AV_FEAT_RCTG)) {
704 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_ABSOLUTE_VOLUME);
705 }
706
707 log::verbose("rc_features: 0x{:x}", rc_features);
708 HAL_CBACK(bt_rc_callbacks, remote_features_cb, p_dev->rc_addr, rc_features);
709
710 log::verbose("Checking for feature flags in btif_rc_handler with label: {}", p_dev->rc_vol_label);
711 // Register for volume change on connect
712 if (p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL && p_dev->rc_features & BTA_AV_FEAT_RCTG) {
713 register_volumechange(p_dev);
714 }
715 }
716
717 /***************************************************************************
718 * Function handle_rc_browse_connect
719 *
720 * - Argument: tBTA_AV_RC_OPEN browse RC open data structure
721 *
722 * - Description: browse RC connection event handler
723 *
724 ***************************************************************************/
handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN * p_rc_br_open)725 static void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) {
726 log::verbose("rc_handle {} status {}", p_rc_br_open->rc_handle, p_rc_br_open->status);
727 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(p_rc_br_open->rc_handle);
728
729 if (!p_dev) {
730 log::error("p_dev is null");
731 return;
732 }
733
734 /* check that we are already connected to this address since being connected
735 * to a browse when not connected to the control channel over AVRCP is
736 * probably not preferred anyways. */
737 if (p_rc_br_open->status == BTA_AV_SUCCESS) {
738 p_dev->br_connected = true;
739 if (btif_av_src_sink_coexist_enabled()) {
740 if (btif_av_peer_is_connected_source(p_dev->rc_addr)) {
741 if (bt_rc_ctrl_callbacks != NULL) {
742 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true, true,
743 p_dev->rc_addr));
744 }
745 } else {
746 p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN;
747 log::verbose("pending rc browse connection event");
748 }
749 } else {
750 if (bt_rc_ctrl_callbacks != NULL) {
751 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true, true,
752 p_dev->rc_addr));
753 } else {
754 log::warn("bt_rc_ctrl_callbacks is null.");
755 }
756 }
757 }
758 }
759
760 /***************************************************************************
761 * Function handle_rc_connect
762 *
763 * - Argument: tBTA_AV_RC_OPEN RC open data structure
764 *
765 * - Description: RC connection event handler
766 *
767 ***************************************************************************/
handle_rc_connect(tBTA_AV_RC_OPEN * p_rc_open)768 static void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
769 log::verbose("rc_handle: {}", p_rc_open->rc_handle);
770
771 btif_rc_device_cb_t* p_dev = alloc_device();
772 if (p_dev == NULL) {
773 log::error("p_dev is NULL");
774 return;
775 }
776
777 if (!(p_rc_open->status == BTA_AV_SUCCESS)) {
778 log::error("Connect failed with error code: {}", p_rc_open->status);
779 p_dev->rc_connected = false;
780 BTA_AvCloseRc(p_rc_open->rc_handle);
781 p_dev->rc_handle = 0;
782 p_dev->rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
783 p_dev->rc_features = 0;
784 p_dev->peer_ct_features = 0;
785 p_dev->peer_tg_features = 0;
786 p_dev->launch_cmd_pending = 0;
787 p_dev->rc_vol_label = MAX_LABEL;
788 p_dev->rc_volume = MAX_VOLUME;
789 p_dev->rc_addr = RawAddress::kEmpty;
790 return;
791 }
792
793 // check if already some RC is connected
794 if (p_dev->rc_connected) {
795 log::error("Got RC OPEN in connected state, Connected RC: {} and Current RC: {}",
796 p_dev->rc_handle, p_rc_open->rc_handle);
797 if (p_dev->rc_handle != p_rc_open->rc_handle && p_dev->rc_addr != p_rc_open->peer_addr) {
798 log::verbose("Got RC connected for some other handle");
799 BTA_AvCloseRc(p_rc_open->rc_handle);
800 return;
801 }
802 }
803 p_dev->rc_addr = p_rc_open->peer_addr;
804 p_dev->rc_features = p_rc_open->peer_features;
805 p_dev->peer_ct_features = p_rc_open->peer_ct_features;
806 p_dev->peer_tg_features = p_rc_open->peer_tg_features;
807 p_dev->rc_cover_art_psm = p_rc_open->cover_art_psm;
808 p_dev->rc_vol_label = MAX_LABEL;
809 p_dev->rc_volume = MAX_VOLUME;
810
811 log::verbose(
812 "handle_rc_connect in features={:#x}, out features={:#x}, "
813 "ct_feature={:#x}, tg_feature={:#x}, cover art psm={:#x}",
814 p_rc_open->peer_features, p_dev->rc_features, p_dev->peer_ct_features,
815 p_dev->peer_tg_features, p_dev->rc_cover_art_psm);
816
817 p_dev->rc_connected = true;
818 p_dev->rc_handle = p_rc_open->rc_handle;
819 p_dev->rc_state = BTRC_CONNECTION_STATE_CONNECTED;
820
821 p_dev->rc_playing_uid = RC_INVALID_TRACK_ID;
822
823 if (btif_av_src_sink_coexist_enabled() && !btif_av_peer_is_connected_source(p_dev->rc_addr)) {
824 p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN;
825 log::verbose("pending rc connection event");
826 return;
827 }
828 if (bt_rc_ctrl_callbacks != NULL) {
829 do_in_jni_thread(
830 base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true, false, p_dev->rc_addr));
831 /* report connection state if remote device is AVRCP target */
832 handle_rc_ctrl_features(p_dev);
833
834 /* report psm if remote device is AVRCP target */
835 handle_rc_ctrl_psm(p_dev);
836 }
837 }
838
839 /***************************************************************************
840 * Function handle_rc_disconnect
841 *
842 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
843 *
844 * - Description: RC disconnection event handler
845 *
846 ***************************************************************************/
handle_rc_disconnect(tBTA_AV_RC_CLOSE * p_rc_close)847 static void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) {
848 btif_rc_device_cb_t* p_dev = NULL;
849 log::verbose("rc_handle: {}", p_rc_close->rc_handle);
850
851 p_dev = btif_rc_get_device_by_handle(p_rc_close->rc_handle);
852 if (p_dev == NULL) {
853 log::error("Got disconnect from invalid rc handle");
854 return;
855 }
856
857 if (p_rc_close->rc_handle != p_dev->rc_handle && p_dev->rc_addr != p_rc_close->peer_addr) {
858 log::error("Got disconnect of unknown device");
859 return;
860 }
861
862 /* Report connection state if device is AVRCP target */
863 if (bt_rc_ctrl_callbacks != NULL) {
864 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, false, false,
865 p_dev->rc_addr));
866 }
867
868 // We'll re-initialize the device state back to what it looked like before
869 // the connection. This will free ongoing transaction labels and clear any
870 // running label timers
871 initialize_device(p_dev);
872 }
873
874 /***************************************************************************
875 * Function handle_rc_passthrough_cmd
876 *
877 * - Argument: tBTA_AV_RC rc_id remote control command ID
878 * tBTA_AV_STATE key_state status of key press
879 *
880 * - Description: Remote control command handler
881 *
882 ***************************************************************************/
handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD * p_remote_cmd)883 static void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) {
884 if (p_remote_cmd == NULL) {
885 log::error("No remote command!");
886 return;
887 }
888
889 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(p_remote_cmd->rc_handle);
890 if (p_dev == NULL) {
891 log::error("Got passthrough command from invalid rc handle");
892 return;
893 }
894
895 log::verbose("p_remote_cmd->rc_id: {}", p_remote_cmd->rc_id);
896
897 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up
898 * this PLAY */
899 if ((p_remote_cmd->rc_id == AVRC_ID_PLAY) && (!btif_av_is_connected(A2dpType::kSink))) {
900 if (p_remote_cmd->key_state == AVRC_STATE_PRESS) {
901 log::warn("AVDT not open, queuing the PLAY command");
902 p_dev->rc_pending_play = true;
903 }
904 return;
905 }
906
907 /* If we previously queued a play and we get a PAUSE, clear it. */
908 if ((p_remote_cmd->rc_id == AVRC_ID_PAUSE) && (p_dev->rc_pending_play)) {
909 log::warn("Clear the pending PLAY on PAUSE received");
910 p_dev->rc_pending_play = false;
911 return;
912 }
913
914 if ((p_remote_cmd->rc_id == AVRC_ID_STOP) && (!btif_av_stream_started_ready(A2dpType::kSink))) {
915 log::warn("Stream suspended, ignore STOP cmd");
916 return;
917 }
918
919 int pressed = (p_remote_cmd->key_state == AVRC_STATE_PRESS) ? 1 : 0;
920
921 /* pass all commands up */
922 log::verbose("rc_features: {}, cmd->rc_id: {}, pressed: {}", p_dev->rc_features,
923 p_remote_cmd->rc_id, pressed);
924 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed, p_dev->rc_addr);
925 }
926
927 /***************************************************************************
928 * Function handle_rc_passthrough_rsp
929 *
930 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
931 *
932 * - Description: Remote control passthrough response handler
933 *
934 ***************************************************************************/
handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)935 static void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) {
936 btif_rc_device_cb_t* p_dev = NULL;
937
938 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle);
939 if (p_dev == NULL) {
940 log::error("passthrough response for Invalid rc handle");
941 return;
942 }
943
944 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG)) {
945 log::error("DUT does not support AVRCP controller role");
946 return;
947 }
948
949 const char* status = (p_remote_rsp->key_state == 1) ? "released" : "pressed";
950 log::verbose("rc_id: {} state: {}", p_remote_rsp->rc_id, status);
951
952 release_transaction(p_dev, p_remote_rsp->label);
953 if (bt_rc_ctrl_callbacks != NULL) {
954 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->passthrough_rsp_cb, p_dev->rc_addr,
955 p_remote_rsp->rc_id, p_remote_rsp->key_state));
956 }
957 }
958
959 /***************************************************************************
960 * Function handle_rc_vendorunique_rsp
961 *
962 * - Argument: tBTA_AV_REMOTE_RSP command response
963 *
964 * - Description: Remote control vendor unique response handler
965 *
966 ***************************************************************************/
handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)967 static void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) {
968 btif_rc_device_cb_t* p_dev = NULL;
969 const char* status;
970 uint8_t vendor_id = 0;
971
972 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle);
973 if (p_dev == NULL) {
974 log::error("Got vendorunique rsp from invalid rc handle");
975 return;
976 }
977
978 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
979 int key_state;
980 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE) {
981 status = "released";
982 key_state = 1;
983 } else {
984 status = "pressed";
985 key_state = 0;
986 }
987
988 if (p_remote_rsp->len > 0 && p_remote_rsp->p_data != NULL) {
989 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN) {
990 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN - 1];
991 }
992 osi_free_and_reset((void**)&p_remote_rsp->p_data);
993 }
994 log::verbose("vendor_id: {} status: {}", vendor_id, status);
995
996 release_transaction(p_dev, p_remote_rsp->label);
997 do_in_jni_thread(
998 base::BindOnce(bt_rc_ctrl_callbacks->groupnavigation_rsp_cb, vendor_id, key_state));
999 } else {
1000 log::error("Remote does not support AVRCP TG role");
1001 }
1002 }
1003
1004 /***************************************************************************
1005 * Function handle_rc_metamsg_cmd
1006 *
1007 * - Argument: tBTA_AV_VENDOR Structure containing the received
1008 * metamsg command
1009 *
1010 * - Description: Remote control metamsg command handler (AVRCP 1.3)
1011 *
1012 ***************************************************************************/
handle_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)1013 static void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
1014 /* Parse the metamsg command and pass it on to BTL-IFS */
1015 uint8_t scratch_buf[512] = {0};
1016 tAVRC_COMMAND avrc_command = {0};
1017 tAVRC_STS status;
1018 btif_rc_device_cb_t* p_dev = NULL;
1019
1020 if (NULL == pmeta_msg) {
1021 log::verbose("Exiting as pmeta_msg is NULL");
1022 return;
1023 }
1024
1025 if (NULL == pmeta_msg->p_msg) {
1026 log::verbose("Exiting as pmeta_msg->p_msg is NULL");
1027 return;
1028 }
1029
1030 log::verbose("pmeta_msg: opcode: {:x}, code: {:x}", pmeta_msg->p_msg->hdr.opcode,
1031 pmeta_msg->code);
1032
1033 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
1034 if (p_dev == NULL) {
1035 log::error("Meta msg event for Invalid rc handle");
1036 return;
1037 }
1038
1039 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR &&
1040 pmeta_msg->p_msg->hdr.opcode != AVRC_OP_BROWSE) {
1041 log::warn("Invalid opcode: {:x}", pmeta_msg->p_msg->hdr.opcode);
1042 return;
1043 }
1044
1045 if (pmeta_msg->len < 3) {
1046 log::warn("Invalid length. opcode: 0x{:x}, len: 0x{:x}", pmeta_msg->p_msg->hdr.opcode,
1047 pmeta_msg->len);
1048 return;
1049 }
1050
1051 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) {
1052 {
1053 rc_transaction_t* transaction = NULL;
1054 transaction = get_transaction_by_lbl(p_dev, pmeta_msg->label);
1055 if (transaction != NULL) {
1056 handle_rc_metamsg_rsp(pmeta_msg, p_dev);
1057 } else {
1058 log::verbose("Discard vendor dependent rsp. code: {} label: {}.", pmeta_msg->code,
1059 pmeta_msg->label);
1060 }
1061 return;
1062 }
1063 }
1064
1065 status = AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
1066 log::verbose("Received vendor command.code,PDU and label: {}, {}, {}", pmeta_msg->code,
1067 avrc_command.cmd.pdu, pmeta_msg->label);
1068
1069 if (status != AVRC_STS_NO_ERROR) {
1070 /* return error */
1071 log::warn("Error in parsing received metamsg command. status: 0x{:02x}", status);
1072 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status,
1073 pmeta_msg->p_msg->hdr.opcode);
1074 } else {
1075 /* if RegisterNotification, add it to our registered queue */
1076
1077 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
1078 uint8_t event_id = avrc_command.reg_notif.event_id;
1079
1080 log::verbose(
1081 "New register notification received.event_id: {}, label: 0x{:x}, "
1082 "code: {:x}",
1083 dump_rc_notification_event_id(event_id), pmeta_msg->label, pmeta_msg->code);
1084 p_dev->rc_notif[event_id - 1].bNotify = true;
1085 p_dev->rc_notif[event_id - 1].label = pmeta_msg->label;
1086 /* this is sink(tg) feature, so it should not handle here */
1087 if (btif_av_both_enable() && event_id == AVRC_EVT_VOLUME_CHANGE) {
1088 return;
1089 }
1090 }
1091
1092 /* this is sink(tg) feature, so it should not handle here */
1093 if (btif_av_both_enable() && avrc_command.cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) {
1094 return;
1095 }
1096 log::verbose("Passing received metamsg command to app. pdu: {}",
1097 dump_rc_pdu(avrc_command.cmd.pdu));
1098
1099 /* Since handle_rc_metamsg_cmd() itself is called from
1100 *btif context, no context switching is required. Invoke
1101 * btif_rc_upstreams_evt directly from here. */
1102 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
1103 pmeta_msg->label, p_dev);
1104 }
1105 }
1106
1107 /***************************************************************************
1108 **
1109 ** Function btif_rc_handler
1110 **
1111 ** Description RC event handler
1112 **
1113 ***************************************************************************/
btif_rc_handler(tBTA_AV_EVT event,tBTA_AV * p_data)1114 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) {
1115 log::verbose("event: {}", dump_rc_event(event));
1116 btif_rc_device_cb_t* p_dev = NULL;
1117 switch (event) {
1118 case BTA_AV_RC_OPEN_EVT: {
1119 log::verbose("Peer_features: 0x{:x} Cover Art PSM: 0x{:x}", p_data->rc_open.peer_features,
1120 p_data->rc_open.cover_art_psm);
1121 handle_rc_connect(&(p_data->rc_open));
1122 } break;
1123
1124 case BTA_AV_RC_BROWSE_OPEN_EVT: {
1125 /* tell the UL that we have connection to browse channel and that
1126 * browse commands can be directed accordingly. */
1127 handle_rc_browse_connect(&p_data->rc_browse_open);
1128 } break;
1129
1130 case BTA_AV_RC_CLOSE_EVT: {
1131 handle_rc_disconnect(&(p_data->rc_close));
1132 } break;
1133
1134 case BTA_AV_RC_BROWSE_CLOSE_EVT: {
1135 log::verbose("BTA_AV_RC_BROWSE_CLOSE_EVT");
1136 } break;
1137
1138 case BTA_AV_REMOTE_CMD_EVT: {
1139 if (bt_rc_callbacks != NULL) {
1140 log::verbose("rc_id: 0x{:x} key_state: {}", p_data->remote_cmd.rc_id,
1141 p_data->remote_cmd.key_state);
1142 handle_rc_passthrough_cmd(&p_data->remote_cmd);
1143 } else {
1144 log::error("AVRCP TG role not up, drop passthrough commands");
1145 }
1146 } break;
1147
1148 case BTA_AV_REMOTE_RSP_EVT: {
1149 log::verbose("RSP: rc_id: 0x{:x} key_state: {}", p_data->remote_rsp.rc_id,
1150 p_data->remote_rsp.key_state);
1151
1152 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR) {
1153 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1154 } else {
1155 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1156 }
1157 } break;
1158
1159 case BTA_AV_RC_FEAT_EVT: {
1160 log::verbose("Peer_features: {:x}", p_data->rc_feat.peer_features);
1161 p_dev = btif_rc_get_device_by_handle(p_data->rc_feat.rc_handle);
1162 if (p_dev == NULL) {
1163 log::error("RC Feature event for Invalid rc handle");
1164 break;
1165 }
1166 log::verbose("peer_ct_features:0x{:x}, peer_tg_features=0x{:x}",
1167 p_data->rc_feat.peer_ct_features, p_data->rc_feat.peer_tg_features);
1168 if (btif_av_src_sink_coexist_enabled() &&
1169 (p_dev->peer_ct_features == p_data->rc_feat.peer_ct_features) &&
1170 (p_dev->peer_tg_features == p_data->rc_feat.peer_tg_features)) {
1171 log::error("do SDP twice, no need callback rc_feature to framework again");
1172 break;
1173 }
1174
1175 p_dev->peer_ct_features = p_data->rc_feat.peer_ct_features;
1176 p_dev->peer_tg_features = p_data->rc_feat.peer_tg_features;
1177 p_dev->rc_features = p_data->rc_feat.peer_features;
1178 if (bt_rc_callbacks != NULL) {
1179 handle_rc_features(p_dev);
1180 }
1181
1182 if ((p_dev->rc_connected) && (bt_rc_ctrl_callbacks != NULL)) {
1183 handle_rc_ctrl_features(p_dev);
1184 }
1185 } break;
1186
1187 case BTA_AV_RC_PSM_EVT: {
1188 log::verbose("Peer cover art PSM: {:x}", p_data->rc_cover_art_psm.cover_art_psm);
1189 p_dev = btif_rc_get_device_by_handle(p_data->rc_cover_art_psm.rc_handle);
1190 if (p_dev == NULL) {
1191 log::error("RC PSM event for Invalid rc handle");
1192 break;
1193 }
1194
1195 p_dev->rc_cover_art_psm = p_data->rc_cover_art_psm.cover_art_psm;
1196 if ((p_dev->rc_connected) && (bt_rc_ctrl_callbacks != NULL)) {
1197 handle_rc_ctrl_psm(p_dev);
1198 }
1199 } break;
1200
1201 case BTA_AV_META_MSG_EVT: {
1202 if (bt_rc_callbacks != NULL) {
1203 log::verbose("BTA_AV_META_MSG_EVT code: {} label: {}", p_data->meta_msg.code,
1204 p_data->meta_msg.label);
1205 log::verbose("company_id: 0x{:x} len: {} handle: {}", p_data->meta_msg.company_id,
1206 p_data->meta_msg.len, p_data->meta_msg.rc_handle);
1207
1208 /* handle the metamsg command */
1209 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1210
1211 /* Free the Memory allocated for tAVRC_MSG */
1212 } else if (bt_rc_ctrl_callbacks != NULL) {
1213 /* This is case of Sink + CT + TG(for abs vol)) */
1214 log::verbose("BTA_AV_META_MSG_EVT code:{} label:{} opcode {} ctype {}",
1215 p_data->meta_msg.code, p_data->meta_msg.label,
1216 p_data->meta_msg.p_msg->hdr.opcode, p_data->meta_msg.p_msg->hdr.ctype);
1217 log::verbose("company_id:0x{:x} len:{} handle:{}", p_data->meta_msg.company_id,
1218 p_data->meta_msg.len, p_data->meta_msg.rc_handle);
1219 switch (p_data->meta_msg.p_msg->hdr.opcode) {
1220 case AVRC_OP_VENDOR:
1221 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL) &&
1222 (p_data->meta_msg.code <= AVRC_RSP_INTERIM)) {
1223 /* Its a response */
1224 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1225 } else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ) {
1226 /* Its a command */
1227 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1228 }
1229 break;
1230
1231 case AVRC_OP_BROWSE:
1232 if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_CMD) {
1233 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1234 } else if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_RSP) {
1235 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1236 }
1237 break;
1238 }
1239 } else {
1240 log::error("Neither CTRL, nor TG is up, drop meta commands");
1241 }
1242 } break;
1243
1244 default:
1245 log::verbose("Unhandled RC event : 0x{:x}", event);
1246 }
1247 }
1248
btif_rc_is_connected_peer(const RawAddress & peer_addr)1249 bool btif_rc_is_connected_peer(const RawAddress& peer_addr) {
1250 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1251 btif_rc_device_cb_t* p_dev = get_connected_device(idx);
1252 if (p_dev != NULL && p_dev->rc_connected && peer_addr == p_dev->rc_addr) {
1253 return true;
1254 }
1255 }
1256 return false;
1257 }
1258
1259 /***************************************************************************
1260 **
1261 ** Function btif_rc_get_connected_peer_handle
1262 **
1263 ** Description Fetches the connected headset's handle if any
1264 **
1265 ***************************************************************************/
btif_rc_get_connected_peer_handle(const RawAddress & peer_addr)1266 uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr) {
1267 btif_rc_device_cb_t* p_dev = NULL;
1268 p_dev = btif_rc_get_device_by_bda(peer_addr);
1269
1270 if (p_dev == NULL) {
1271 log::error("p_dev NULL");
1272 return BTRC_HANDLE_NONE;
1273 }
1274 return p_dev->rc_handle;
1275 }
1276
1277 /***************************************************************************
1278 **
1279 ** Function btif_rc_check_handle_pending_play
1280 **
1281 ** Description Clears the queued PLAY command. if |bSendToApp| is true,
1282 ** forwards to app
1283 **
1284 ***************************************************************************/
1285
1286 /* clear the queued PLAY command. if |bSendToApp| is true, forward to app */
btif_rc_check_handle_pending_play(const RawAddress & peer_addr,bool bSendToApp)1287 void btif_rc_check_handle_pending_play(const RawAddress& peer_addr, bool bSendToApp) {
1288 btif_rc_device_cb_t* p_dev = NULL;
1289 p_dev = btif_rc_get_device_by_bda(peer_addr);
1290
1291 if (p_dev == NULL) {
1292 log::error("p_dev NULL");
1293 return;
1294 }
1295
1296 log::verbose("bSendToApp: {}", bSendToApp);
1297 if (p_dev->rc_pending_play) {
1298 if (bSendToApp) {
1299 tBTA_AV_REMOTE_CMD remote_cmd;
1300 log::verbose("Sending queued PLAYED event to app");
1301
1302 memset(&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1303 remote_cmd.rc_handle = p_dev->rc_handle;
1304 remote_cmd.rc_id = AVRC_ID_PLAY;
1305 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1306 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1307
1308 /* delay sending to app, else there is a timing issue in the framework,
1309 ** which causes the audio to be on th device's speaker. Delay between
1310 ** OPEN & RC_PLAYs
1311 */
1312 sleep_ms(200);
1313 /* send to app - both PRESSED & RELEASED */
1314 remote_cmd.key_state = AVRC_STATE_PRESS;
1315 handle_rc_passthrough_cmd(&remote_cmd);
1316
1317 sleep_ms(100);
1318
1319 remote_cmd.key_state = AVRC_STATE_RELEASE;
1320 handle_rc_passthrough_cmd(&remote_cmd);
1321 }
1322 p_dev->rc_pending_play = false;
1323 }
1324 }
1325
1326 /* Generic reject response */
send_reject_response(uint8_t rc_handle,uint8_t label,uint8_t pdu,uint8_t status,uint8_t opcode)1327 static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu, uint8_t status,
1328 uint8_t opcode) {
1329 uint8_t ctype = AVRC_RSP_REJ;
1330 tAVRC_RESPONSE avrc_rsp;
1331 BT_HDR* p_msg = NULL;
1332 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1333
1334 avrc_rsp.rsp.opcode = opcode;
1335 avrc_rsp.rsp.pdu = pdu;
1336 avrc_rsp.rsp.status = status;
1337
1338 status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg);
1339
1340 if (status != AVRC_STS_NO_ERROR) {
1341 log::error("status not AVRC_STS_NO_ERROR");
1342 return;
1343 }
1344
1345 log::verbose("Sending error notification to handle: {}. pdu: {},status: 0x{:02x}", rc_handle,
1346 dump_rc_pdu(pdu), status);
1347 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1348 }
1349
1350 /***************************************************************************
1351 * Function get_rsp_type_code
1352 *
1353 * - Argument: status
1354 * - Description: Returns response type codes for particular command code and
1355 * status.
1356 *
1357 ***************************************************************************/
get_rsp_type_code(tAVRC_STS status,tBTA_AV_CODE code)1358 static tBTA_AV_CODE get_rsp_type_code(tAVRC_STS status, tBTA_AV_CODE code) {
1359 if (status != AVRC_STS_NO_ERROR) {
1360 return AVRC_RSP_REJ;
1361 }
1362
1363 if (code < AVRC_RSP_NOT_IMPL) {
1364 if (code == AVRC_CMD_NOTIF) {
1365 return AVRC_RSP_INTERIM;
1366 }
1367
1368 if (code == AVRC_CMD_STATUS) {
1369 return AVRC_RSP_IMPL_STBL;
1370 }
1371
1372 return AVRC_RSP_ACCEPT;
1373 }
1374
1375 return code;
1376 }
1377
1378 /***************************************************************************
1379 * Function send_metamsg_rsp
1380 *
1381 * - Argument:
1382 * p_dev Dev pointer
1383 * index Command index (= -1 if not used)
1384 * label Label of the RC response
1385 * code Response type
1386 * pmetamsg_resp Vendor response
1387 *
1388 * - Description: Remote control metamsg response handler
1389 *
1390 ***************************************************************************/
send_metamsg_rsp(btif_rc_device_cb_t * p_dev,int index,uint8_t label,tBTA_AV_CODE code,tAVRC_RESPONSE * pmetamsg_resp)1391 static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index, uint8_t label,
1392 tBTA_AV_CODE code, tAVRC_RESPONSE* pmetamsg_resp) {
1393 uint8_t ctype;
1394
1395 if (p_dev == NULL) {
1396 log::error("p_dev NULL");
1397 return;
1398 }
1399
1400 if (pmetamsg_resp == NULL) {
1401 log::warn("Invalid response received from application");
1402 return;
1403 }
1404
1405 log::verbose("rc_handle: {}, index: {}, label: {}, code: 0x{:02x}, pdu: {}", p_dev->rc_handle,
1406 index, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1407
1408 if (index >= 0 && !p_dev->rc_pdu_info[index].is_rsp_pending) {
1409 log::error("is_rsp_pending false, returning");
1410 return;
1411 }
1412
1413 ctype = get_rsp_type_code(pmetamsg_resp->rsp.status, code);
1414
1415 /* if response is for register_notification, make sure the rc has
1416 actually registered for this */
1417 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) &&
1418 ((code == AVRC_RSP_CHANGED) || (code == AVRC_RSP_INTERIM))) {
1419 bool bSent = false;
1420 uint8_t event_id = pmetamsg_resp->reg_notif.event_id;
1421 bool bNotify = (p_dev->rc_connected) && (p_dev->rc_notif[event_id - 1].bNotify);
1422
1423 /* de-register this notification for a CHANGED response */
1424 p_dev->rc_notif[event_id - 1].bNotify = false;
1425 log::verbose("rc_handle: {}. event_id: 0x{:02} bNotify: {}", p_dev->rc_handle, event_id,
1426 bNotify);
1427 if (bNotify) {
1428 BT_HDR* p_msg = NULL;
1429 tAVRC_STS status;
1430
1431 if (AVRC_STS_NO_ERROR ==
1432 (status = AVRC_BldResponse(p_dev->rc_handle, pmetamsg_resp, &p_msg))) {
1433 log::verbose("Sending notification to rc_handle: {}. event_id: 0x{:02}", p_dev->rc_handle,
1434 event_id);
1435 bSent = true;
1436 BTA_AvMetaRsp(p_dev->rc_handle, p_dev->rc_notif[event_id - 1].label, ctype, p_msg);
1437 } else {
1438 log::warn("failed to build metamsg response. status: 0x{:02x}", status);
1439 }
1440 }
1441
1442 if (!bSent) {
1443 log::verbose(
1444 "Notification not sent, as there are no RC connections or the CT has "
1445 "not subscribed for event_id: {}",
1446 dump_rc_notification_event_id(event_id));
1447 }
1448 } else {
1449 /* All other commands go here */
1450
1451 BT_HDR* p_msg = NULL;
1452 tAVRC_STS status;
1453
1454 status = AVRC_BldResponse(p_dev->rc_handle, pmetamsg_resp, &p_msg);
1455
1456 if (status == AVRC_STS_NO_ERROR) {
1457 BTA_AvMetaRsp(p_dev->rc_handle, label, ctype, p_msg);
1458 } else {
1459 log::error("failed to build metamsg response. status: 0x{:02x}", status);
1460 }
1461 }
1462
1463 if (index >= 0) {
1464 p_dev->rc_pdu_info[index].ctype = 0;
1465 p_dev->rc_pdu_info[index].label = 0;
1466 p_dev->rc_pdu_info[index].is_rsp_pending = false;
1467 }
1468 }
1469
opcode_from_pdu(uint8_t pdu)1470 static uint8_t opcode_from_pdu(uint8_t pdu) {
1471 uint8_t opcode = 0;
1472
1473 switch (pdu) {
1474 case AVRC_PDU_SET_BROWSED_PLAYER:
1475 case AVRC_PDU_GET_FOLDER_ITEMS:
1476 case AVRC_PDU_CHANGE_PATH:
1477 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
1478 case AVRC_PDU_ADD_TO_NOW_PLAYING:
1479 case AVRC_PDU_SEARCH:
1480 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
1481 case AVRC_PDU_GENERAL_REJECT:
1482 opcode = AVRC_OP_BROWSE;
1483 break;
1484
1485 case AVRC_PDU_NEXT_GROUP:
1486 case AVRC_PDU_PREV_GROUP: /* pass thru */
1487 opcode = AVRC_OP_PASS_THRU;
1488 break;
1489
1490 default: /* vendor */
1491 opcode = AVRC_OP_VENDOR;
1492 break;
1493 }
1494
1495 return opcode;
1496 }
1497
1498 /***************************************************************************
1499 * Function: fill_attribute_id_array
1500 *
1501 * - Argument:
1502 * cmd_attribute_number input attribute number from AVRCP command
1503 * cmd_attribute_id_array input attribute list from AVRCP command
1504 * out_array_size allocated size of out attribute id array
1505 * out_attribute_id_array output attribute list resolved here
1506 *
1507 * - Description:
1508 * Resolve attribute id array as defined by the AVRCP specification.
1509 *
1510 * - Returns:
1511 * The number of attributes filled in
1512 *
1513 ***************************************************************************/
fill_attribute_id_array(uint8_t cmd_attribute_number,const uint32_t * cmd_attribute_id_array,size_t out_array_size,btrc_media_attr_t * out_attribute_id_array)1514 static uint8_t fill_attribute_id_array(uint8_t cmd_attribute_number,
1515 const uint32_t* cmd_attribute_id_array,
1516 size_t out_array_size,
1517 btrc_media_attr_t* out_attribute_id_array) {
1518 /* Default case for cmd_attribute_number == 0xFF, No attribute */
1519 uint8_t out_attribute_number = 0;
1520 if (cmd_attribute_number == 0) {
1521 /* All attributes */
1522 out_attribute_number = out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID ? out_array_size
1523 : AVRC_MAX_NUM_MEDIA_ATTR_ID;
1524 for (int i = 0; i < out_attribute_number; i++) {
1525 out_attribute_id_array[i] = (btrc_media_attr_t)(i + 1);
1526 }
1527 } else if (cmd_attribute_number != 0xFF) {
1528 /* Attribute List */
1529 out_attribute_number = 0;
1530 int filled_id_count = 0;
1531 for (int i = 0; (i < cmd_attribute_number) && (out_attribute_number < out_array_size) &&
1532 (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID);
1533 i++) {
1534 /* Fill only valid entries */
1535 if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) {
1536 /* Skip the duplicate entries */
1537 for (filled_id_count = 0; filled_id_count < out_attribute_number; filled_id_count++) {
1538 if (out_attribute_id_array[filled_id_count] == cmd_attribute_id_array[i]) {
1539 break;
1540 }
1541 }
1542 /* New ID */
1543 if (filled_id_count == out_attribute_number) {
1544 out_attribute_id_array[out_attribute_number] =
1545 (btrc_media_attr_t)cmd_attribute_id_array[i];
1546 out_attribute_number++;
1547 }
1548 }
1549 }
1550 }
1551 return out_attribute_number;
1552 }
1553
1554 /*******************************************************************************
1555 *
1556 * Function btif_rc_upstreams_evt
1557 *
1558 * Description Executes AVRC UPSTREAMS events in btif context.
1559 *
1560 * Returns void
1561 *
1562 ******************************************************************************/
btif_rc_upstreams_evt(uint16_t event,tAVRC_COMMAND * pavrc_cmd,uint8_t ctype,uint8_t label,btif_rc_device_cb_t * p_dev)1563 static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, uint8_t ctype,
1564 uint8_t label, btif_rc_device_cb_t* p_dev) {
1565 log::verbose("pdu: {} handle: 0x{:x} ctype: {:x} label: {:x} event ID: {:x}",
1566 dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle, ctype, label,
1567 pavrc_cmd->reg_notif.event_id);
1568
1569 switch (event) {
1570 case AVRC_PDU_GET_PLAY_STATUS: {
1571 fill_pdu_queue(IDX_GET_PLAY_STATUS_RSP, ctype, label, true, p_dev);
1572 HAL_CBACK(bt_rc_callbacks, get_play_status_cb, p_dev->rc_addr);
1573 } break;
1574 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1575 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1576 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1577 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1578 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1579 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
1580 /* TODO: Add support for Application Settings */
1581 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD,
1582 pavrc_cmd->cmd.opcode);
1583 } break;
1584 case AVRC_PDU_GET_ELEMENT_ATTR: {
1585 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE] = {};
1586 uint8_t num_attr = fill_attribute_id_array(pavrc_cmd->get_elem_attrs.num_attr,
1587 pavrc_cmd->get_elem_attrs.attrs,
1588 BTRC_MAX_ELEM_ATTR_SIZE, element_attrs);
1589 if (num_attr == 0) {
1590 log::error("No valid attributes requested in GET_ELEMENT_ATTRIBUTES");
1591 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM,
1592 pavrc_cmd->cmd.opcode);
1593 return;
1594 }
1595 fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev);
1596 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, p_dev->rc_addr);
1597 } break;
1598 case AVRC_PDU_REGISTER_NOTIFICATION: {
1599 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1600 pavrc_cmd->reg_notif.param == 0) {
1601 log::warn("Device registering position changed with illegal param 0.");
1602 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM,
1603 pavrc_cmd->cmd.opcode);
1604 /* de-register this notification for a rejected response */
1605 p_dev->rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = false;
1606 return;
1607 }
1608 HAL_CBACK(bt_rc_callbacks, register_notification_cb,
1609 (btrc_event_id_t)pavrc_cmd->reg_notif.event_id, pavrc_cmd->reg_notif.param,
1610 p_dev->rc_addr);
1611 } break;
1612 case AVRC_PDU_INFORM_DISPLAY_CHARSET: {
1613 tAVRC_RESPONSE avrc_rsp;
1614 log::verbose("AVRC_PDU_INFORM_DISPLAY_CHARSET");
1615 if (p_dev->rc_connected) {
1616 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1617 avrc_rsp.inform_charset.opcode = opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1618 avrc_rsp.inform_charset.pdu = AVRC_PDU_INFORM_DISPLAY_CHARSET;
1619 avrc_rsp.inform_charset.status = AVRC_STS_NO_ERROR;
1620 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1621 }
1622 } break;
1623
1624 case AVRC_PDU_GET_FOLDER_ITEMS: {
1625 uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE] = {0};
1626 uint8_t num_attr;
1627 num_attr = pavrc_cmd->get_items.attr_count;
1628
1629 log::verbose(
1630 "AVRC_PDU_GET_FOLDER_ITEMS num_attr: {}, start_item [{}] end_item "
1631 "[{}]",
1632 num_attr, pavrc_cmd->get_items.start_item, pavrc_cmd->get_items.end_item);
1633
1634 /* num_attr requested:
1635 * 0x00: All attributes requested
1636 * 0xFF: No Attributes requested
1637 * 0x01 to 0x07: Specified number of attributes
1638 */
1639 if (num_attr != 0xFF && num_attr > BTRC_MAX_ELEM_ATTR_SIZE) {
1640 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM,
1641 pavrc_cmd->cmd.opcode);
1642 return;
1643 }
1644
1645 /* Except num_attr is None(0xff) / All(0x00), request follows with an
1646 * Attribute List */
1647 if ((num_attr != 0xFF) && (num_attr != 0x00)) {
1648 memcpy(attr_ids, pavrc_cmd->get_items.p_attr_list, sizeof(uint32_t) * num_attr);
1649 }
1650
1651 fill_pdu_queue(IDX_GET_FOLDER_ITEMS_RSP, ctype, label, true, p_dev);
1652 HAL_CBACK(bt_rc_callbacks, get_folder_items_cb, pavrc_cmd->get_items.scope,
1653 pavrc_cmd->get_items.start_item, pavrc_cmd->get_items.end_item, num_attr, attr_ids,
1654 p_dev->rc_addr);
1655 } break;
1656
1657 case AVRC_PDU_SET_ADDRESSED_PLAYER: {
1658 fill_pdu_queue(IDX_SET_ADDR_PLAYER_RSP, ctype, label, true, p_dev);
1659 HAL_CBACK(bt_rc_callbacks, set_addressed_player_cb, pavrc_cmd->addr_player.player_id,
1660 p_dev->rc_addr);
1661 } break;
1662
1663 case AVRC_PDU_SET_BROWSED_PLAYER: {
1664 fill_pdu_queue(IDX_SET_BROWSED_PLAYER_RSP, ctype, label, true, p_dev);
1665 HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb, pavrc_cmd->br_player.player_id,
1666 p_dev->rc_addr);
1667 } break;
1668
1669 case AVRC_PDU_REQUEST_CONTINUATION_RSP: {
1670 log::verbose("REQUEST CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->continu.target_pdu);
1671 tAVRC_RESPONSE avrc_rsp;
1672 if (p_dev->rc_connected) {
1673 memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP));
1674 avrc_rsp.continu.opcode = opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP);
1675 avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
1676 avrc_rsp.continu.status = AVRC_STS_NO_ERROR;
1677 avrc_rsp.continu.target_pdu = pavrc_cmd->continu.target_pdu;
1678 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1679 }
1680 } break;
1681
1682 case AVRC_PDU_ABORT_CONTINUATION_RSP: {
1683 log::verbose("ABORT CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->abort.target_pdu);
1684 tAVRC_RESPONSE avrc_rsp;
1685 if (p_dev->rc_connected) {
1686 memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP));
1687 avrc_rsp.abort.opcode = opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP);
1688 avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP;
1689 avrc_rsp.abort.status = AVRC_STS_NO_ERROR;
1690 avrc_rsp.abort.target_pdu = pavrc_cmd->continu.target_pdu;
1691 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1692 }
1693 } break;
1694
1695 case AVRC_PDU_CHANGE_PATH: {
1696 fill_pdu_queue(IDX_CHG_PATH_RSP, ctype, label, true, p_dev);
1697 HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction,
1698 pavrc_cmd->chg_path.folder_uid, p_dev->rc_addr);
1699 } break;
1700
1701 case AVRC_PDU_SEARCH: {
1702 fill_pdu_queue(IDX_SEARCH_RSP, ctype, label, true, p_dev);
1703 HAL_CBACK(bt_rc_callbacks, search_cb, pavrc_cmd->search.string.charset_id,
1704 pavrc_cmd->search.string.str_len, pavrc_cmd->search.string.p_str, p_dev->rc_addr);
1705 } break;
1706
1707 case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
1708 btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE] = {};
1709 uint8_t num_attr = fill_attribute_id_array(pavrc_cmd->get_attrs.attr_count,
1710 pavrc_cmd->get_attrs.p_attr_list,
1711 BTRC_MAX_ELEM_ATTR_SIZE, item_attrs);
1712 if (num_attr == 0) {
1713 log::error("No valid attributes requested in GET_ITEM_ATTRIBUTES");
1714 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM,
1715 pavrc_cmd->cmd.opcode);
1716 return;
1717 }
1718 fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev);
1719 log::verbose("GET_ITEM_ATTRIBUTES: num_attr: {}", num_attr);
1720 HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
1721 pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter, num_attr, item_attrs,
1722 p_dev->rc_addr);
1723 } break;
1724
1725 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: {
1726 fill_pdu_queue(IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, ctype, label, true, p_dev);
1727 HAL_CBACK(bt_rc_callbacks, get_total_num_of_items_cb, pavrc_cmd->get_num_of_items.scope,
1728 p_dev->rc_addr);
1729 } break;
1730
1731 case AVRC_PDU_ADD_TO_NOW_PLAYING: {
1732 fill_pdu_queue(IDX_ADD_TO_NOW_PLAYING_RSP, ctype, label, true, p_dev);
1733 HAL_CBACK(bt_rc_callbacks, add_to_now_playing_cb, pavrc_cmd->add_to_play.scope,
1734 pavrc_cmd->add_to_play.uid, pavrc_cmd->add_to_play.uid_counter, p_dev->rc_addr);
1735 } break;
1736
1737 case AVRC_PDU_PLAY_ITEM: {
1738 fill_pdu_queue(IDX_PLAY_ITEM_RSP, ctype, label, true, p_dev);
1739 HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
1740 pavrc_cmd->play_item.uid_counter, pavrc_cmd->play_item.uid, p_dev->rc_addr);
1741 } break;
1742
1743 default: {
1744 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD,
1745 pavrc_cmd->cmd.opcode);
1746 return;
1747 } break;
1748 }
1749 }
1750
1751 /*******************************************************************************
1752 *
1753 * Function btif_rc_ctrl_upstreams_rsp_cmd
1754 *
1755 * Description Executes AVRC UPSTREAMS response events in btif context.
1756 *
1757 * Returns void
1758 *
1759 ******************************************************************************/
btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,tAVRC_COMMAND * pavrc_cmd,uint8_t label,btif_rc_device_cb_t * p_dev)1760 static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event, tAVRC_COMMAND* pavrc_cmd, uint8_t label,
1761 btif_rc_device_cb_t* p_dev) {
1762 log::verbose("pdu: {}: handle: 0x{:x}", dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle);
1763 switch (event) {
1764 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1765 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->setabsvol_cmd_cb, p_dev->rc_addr,
1766 pavrc_cmd->volume.volume, label));
1767 break;
1768 case AVRC_PDU_REGISTER_NOTIFICATION:
1769 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE) {
1770 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->registernotification_absvol_cb,
1771 p_dev->rc_addr, label));
1772 }
1773 break;
1774 }
1775 }
1776
1777 /*******************************************************************************
1778 *
1779 * Function btif_rc_upstreams_rsp_evt
1780 *
1781 * Description Executes AVRC UPSTREAMS response events in btif context.
1782 *
1783 * Returns void
1784 *
1785 ******************************************************************************/
btif_rc_upstreams_rsp_evt(uint16_t event,tAVRC_RESPONSE * pavrc_resp,uint8_t ctype,uint8_t label,btif_rc_device_cb_t * p_dev)1786 static void btif_rc_upstreams_rsp_evt(uint16_t event, tAVRC_RESPONSE* pavrc_resp, uint8_t ctype,
1787 uint8_t label, btif_rc_device_cb_t* p_dev) {
1788 log::verbose("pdu: {}: handle: 0x{:x} ctype: {:x} label: {:x}", dump_rc_pdu(pavrc_resp->pdu),
1789 p_dev->rc_handle, ctype, label);
1790
1791 switch (event) {
1792 case AVRC_PDU_REGISTER_NOTIFICATION: {
1793 if (AVRC_RSP_CHANGED == ctype) {
1794 p_dev->rc_volume = pavrc_resp->reg_notif.param.volume;
1795 }
1796 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume, ctype,
1797 p_dev->rc_addr);
1798 } break;
1799
1800 case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
1801 log::verbose("Set absolute volume change event received: volume: {}, ctype: {}",
1802 pavrc_resp->volume.volume, ctype);
1803 if (AVRC_RSP_ACCEPT == ctype) {
1804 p_dev->rc_volume = pavrc_resp->volume.volume;
1805 }
1806 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->volume.volume, ctype,
1807 p_dev->rc_addr);
1808 } break;
1809
1810 default:
1811 return;
1812 }
1813 }
1814
1815 /*******************************************************************************
1816 * AVRCP API Functions
1817 ******************************************************************************/
1818
1819 /*******************************************************************************
1820 *
1821 * Function init
1822 *
1823 * Description Initializes the AVRC interface
1824 *
1825 * Returns bt_status_t
1826 *
1827 ******************************************************************************/
init(btrc_callbacks_t * callbacks)1828 static bt_status_t init(btrc_callbacks_t* callbacks) {
1829 log::verbose("");
1830 bt_status_t result = BT_STATUS_SUCCESS;
1831
1832 if (bt_rc_callbacks) {
1833 return BT_STATUS_DONE;
1834 }
1835
1836 bt_rc_callbacks = callbacks;
1837 if (bt_rc_ctrl_callbacks) {
1838 return BT_STATUS_SUCCESS;
1839 }
1840
1841 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1842 initialize_device(&btif_rc_cb.rc_multi_cb[idx]);
1843 }
1844
1845 return result;
1846 }
1847
1848 /*******************************************************************************
1849 *
1850 * Function init_ctrl
1851 *
1852 * Description Initializes the AVRC interface
1853 *
1854 * Returns bt_status_t
1855 *
1856 ******************************************************************************/
init_ctrl(btrc_ctrl_callbacks_t * callbacks)1857 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks) {
1858 log::verbose("");
1859 bt_status_t result = BT_STATUS_SUCCESS;
1860
1861 if (bt_rc_ctrl_callbacks) {
1862 return BT_STATUS_DONE;
1863 }
1864
1865 bt_rc_ctrl_callbacks = callbacks;
1866 if (bt_rc_callbacks) {
1867 return BT_STATUS_SUCCESS;
1868 }
1869
1870 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1871 initialize_device(&btif_rc_cb.rc_multi_cb[idx]);
1872 }
1873
1874 return result;
1875 }
1876
rc_ctrl_procedure_complete(btif_rc_device_cb_t * p_dev)1877 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev) {
1878 if (p_dev == NULL) {
1879 log::error("p_dev NULL");
1880 return;
1881 }
1882
1883 if (p_dev->rc_procedure_complete) {
1884 return;
1885 }
1886 p_dev->rc_procedure_complete = true;
1887 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
1888 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
1889 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
1890 }
1891
1892 /***************************************************************************
1893 *
1894 * Function get_play_status_rsp
1895 *
1896 * Description Returns the current play status.
1897 * This method is called in response to
1898 * GetPlayStatus request.
1899 *
1900 * Returns bt_status_t
1901 *
1902 **************************************************************************/
get_play_status_rsp(const RawAddress & bd_addr,btrc_play_status_t play_status,uint32_t song_len,uint32_t song_pos)1903 static bt_status_t get_play_status_rsp(const RawAddress& bd_addr, btrc_play_status_t play_status,
1904 uint32_t song_len, uint32_t song_pos) {
1905 tAVRC_RESPONSE avrc_rsp;
1906 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1907
1908 log::verbose("song len {} song pos {}", song_len, song_pos);
1909 CHECK_RC_CONNECTED(p_dev);
1910
1911 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1912
1913 avrc_rsp.get_play_status.song_len = song_len;
1914 avrc_rsp.get_play_status.song_pos = song_pos;
1915 avrc_rsp.get_play_status.play_status = play_status;
1916
1917 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1918 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1919 avrc_rsp.get_play_status.status =
1920 ((play_status != BTRC_PLAYSTATE_ERROR) ? AVRC_STS_NO_ERROR : AVRC_STS_BAD_PARAM);
1921
1922 /* Send the response */
1923 send_metamsg_rsp(p_dev, IDX_GET_PLAY_STATUS_RSP,
1924 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].label,
1925 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].ctype, &avrc_rsp);
1926
1927 return BT_STATUS_SUCCESS;
1928 }
1929
1930 /***************************************************************************
1931 *
1932 * Function get_element_attr_rsp
1933 *
1934 * Description Returns the current songs' element attributes
1935 * in text.
1936 *
1937 * Returns bt_status_t
1938 *
1939 **************************************************************************/
get_element_attr_rsp(const RawAddress & bd_addr,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)1940 static bt_status_t get_element_attr_rsp(const RawAddress& bd_addr, uint8_t num_attr,
1941 btrc_element_attr_val_t* p_attrs) {
1942 tAVRC_RESPONSE avrc_rsp;
1943 uint32_t i;
1944 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1945 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1946
1947 log::verbose("");
1948 CHECK_RC_CONNECTED(p_dev);
1949
1950 if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) {
1951 log::warn("Exceeded number attributes:{} max:{}", static_cast<int>(num_attr),
1952 BTRC_MAX_ELEM_ATTR_SIZE);
1953 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1954 }
1955 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1956
1957 if (num_attr == 0) {
1958 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1959 } else {
1960 for (i = 0; i < num_attr; i++) {
1961 element_attrs[i].attr_id = p_attrs[i].attr_id;
1962 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1963 element_attrs[i].name.str_len =
1964 (uint16_t)strnlen((char*)p_attrs[i].text, BTRC_MAX_ATTR_STR_LEN);
1965 element_attrs[i].name.p_str = p_attrs[i].text;
1966 log::verbose("attr_id: 0x{:x}, charset_id: 0x{:x}, str_len: {}, str: {}",
1967 (unsigned int)element_attrs[i].attr_id, element_attrs[i].name.charset_id,
1968 element_attrs[i].name.str_len,
1969 reinterpret_cast<char const*>(element_attrs[i].name.p_str));
1970 }
1971 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1972 }
1973 avrc_rsp.get_attrs.num_attrs = num_attr;
1974 avrc_rsp.get_attrs.p_attrs = element_attrs;
1975 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1976 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1977
1978 /* Send the response */
1979 send_metamsg_rsp(p_dev, IDX_GET_ELEMENT_ATTR_RSP,
1980 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].label,
1981 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].ctype, &avrc_rsp);
1982
1983 return BT_STATUS_SUCCESS;
1984 }
1985
1986 /***************************************************************************
1987 *
1988 * Function register_notification_rsp
1989 *
1990 * Description Response to the register notification request.
1991 *
1992 * Returns bt_status_t
1993 *
1994 **************************************************************************/
register_notification_rsp(btrc_event_id_t event_id,btrc_notification_type_t type,btrc_register_notification_t * p_param)1995 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1996 btrc_notification_type_t type,
1997 btrc_register_notification_t* p_param) {
1998 tAVRC_RESPONSE avrc_rsp;
1999 log::verbose("event_id: {}", dump_rc_notification_event_id(event_id));
2000 std::unique_lock<std::mutex> lock(btif_rc_cb.lock);
2001
2002 if (event_id > MAX_RC_NOTIFICATIONS) {
2003 log::error("Invalid event id");
2004 return BT_STATUS_PARM_INVALID;
2005 }
2006
2007 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
2008
2009 avrc_rsp.reg_notif.event_id = event_id;
2010 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
2011 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
2012 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
2013
2014 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
2015 memset(&(avrc_rsp.reg_notif.param), 0, sizeof(tAVRC_NOTIF_RSP_PARAM));
2016
2017 if (!(btif_rc_cb.rc_multi_cb[idx].rc_connected)) {
2018 log::error("Avrcp device is not connected, handle: 0x{:x}",
2019 btif_rc_cb.rc_multi_cb[idx].rc_handle);
2020 continue;
2021 }
2022
2023 if (!btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify) {
2024 log::warn("Avrcp Event id is not registered: event_id: {:x}, handle: 0x{:x}", event_id,
2025 btif_rc_cb.rc_multi_cb[idx].rc_handle);
2026 continue;
2027 }
2028
2029 log::verbose("Avrcp Event id is registered: event_id: {:x} handle: 0x{:x}", event_id,
2030 btif_rc_cb.rc_multi_cb[idx].rc_handle);
2031
2032 switch (event_id) {
2033 case BTRC_EVT_PLAY_STATUS_CHANGED:
2034 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
2035 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING) {
2036 btif_av_clear_remote_suspend_flag(A2dpType::kSink);
2037 }
2038 break;
2039 case BTRC_EVT_TRACK_CHANGE:
2040 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
2041 break;
2042 case BTRC_EVT_PLAY_POS_CHANGED:
2043 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
2044 break;
2045 case BTRC_EVT_AVAL_PLAYER_CHANGE:
2046 break;
2047 case BTRC_EVT_ADDR_PLAYER_CHANGE:
2048 avrc_rsp.reg_notif.param.addr_player.player_id = p_param->addr_player_changed.player_id;
2049 avrc_rsp.reg_notif.param.addr_player.uid_counter = p_param->addr_player_changed.uid_counter;
2050 break;
2051 case BTRC_EVT_UIDS_CHANGED:
2052 avrc_rsp.reg_notif.param.uid_counter = p_param->uids_changed.uid_counter;
2053 break;
2054 case BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED:
2055 break;
2056
2057 default:
2058 log::warn("Unhandled event ID: 0x{:x}", event_id);
2059 return BT_STATUS_UNHANDLED;
2060 }
2061
2062 /* Send the response. */
2063 send_metamsg_rsp(&btif_rc_cb.rc_multi_cb[idx], -1,
2064 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label,
2065 ((type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_CMD_NOTIF : AVRC_RSP_CHANGED),
2066 &avrc_rsp);
2067 }
2068 return BT_STATUS_SUCCESS;
2069 }
2070
2071 /***************************************************************************
2072 *
2073 * Function get_folder_items_list_rsp
2074 *
2075 * Description Returns the list of media items in current folder along with
2076 * requested attributes. This is called in response to
2077 * GetFolderItems request.
2078 *
2079 * Returns bt_status_t
2080 * BT_STATUS_NOT_READY - when RC is not connected.
2081 * BT_STATUS_SUCCESS - always if RC is connected
2082 * BT_STATUS_UNHANDLED - when rsp is not pending for
2083 * get_folder_items_list PDU
2084 *
2085 **************************************************************************/
get_folder_items_list_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint16_t uid_counter,uint8_t num_items,btrc_folder_items_t * p_items)2086 static bt_status_t get_folder_items_list_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2087 uint16_t uid_counter, uint8_t num_items,
2088 btrc_folder_items_t* p_items) {
2089 tAVRC_RESPONSE avrc_rsp;
2090 tAVRC_ITEM item;
2091 tBTA_AV_CODE code = 0, ctype = 0;
2092 BT_HDR* p_msg = NULL;
2093 int item_cnt;
2094 tAVRC_STS status = AVRC_STS_NO_ERROR;
2095 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2096 btrc_folder_items_t* cur_item = NULL;
2097
2098 log::verbose("uid_counter {} num_items {}", uid_counter, num_items);
2099 CHECK_RC_CONNECTED(p_dev);
2100
2101 /* check if rsp to previous cmd was completed */
2102 if (!p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending) {
2103 log::warn("Not sending response as no PDU was registered");
2104 return BT_STATUS_UNHANDLED;
2105 }
2106
2107 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2108 memset(&item, 0, sizeof(tAVRC_ITEM));
2109
2110 avrc_rsp.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
2111 avrc_rsp.get_items.opcode = opcode_from_pdu(AVRC_PDU_GET_FOLDER_ITEMS);
2112 avrc_rsp.get_items.status = status_code_map[rsp_status];
2113
2114 if (avrc_rsp.get_items.status != AVRC_STS_NO_ERROR) {
2115 log::warn("Error in parsing the received getfolderitems cmd. status: 0x{:02x}",
2116 avrc_rsp.get_items.status);
2117 status = avrc_rsp.get_items.status;
2118 } else {
2119 avrc_rsp.get_items.uid_counter = uid_counter;
2120 avrc_rsp.get_items.item_count = 1;
2121
2122 /* create single item and build response iteratively for all num_items */
2123 for (item_cnt = 0; item_cnt < num_items; item_cnt++) {
2124 cur_item = &p_items[item_cnt];
2125 item.item_type = p_items->item_type;
2126 /* build respective item based on item_type. All items should be of same
2127 * type within
2128 * a response */
2129 switch (p_items->item_type) {
2130 case AVRC_ITEM_PLAYER: {
2131 item.u.player.name.charset_id = cur_item->player.charset_id;
2132 memcpy(&(item.u.player.features), &(cur_item->player.features),
2133 sizeof(cur_item->player.features));
2134 item.u.player.major_type = cur_item->player.major_type;
2135 item.u.player.sub_type = cur_item->player.sub_type;
2136 item.u.player.play_status = cur_item->player.play_status;
2137 item.u.player.player_id = cur_item->player.player_id;
2138 item.u.player.name.p_str = cur_item->player.name;
2139 item.u.player.name.str_len = (uint16_t)strlen((char*)(cur_item->player.name));
2140 } break;
2141
2142 case AVRC_ITEM_FOLDER: {
2143 memcpy(item.u.folder.uid, cur_item->folder.uid, sizeof(tAVRC_UID));
2144 item.u.folder.type = cur_item->folder.type;
2145 item.u.folder.playable = cur_item->folder.playable;
2146 item.u.folder.name.charset_id = AVRC_CHARSET_ID_UTF8;
2147 item.u.folder.name.str_len = strlen((char*)cur_item->folder.name);
2148 item.u.folder.name.p_str = cur_item->folder.name;
2149 } break;
2150
2151 case AVRC_ITEM_MEDIA: {
2152 tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE] = {};
2153
2154 memcpy(item.u.media.uid, cur_item->media.uid, sizeof(tAVRC_UID));
2155 item.u.media.type = cur_item->media.type;
2156 item.u.media.name.charset_id = cur_item->media.charset_id;
2157 item.u.media.name.str_len = strlen((char*)cur_item->media.name);
2158 item.u.media.name.p_str = cur_item->media.name;
2159 item.u.media.attr_count = cur_item->media.num_attrs;
2160
2161 /* Handle attributes of given item */
2162 if (item.u.media.attr_count == 0) {
2163 item.u.media.p_attr_list = NULL;
2164 } else {
2165 memset(&attr_vals, 0, sizeof(tAVRC_ATTR_ENTRY) * BTRC_MAX_ELEM_ATTR_SIZE);
2166 fill_avrc_attr_entry(attr_vals, item.u.media.attr_count, cur_item->media.p_attrs);
2167 item.u.media.p_attr_list = attr_vals;
2168 }
2169 } break;
2170
2171 default: {
2172 log::error("Unknown item_type: {}. Internal Error", p_items->item_type);
2173 status = AVRC_STS_INTERNAL_ERR;
2174 } break;
2175 }
2176
2177 avrc_rsp.get_items.p_item_list = &item;
2178
2179 /* Add current item to buffer and build response if no error in item type
2180 */
2181 if (status != AVRC_STS_NO_ERROR) {
2182 /* Reject response due to error occurred for unknown item_type, break the
2183 * loop */
2184 break;
2185 }
2186
2187 int len_before = p_msg ? p_msg->len : 0;
2188 log::verbose("item_cnt: {} len: {}", item_cnt, len_before);
2189 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2190 log::verbose("Build rsp status: {} len: {}", status, p_msg ? p_msg->len : 0);
2191 int len_after = p_msg ? p_msg->len : 0;
2192 if (status != AVRC_STS_NO_ERROR || len_before == len_after) {
2193 /* Error occurred in build response or we ran out of buffer so break the
2194 * loop */
2195 break;
2196 }
2197 }
2198
2199 /* setting the error status */
2200 avrc_rsp.get_items.status = status;
2201 }
2202
2203 /* if packet built successfully, send the built items to BTA layer */
2204 if (status == AVRC_STS_NO_ERROR) {
2205 code = p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype;
2206 ctype = get_rsp_type_code(avrc_rsp.get_items.status, code);
2207 BTA_AvMetaRsp(p_dev->rc_handle, p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label, ctype,
2208 p_msg);
2209 } else {
2210 /* Error occurred, send reject response */
2211 log::error("Error status: 0x{:02X}. Sending reject rsp", avrc_rsp.rsp.status);
2212 send_reject_response(p_dev->rc_handle, p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label,
2213 avrc_rsp.pdu, avrc_rsp.get_items.status, avrc_rsp.get_items.opcode);
2214 }
2215
2216 /* Reset values for current pdu. */
2217 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype = 0;
2218 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label = 0;
2219 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending = false;
2220
2221 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2222 }
2223
2224 /***************************************************************************
2225 *
2226 * Function set_addressed_player_rsp
2227 *
2228 * Description Response to set the addressed player for specified media
2229 * player based on id in the media player list.
2230 *
2231 * Returns bt_status_t
2232 * BT_STATUS_NOT_READY - when RC is not connected.
2233 * BT_STATUS_SUCCESS - always if RC is connected
2234 *
2235 **************************************************************************/
set_addressed_player_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2236 static bt_status_t set_addressed_player_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status) {
2237 tAVRC_RESPONSE avrc_rsp;
2238 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2239
2240 log::verbose("");
2241 CHECK_RC_CONNECTED(p_dev);
2242
2243 avrc_rsp.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
2244 avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER);
2245 avrc_rsp.addr_player.status = status_code_map[rsp_status];
2246
2247 /* Send the response. */
2248 send_metamsg_rsp(p_dev, IDX_SET_ADDR_PLAYER_RSP,
2249 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].label,
2250 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].ctype, &avrc_rsp);
2251
2252 return BT_STATUS_SUCCESS;
2253 }
2254
2255 /***************************************************************************
2256 *
2257 * Function set_browsed_player_rsp
2258 *
2259 * Description Response to set the browsed player command which contains
2260 * current browsed path of the media player. By default,
2261 * current_path = root and folder_depth = 0 for
2262 * every set_browsed_player request.
2263 *
2264 * Returns bt_status_t
2265 * BT_STATUS_NOT_READY - when RC is not connected.
2266 * BT_STATUS_SUCCESS - if RC is connected and response
2267 * sent successfully
2268 * BT_STATUS_UNHANDLED - when rsp is not pending for
2269 * set_browsed_player PDU
2270 *
2271 **************************************************************************/
set_browsed_player_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t num_items,uint16_t charset_id,uint8_t folder_depth,btrc_br_folder_name_t * p_folders)2272 static bt_status_t set_browsed_player_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2273 uint32_t num_items, uint16_t charset_id,
2274 uint8_t folder_depth, btrc_br_folder_name_t* p_folders) {
2275 tAVRC_RESPONSE avrc_rsp;
2276 tAVRC_NAME item;
2277 BT_HDR* p_msg = NULL;
2278 tBTA_AV_CODE code = 0;
2279 tBTA_AV_CODE ctype = 0;
2280 unsigned int item_cnt;
2281 tAVRC_STS status = AVRC_STS_NO_ERROR;
2282 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2283
2284 CHECK_RC_CONNECTED(p_dev);
2285
2286 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2287 memset(&item, 0, sizeof(tAVRC_NAME));
2288
2289 avrc_rsp.br_player.status = status_code_map[rsp_status];
2290 avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
2291 avrc_rsp.br_player.opcode = opcode_from_pdu(AVRC_PDU_SET_BROWSED_PLAYER);
2292
2293 log::verbose("rsp_status: 0x{:02X} avrc_rsp.br_player.status: 0x{:02X}", rsp_status,
2294 avrc_rsp.br_player.status);
2295
2296 /* check if rsp to previous cmd was completed */
2297 if (!p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending) {
2298 log::warn("Not sending response as no PDU was registered");
2299 return BT_STATUS_UNHANDLED;
2300 }
2301
2302 if (AVRC_STS_NO_ERROR == avrc_rsp.get_items.status) {
2303 avrc_rsp.br_player.num_items = num_items;
2304 avrc_rsp.br_player.charset_id = charset_id;
2305 avrc_rsp.br_player.folder_depth = folder_depth;
2306 avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_folders;
2307
2308 log::verbose("folder_depth: 0x{:02X} num_items: {}", folder_depth, num_items);
2309
2310 if (folder_depth > 0) {
2311 /* Iteratively build response for all folders across folder depth upto
2312 * current path */
2313 avrc_rsp.br_player.folder_depth = 1;
2314 for (item_cnt = 0; item_cnt < folder_depth; item_cnt++) {
2315 log::verbose("iteration: {}", item_cnt);
2316 item.str_len = p_folders[item_cnt].str_len;
2317 item.p_str = p_folders[item_cnt].p_str;
2318 avrc_rsp.br_player.p_folders = &item;
2319
2320 /* Add current item to buffer and build response */
2321 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2322 if (AVRC_STS_NO_ERROR != status) {
2323 log::warn("Build rsp status: {}", status);
2324 /* if the build fails, it is likely that we ran out of buffer. so if
2325 * we have
2326 * some items to send, reset this error to no error for sending what we
2327 * have */
2328 if (item_cnt > 0) {
2329 status = AVRC_STS_NO_ERROR;
2330 }
2331
2332 /* Error occurred in build response so break the loop */
2333 break;
2334 }
2335 }
2336 } else /* current path is root folder, no folders navigated yet */
2337 {
2338 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2339 }
2340
2341 /* setting the error status */
2342 avrc_rsp.br_player.status = status;
2343 } else /* error received from above layer */
2344 {
2345 log::warn("Error in parsing the received setbrowsed command. status: 0x{:02x}",
2346 avrc_rsp.br_player.status);
2347 status = avrc_rsp.br_player.status;
2348 }
2349
2350 /* if packet built successfully, send the built items to BTA layer */
2351 if (status == AVRC_STS_NO_ERROR) {
2352 code = p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype;
2353 ctype = get_rsp_type_code(avrc_rsp.br_player.status, code);
2354 BTA_AvMetaRsp(p_dev->rc_handle, p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label, ctype,
2355 p_msg);
2356 } else {
2357 /* Error occurred, send reject response */
2358 log::error("Error status: 0x{:02X}. Sending reject rsp", avrc_rsp.br_player.status);
2359 send_reject_response(p_dev->rc_handle, p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label,
2360 avrc_rsp.pdu, avrc_rsp.br_player.status, avrc_rsp.get_items.opcode);
2361 }
2362
2363 /* Reset values for set_browsed_player pdu.*/
2364 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype = 0;
2365 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label = 0;
2366 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending = false;
2367
2368 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2369 }
2370
2371 /*******************************************************************************
2372 *
2373 * Function change_path_rsp
2374 *
2375 * Description Response to the change path command which
2376 * contains number of items in the changed path.
2377 *
2378 * Returns bt_status_t
2379 * BT_STATUS_NOT_READY - when RC is not connected.
2380 * BT_STATUS_SUCCESS - always if RC is connected
2381 *
2382 **************************************************************************/
change_path_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t num_items)2383 static bt_status_t change_path_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2384 uint32_t num_items) {
2385 tAVRC_RESPONSE avrc_rsp;
2386 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2387
2388 log::verbose("");
2389 CHECK_RC_CONNECTED(p_dev);
2390
2391 avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
2392 avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH);
2393 avrc_rsp.chg_path.num_items = num_items;
2394 avrc_rsp.chg_path.status = status_code_map[rsp_status];
2395
2396 /* Send the response. */
2397 send_metamsg_rsp(p_dev, IDX_CHG_PATH_RSP, p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].label,
2398 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].ctype, &avrc_rsp);
2399
2400 return BT_STATUS_SUCCESS;
2401 }
2402
2403 /***************************************************************************
2404 *
2405 * Function search_rsp
2406 *
2407 * Description Response to search a string from media content command.
2408 *
2409 * Returns bt_status_t
2410 * BT_STATUS_NOT_READY - when RC is not connected.
2411 * BT_STATUS_SUCCESS - always if RC is connected
2412 *
2413 **************************************************************************/
search_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2414 static bt_status_t search_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2415 uint32_t uid_counter, uint32_t num_items) {
2416 tAVRC_RESPONSE avrc_rsp;
2417 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2418
2419 log::verbose("");
2420 CHECK_RC_CONNECTED(p_dev);
2421
2422 avrc_rsp.search.pdu = AVRC_PDU_SEARCH;
2423 avrc_rsp.search.opcode = opcode_from_pdu(AVRC_PDU_SEARCH);
2424 avrc_rsp.search.num_items = num_items;
2425 avrc_rsp.search.uid_counter = uid_counter;
2426 avrc_rsp.search.status = status_code_map[rsp_status];
2427
2428 /* Send the response. */
2429 send_metamsg_rsp(p_dev, IDX_SEARCH_RSP, p_dev->rc_pdu_info[IDX_SEARCH_RSP].label,
2430 p_dev->rc_pdu_info[IDX_SEARCH_RSP].ctype, &avrc_rsp);
2431
2432 return BT_STATUS_SUCCESS;
2433 }
2434 /***************************************************************************
2435 *
2436 * Function get_item_attr_rsp
2437 *
2438 * Description Response to the get item's attributes command which
2439 * contains number of attributes and values list in text.
2440 *
2441 * Returns bt_status_t
2442 * BT_STATUS_NOT_READY - when RC is not connected.
2443 * BT_STATUS_SUCCESS - always if RC is connected
2444 *
2445 **************************************************************************/
get_item_attr_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)2446 static bt_status_t get_item_attr_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2447 uint8_t num_attr, btrc_element_attr_val_t* p_attrs) {
2448 tAVRC_RESPONSE avrc_rsp;
2449 tAVRC_ATTR_ENTRY item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
2450 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2451
2452 log::verbose("");
2453 CHECK_RC_CONNECTED(p_dev);
2454
2455 memset(item_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
2456
2457 avrc_rsp.get_attrs.status = status_code_map[rsp_status];
2458 if (rsp_status == BTRC_STS_NO_ERROR) {
2459 fill_avrc_attr_entry(item_attrs, num_attr, p_attrs);
2460 }
2461
2462 avrc_rsp.get_attrs.num_attrs = num_attr;
2463 avrc_rsp.get_attrs.p_attrs = item_attrs;
2464 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
2465 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);
2466
2467 /* Send the response. */
2468 send_metamsg_rsp(p_dev, IDX_GET_ITEM_ATTR_RSP, p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].label,
2469 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].ctype, &avrc_rsp);
2470
2471 return BT_STATUS_SUCCESS;
2472 }
2473
2474 /***************************************************************************
2475 *
2476 * Function add_to_now_playing_rsp
2477 *
2478 * Description Response to command for adding speciafied media item
2479 * to Now Playing queue.
2480 *
2481 * Returns bt_status_t
2482 * BT_STATUS_NOT_READY - when RC is not connected.
2483 * BT_STATUS_SUCCESS - always if RC is connected
2484 *
2485 **************************************************************************/
add_to_now_playing_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2486 static bt_status_t add_to_now_playing_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status) {
2487 tAVRC_RESPONSE avrc_rsp;
2488 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2489
2490 log::verbose("");
2491 CHECK_RC_CONNECTED(p_dev);
2492
2493 avrc_rsp.add_to_play.pdu = AVRC_PDU_ADD_TO_NOW_PLAYING;
2494 avrc_rsp.add_to_play.opcode = opcode_from_pdu(AVRC_PDU_ADD_TO_NOW_PLAYING);
2495 avrc_rsp.add_to_play.status = status_code_map[rsp_status];
2496
2497 /* Send the response. */
2498 send_metamsg_rsp(p_dev, IDX_ADD_TO_NOW_PLAYING_RSP,
2499 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].label,
2500 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].ctype, &avrc_rsp);
2501
2502 return BT_STATUS_SUCCESS;
2503 }
2504
2505 /***************************************************************************
2506 *
2507 * Function play_item_rsp
2508 *
2509 * Description Response to command for playing the specified media item.
2510 *
2511 * Returns bt_status_t
2512 * BT_STATUS_NOT_READY - when RC is not connected.
2513 * BT_STATUS_SUCCESS - always if RC is connected
2514 *
2515 **************************************************************************/
play_item_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2516 static bt_status_t play_item_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status) {
2517 tAVRC_RESPONSE avrc_rsp;
2518 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2519
2520 log::verbose("");
2521 CHECK_RC_CONNECTED(p_dev);
2522
2523 avrc_rsp.play_item.pdu = AVRC_PDU_PLAY_ITEM;
2524 avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM);
2525 avrc_rsp.play_item.status = status_code_map[rsp_status];
2526
2527 /* Send the response. */
2528 send_metamsg_rsp(p_dev, IDX_PLAY_ITEM_RSP, p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].label,
2529 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].ctype, &avrc_rsp);
2530
2531 return BT_STATUS_SUCCESS;
2532 }
2533
2534 /***************************************************************************
2535 *
2536 * Function get_total_num_of_items_rsp
2537 *
2538 * Description response to command to get the Number of Items
2539 * in the selected folder at the selected scope
2540 *
2541 * Returns bt_status_t
2542 * BT_STATUS_NOT_READY - when RC is not connected.
2543 * BT_STATUS_SUCCESS - always if RC is connected
2544 *
2545 **************************************************************************/
get_total_num_of_items_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2546 static bt_status_t get_total_num_of_items_rsp(const RawAddress& bd_addr, btrc_status_t rsp_status,
2547 uint32_t uid_counter, uint32_t num_items) {
2548 tAVRC_RESPONSE avrc_rsp;
2549 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2550
2551 log::verbose("");
2552 CHECK_RC_CONNECTED(p_dev);
2553
2554 avrc_rsp.get_num_of_items.pdu = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS;
2555 avrc_rsp.get_num_of_items.opcode = opcode_from_pdu(AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS);
2556 avrc_rsp.get_num_of_items.num_items = num_items;
2557 avrc_rsp.get_num_of_items.uid_counter = uid_counter;
2558 avrc_rsp.get_num_of_items.status = status_code_map[rsp_status];
2559
2560 /* Send the response. */
2561 send_metamsg_rsp(p_dev, IDX_GET_TOTAL_NUM_OF_ITEMS_RSP,
2562 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].label,
2563 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].ctype, &avrc_rsp);
2564
2565 return BT_STATUS_SUCCESS;
2566 }
2567
2568 /***************************************************************************
2569 *
2570 * Function set_volume
2571 *
2572 * Description Send current volume setting to remote side.
2573 * Support limited to SetAbsoluteVolume
2574 * This can be enhanced to support Relative Volume (AVRCP 1.0).
2575 * With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
2576 * as opposed to absolute volume level
2577 * volume: Should be in the range 0-127. bit7 is reserved and cannot be set
2578 *
2579 * Returns bt_status_t
2580 *
2581 **************************************************************************/
set_volume(uint8_t volume)2582 static bt_status_t set_volume(uint8_t volume) {
2583 log::verbose("volume: {}", volume);
2584 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2585
2586 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
2587 btif_rc_device_cb_t* p_dev = &btif_rc_cb.rc_multi_cb[idx];
2588 if (!p_dev->rc_connected) {
2589 continue;
2590 }
2591
2592 if (p_dev->rc_volume == volume) {
2593 status = BT_STATUS_DONE;
2594 log::error("volume value already set earlier: 0x{:02x}", volume);
2595 continue;
2596 }
2597
2598 if ((p_dev->rc_volume == volume) || p_dev->rc_state != BTRC_CONNECTION_STATE_CONNECTED) {
2599 continue;
2600 }
2601
2602 if ((p_dev->rc_features & BTA_AV_FEAT_RCTG) == 0) {
2603 status = BT_STATUS_NOT_READY;
2604 continue;
2605 }
2606
2607 if (!(p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL)) {
2608 continue;
2609 }
2610
2611 log::verbose("Peer supports absolute volume. newVolume: {}", volume);
2612
2613 tAVRC_COMMAND avrc_cmd = {.volume = {.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME,
2614 .status = AVRC_STS_NO_ERROR,
2615 .opcode = AVRC_OP_VENDOR,
2616 .volume = volume}};
2617
2618 BT_HDR* p_msg = NULL;
2619 if (AVRC_BldCommand(&avrc_cmd, &p_msg) != AVRC_STS_NO_ERROR) {
2620 log::error("failed to build absolute volume command. status: 0x{:02x}", status);
2621 status = BT_STATUS_FAIL;
2622 continue;
2623 }
2624
2625 rc_transaction_context_t context = {
2626 .rc_addr = p_dev->rc_addr,
2627 .label = MAX_LABEL,
2628 .opcode = AVRC_OP_VENDOR,
2629 .command = {.vendor = {AVRC_PDU_SET_ABSOLUTE_VOLUME, AVRC_EVT_INVALID}}};
2630 rc_transaction_t* p_transaction = NULL;
2631 bt_status_t tran_status = get_transaction(p_dev, context, &p_transaction);
2632
2633 if (tran_status != BT_STATUS_SUCCESS || !p_transaction) {
2634 osi_free_and_reset((void**)&p_msg);
2635 log::error("failed to get label, pdu_id={}, status=0x{:02x}", dump_rc_pdu(avrc_cmd.pdu),
2636 tran_status);
2637 status = BT_STATUS_FAIL;
2638 continue;
2639 }
2640
2641 log::verbose("msgreq being sent out with label: {}", p_transaction->label);
2642 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->label, AVRC_CMD_CTRL, p_msg);
2643 status = BT_STATUS_SUCCESS;
2644 start_transaction_timer(p_dev, p_transaction->label, BTIF_RC_TIMEOUT_MS);
2645 }
2646 return (bt_status_t)status;
2647 }
2648
2649 /***************************************************************************
2650 *
2651 * Function register_volumechange
2652 *
2653 * Description Register for volume change notification from remote side.
2654 *
2655 * Returns void
2656 *
2657 **************************************************************************/
2658
register_volumechange(btif_rc_device_cb_t * p_dev)2659 static void register_volumechange(btif_rc_device_cb_t* p_dev) {
2660 if (p_dev == nullptr) {
2661 log::error("device was null");
2662 return;
2663 }
2664
2665 tAVRC_COMMAND avrc_cmd = {0};
2666 BT_HDR* p_msg = NULL;
2667 tAVRC_STS BldResp = AVRC_STS_BAD_CMD;
2668
2669 rc_transaction_t* p_transaction = NULL;
2670 rc_transaction_context_t context = {
2671 .rc_addr = p_dev->rc_addr,
2672 .label = MAX_LABEL,
2673 .opcode = AVRC_OP_VENDOR,
2674 .command = {.vendor = {AVRC_PDU_REGISTER_NOTIFICATION, AVRC_EVT_VOLUME_CHANGE}}};
2675 bt_status_t status = BT_STATUS_NOT_READY;
2676 if (MAX_LABEL == p_dev->rc_vol_label) {
2677 status = get_transaction(p_dev, context, &p_transaction);
2678 } else {
2679 p_transaction = get_transaction_by_lbl(p_dev, p_dev->rc_vol_label);
2680 if (NULL != p_transaction) {
2681 log::verbose("already in progress for label: {}", p_dev->rc_vol_label);
2682 return;
2683 }
2684 status = get_transaction(p_dev, context, &p_transaction);
2685 }
2686
2687 if (BT_STATUS_SUCCESS == status && NULL != p_transaction) {
2688 p_dev->rc_vol_label = p_transaction->label;
2689 } else {
2690 log::error("failed to get a transaction label");
2691 return;
2692 }
2693
2694 log::verbose("label: {}", p_dev->rc_vol_label);
2695
2696 avrc_cmd.cmd.opcode = 0x00;
2697 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
2698 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
2699 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
2700 avrc_cmd.reg_notif.param = 0;
2701
2702 BldResp = AVRC_BldCommand(&avrc_cmd, &p_msg);
2703 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
2704 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->label, AVRC_CMD_NOTIF, p_msg);
2705 log::verbose("BTA_AvMetaCmd called");
2706 } else {
2707 log::error("failed to build command: {}", BldResp);
2708 }
2709 }
2710
2711 /***************************************************************************
2712 *
2713 * Function handle_rc_metamsg_rsp
2714 *
2715 * Description Handle RC metamessage response
2716 *
2717 * Returns void
2718 *
2719 **************************************************************************/
handle_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg,btif_rc_device_cb_t * p_dev)2720 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg, btif_rc_device_cb_t* p_dev) {
2721 tAVRC_RESPONSE avrc_response = {0};
2722 uint8_t scratch_buf[512] = {0};
2723 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2724
2725 log::verbose("");
2726
2727 if (AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode &&
2728 (AVRC_RSP_CHANGED == pmeta_msg->code || AVRC_RSP_INTERIM == pmeta_msg->code ||
2729 AVRC_RSP_ACCEPT == pmeta_msg->code || AVRC_RSP_REJ == pmeta_msg->code ||
2730 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2731 status = AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
2732 log::verbose("code:{}, event ID: {}, PDU: {:x}, parsing status: {}, label: {}", pmeta_msg->code,
2733 avrc_response.reg_notif.event_id, avrc_response.reg_notif.pdu, status,
2734 pmeta_msg->label);
2735
2736 if (status != AVRC_STS_NO_ERROR) {
2737 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2738 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2739 p_dev->rc_vol_label == pmeta_msg->label) {
2740 p_dev->rc_vol_label = MAX_LABEL;
2741 release_transaction(p_dev, p_dev->rc_vol_label);
2742 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2743 release_transaction(p_dev, pmeta_msg->label);
2744 }
2745 return;
2746 }
2747
2748 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2749 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2750 p_dev->rc_vol_label != pmeta_msg->label) {
2751 // Just discard the message, if the device sends back with an incorrect
2752 // label
2753 log::verbose("Discarding register notification in rsp.code: {} and label: {}",
2754 pmeta_msg->code, pmeta_msg->label);
2755 return;
2756 }
2757
2758 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2759 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2760 (AVRC_RSP_REJ == pmeta_msg->code || AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2761 log::verbose("remove AbsoluteVolume feature flag.");
2762 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
2763 handle_rc_features(p_dev);
2764 return;
2765 }
2766 } else {
2767 log::verbose(
2768 "Received vendor dependent in adv ctrl rsp. code: {} len: {}. Not "
2769 "processing it.",
2770 pmeta_msg->code, pmeta_msg->len);
2771 return;
2772 }
2773
2774 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2775 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2776 AVRC_RSP_CHANGED == pmeta_msg->code) {
2777 /* re-register for volume change notification */
2778 // Do not re-register for rejected case, as it might get into endless loop
2779 register_volumechange(p_dev);
2780 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2781 /* free up the label here */
2782 release_transaction(p_dev, pmeta_msg->label);
2783 }
2784
2785 log::verbose("Passing received metamsg response to app. pdu: {}", dump_rc_pdu(avrc_response.pdu));
2786 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
2787 pmeta_msg->label, p_dev);
2788 }
2789
2790 /***************************************************************************
2791 *
2792 * Function iterate_supported_event_list_for_interim_rsp
2793 *
2794 * Description iterator callback function to match the event and handle
2795 * timer cleanup
2796 * Returns true to continue iterating, false to stop
2797 *
2798 **************************************************************************/
iterate_supported_event_list_for_interim_rsp(void * data,void * cb_data)2799 static bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) {
2800 uint8_t* p_event_id;
2801 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
2802
2803 p_event_id = (uint8_t*)cb_data;
2804
2805 if (p_event->event_id == *p_event_id) {
2806 p_event->status = eINTERIM;
2807 return false;
2808 }
2809 return true;
2810 }
2811
2812 /***************************************************************************
2813 *
2814 * Function rc_notification_interim_timeout
2815 *
2816 * Description Interim response timeout handler.
2817 * Runs the iterator to check and clear the timed out event.
2818 * Proceeds to register for the unregistered events.
2819 * Returns None
2820 *
2821 **************************************************************************/
rc_notification_interim_timeout(btif_rc_device_cb_t * p_dev,uint8_t event_id)2822 static void rc_notification_interim_timeout(btif_rc_device_cb_t* p_dev, uint8_t event_id) {
2823 /* Device disconnections clear the event list but can't free the timer */
2824 if (p_dev == NULL || p_dev->rc_supported_event_list == NULL) {
2825 log::warn("timeout for null device or event list");
2826 return;
2827 }
2828
2829 // Remove the timed out event from the supported events list
2830 list_node_t* node = list_begin(p_dev->rc_supported_event_list);
2831 while (node != NULL) {
2832 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)list_node(node);
2833 if (p_event != nullptr && p_event->event_id == event_id) {
2834 list_remove(p_dev->rc_supported_event_list, p_event);
2835 break;
2836 }
2837 node = list_next(node);
2838 }
2839
2840 /* Timeout happened for interim response for the registered event,
2841 * check if there are any pending for registration
2842 */
2843 node = list_begin(p_dev->rc_supported_event_list);
2844 while (node != NULL) {
2845 btif_rc_supported_event_t* p_event;
2846
2847 p_event = (btif_rc_supported_event_t*)list_node(node);
2848 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
2849 register_for_event_notification(p_event, p_dev);
2850 break;
2851 }
2852 node = list_next(node);
2853 }
2854 /* Todo. Need to initiate application settings query if this
2855 * is the last event registration.
2856 */
2857 }
2858
2859 /***************************************************************************
2860 *
2861 * Function register_for_event_notification
2862 *
2863 * Description Helper function registering notification events
2864 * sets an interim response timeout to handle if the remote
2865 * does not respond.
2866 * Returns None
2867 *
2868 **************************************************************************/
register_for_event_notification(btif_rc_supported_event_t * p_event,btif_rc_device_cb_t * p_dev)2869 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
2870 btif_rc_device_cb_t* p_dev) {
2871 // interval is only valid for AVRC_EVT_PLAY_POS_CHANGED
2872 uint32_t interval_in_seconds = 0;
2873 if (p_event->event_id == AVRC_EVT_PLAY_POS_CHANGED) {
2874 interval_in_seconds = 2;
2875 }
2876 bt_status_t status = register_notification_cmd(p_event->event_id, interval_in_seconds, p_dev);
2877 if (status != BT_STATUS_SUCCESS) {
2878 log::error("failed, status={}", status);
2879 return;
2880 }
2881
2882 p_event->status = eREGISTERED;
2883 }
2884
2885 /***************************************************************************
2886 *
2887 * Function build_and_send_vendor_cmd
2888 *
2889 * Description Send a command to a device on the browsing channel
2890 *
2891 * Parameters avrc_cmd: The command you're sending
2892 * p_dev: Device control block
2893 *
2894 * Returns BT_STATUS_SUCCESS if command is issued successfully
2895 * otherwise BT_STATUS_FAIL
2896 *
2897 **************************************************************************/
build_and_send_vendor_cmd(tAVRC_COMMAND * avrc_cmd,tBTA_AV_CODE cmd_code,btif_rc_device_cb_t * p_dev)2898 static bt_status_t build_and_send_vendor_cmd(tAVRC_COMMAND* avrc_cmd, tBTA_AV_CODE cmd_code,
2899 btif_rc_device_cb_t* p_dev) {
2900 rc_transaction_t* p_transaction = NULL;
2901 rc_transaction_context_t context = {.rc_addr = p_dev->rc_addr,
2902 .label = MAX_LABEL,
2903 .opcode = AVRC_OP_VENDOR,
2904 .command = {.vendor = {avrc_cmd->pdu, AVRC_EVT_INVALID}}};
2905
2906 // Set the event ID in the context if this is a notification registration
2907 if (avrc_cmd->pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
2908 context.command.vendor.event_id = avrc_cmd->reg_notif.event_id;
2909 }
2910
2911 bt_status_t tran_status = get_transaction(p_dev, context, &p_transaction);
2912 if (BT_STATUS_SUCCESS != tran_status || p_transaction == NULL) {
2913 log::error("failed to get label, pdu_id={}, status=0x{:02x}", dump_rc_pdu(avrc_cmd->pdu),
2914 tran_status);
2915 return BT_STATUS_FAIL;
2916 }
2917
2918 BT_HDR* p_msg = NULL;
2919 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
2920 if (status == AVRC_STS_NO_ERROR && p_msg != NULL) {
2921 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
2922 log::verbose("{} msgreq being sent out with label: {}", dump_rc_pdu(avrc_cmd->pdu),
2923 p_transaction->label);
2924 BTA_AvVendorCmd(p_dev->rc_handle, p_transaction->label, cmd_code, data_start, p_msg->len);
2925 status = BT_STATUS_SUCCESS;
2926 start_transaction_timer(p_dev, p_transaction->label, BTIF_RC_TIMEOUT_MS);
2927 } else {
2928 log::error("failed to build command. status: 0x{:02x}", status);
2929 release_transaction(p_dev, p_transaction->label);
2930 }
2931 osi_free(p_msg);
2932 return (bt_status_t)status;
2933 }
2934
2935 /***************************************************************************
2936 *
2937 * Function build_and_send_browsing_cmd
2938 *
2939 * Description Send a command to a device on the browsing channel
2940 *
2941 * Parameters avrc_cmd: The command you're sending
2942 * p_dev: Device control block
2943 *
2944 * Returns BT_STATUS_SUCCESS if command is issued successfully
2945 * otherwise BT_STATUS_FAIL
2946 *
2947 **************************************************************************/
build_and_send_browsing_cmd(tAVRC_COMMAND * avrc_cmd,btif_rc_device_cb_t * p_dev)2948 static bt_status_t build_and_send_browsing_cmd(tAVRC_COMMAND* avrc_cmd,
2949 btif_rc_device_cb_t* p_dev) {
2950 rc_transaction_t* p_transaction = NULL;
2951 rc_transaction_context_t context = {.rc_addr = p_dev->rc_addr,
2952 .label = MAX_LABEL,
2953 .opcode = AVRC_OP_BROWSE,
2954 .command = {.browse = {avrc_cmd->pdu}}};
2955
2956 bt_status_t tran_status = get_transaction(p_dev, context, &p_transaction);
2957 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
2958 log::error("failed to get label, pdu_id={}, status=0x{:02x}", dump_rc_pdu(avrc_cmd->pdu),
2959 tran_status);
2960 return BT_STATUS_FAIL;
2961 }
2962
2963 BT_HDR* p_msg = NULL;
2964 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
2965 if (status != AVRC_STS_NO_ERROR) {
2966 log::error("failed to build command status {}", status);
2967 release_transaction(p_dev, p_transaction->label);
2968 return BT_STATUS_FAIL;
2969 }
2970
2971 log::verbose("Send pdu_id={}, label={}", dump_rc_pdu(avrc_cmd->pdu), p_transaction->label);
2972 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->label, AVRC_CMD_CTRL, p_msg);
2973 start_transaction_timer(p_dev, p_transaction->label, BTIF_RC_TIMEOUT_MS);
2974 return BT_STATUS_SUCCESS;
2975 }
2976
2977 /***************************************************************************
2978 *
2979 * Function handle_get_capability_response
2980 *
2981 * Description Handles the get_cap_response to populate company id info
2982 * and query the supported events.
2983 * Initiates Notification registration for events supported
2984 * Returns None
2985 *
2986 **************************************************************************/
handle_get_capability_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CAPS_RSP * p_rsp)2987 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_GET_CAPS_RSP* p_rsp) {
2988 int xx = 0;
2989 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
2990
2991 /* Todo: Do we need to retry on command timeout */
2992 if (p_rsp->status != AVRC_STS_NO_ERROR) {
2993 log::error("Error capability response: 0x{:02X}", p_rsp->status);
2994 return;
2995 }
2996
2997 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
2998 btif_rc_supported_event_t* p_event;
2999
3000 /* Todo: Check if list can be active when we hit here */
3001 p_dev->rc_supported_event_list = list_new(osi_free);
3002 for (xx = 0; xx < p_rsp->count; xx++) {
3003 /* Skip registering for Play position change notification */
3004 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) ||
3005 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) ||
3006 (p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_POS_CHANGED) ||
3007 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) ||
3008 (p_rsp->param.event_id[xx] == AVRC_EVT_NOW_PLAYING_CHANGE) ||
3009 (p_rsp->param.event_id[xx] == AVRC_EVT_ADDR_PLAYER_CHANGE) ||
3010 (p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE) ||
3011 (p_rsp->param.event_id[xx] == AVRC_EVT_AVAL_PLAYERS_CHANGE)) {
3012 p_event = (btif_rc_supported_event_t*)osi_malloc(sizeof(btif_rc_supported_event_t));
3013 p_event->event_id = p_rsp->param.event_id[xx];
3014 p_event->status = eNOT_REGISTERED;
3015 list_append(p_dev->rc_supported_event_list, p_event);
3016 }
3017 }
3018
3019 // On occasion a remote device can intermittently send a poorly configured
3020 // packet with 0 capabilities. This check ensures the stack does not crash.
3021 // Typically the remote device will send a proper packet in the future and
3022 // continue operation.
3023 if (list_is_empty(p_dev->rc_supported_event_list)) {
3024 return;
3025 }
3026
3027 p_event = (btif_rc_supported_event_t*)list_front(p_dev->rc_supported_event_list);
3028 if (p_event != NULL) {
3029 register_for_event_notification(p_event, p_dev);
3030 }
3031 } else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
3032 getcapabilities_cmd(AVRC_CAP_EVENTS_SUPPORTED, p_dev);
3033 log::verbose("AVRC_CAP_COMPANY_ID:");
3034 for (xx = 0; xx < p_rsp->count; xx++) {
3035 log::verbose("company_id: {}", p_rsp->param.company_id[xx]);
3036 }
3037 }
3038 }
3039
rc_is_track_id_valid(tAVRC_UID uid)3040 static bool rc_is_track_id_valid(tAVRC_UID uid) {
3041 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3042
3043 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0) {
3044 return false;
3045 } else {
3046 return true;
3047 }
3048 }
3049
3050 /***************************************************************************
3051 *
3052 * Function handle_notification_response
3053 *
3054 * Description Main handler for notification responses to registered events
3055 * 1. Register for unregistered event(in interim response path)
3056 * 2. After registering for all supported events, start
3057 * retrieving application settings and values
3058 * 3. Reregister for events on getting changed response
3059 * 4. Run play status timer for getting position when the
3060 * status changes to playing
3061 * 5. Get the Media details when the track change happens
3062 * or track change interim response is received with
3063 * valid track id
3064 * 6. HAL callback for play status change and application
3065 * setting change
3066 * Returns None
3067 *
3068 **************************************************************************/
handle_notification_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_REG_NOTIF_RSP * p_rsp)3069 static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_REG_NOTIF_RSP* p_rsp) {
3070 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3071
3072 if (p_dev == NULL) {
3073 log::error("p_dev NULL");
3074 return;
3075 }
3076
3077 if (btif_av_src_sink_coexist_enabled() && p_rsp->event_id == AVRC_EVT_VOLUME_CHANGE) {
3078 log::error("legacy TG don't handle absolute volume change. leave it to new avrcp");
3079 return;
3080 }
3081
3082 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
3083 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
3084
3085 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
3086 btif_rc_supported_event_t* p_event;
3087 list_node_t* node;
3088
3089 log::verbose("Interim response: 0x{:2X}", p_rsp->event_id);
3090 switch (p_rsp->event_id) {
3091 case AVRC_EVT_PLAY_STATUS_CHANGE:
3092 get_play_status_cmd(p_dev);
3093 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->play_status_changed_cb,
3094 p_dev->rc_addr,
3095 (btrc_play_status_t)p_rsp->param.play_status));
3096 break;
3097
3098 case AVRC_EVT_TRACK_CHANGE:
3099 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3100 break;
3101 } else {
3102 uint8_t* p_data = p_rsp->param.track;
3103 BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
3104 get_play_status_cmd(p_dev);
3105 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
3106 }
3107 break;
3108
3109 case AVRC_EVT_APP_SETTING_CHANGE:
3110 break;
3111
3112 case AVRC_EVT_NOW_PLAYING_CHANGE:
3113 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->now_playing_contents_changed_cb,
3114 p_dev->rc_addr));
3115 break;
3116
3117 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3118 log::verbose("AVRC_EVT_AVAL_PLAYERS_CHANGE");
3119 do_in_jni_thread(
3120 base::BindOnce(bt_rc_ctrl_callbacks->available_player_changed_cb, p_dev->rc_addr));
3121 break;
3122
3123 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3124 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->addressed_player_changed_cb,
3125 p_dev->rc_addr, p_rsp->param.addr_player.player_id));
3126 break;
3127
3128 case AVRC_EVT_PLAY_POS_CHANGED:
3129 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->play_position_changed_cb,
3130 p_dev->rc_addr, 0, p_rsp->param.play_pos));
3131
3132 break;
3133 case AVRC_EVT_UIDS_CHANGE:
3134 break;
3135
3136 case AVRC_EVT_TRACK_REACHED_END:
3137 case AVRC_EVT_TRACK_REACHED_START:
3138 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3139 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3140 default:
3141 log::error("Unhandled interim response: 0x{:2X}", p_rsp->event_id);
3142 return;
3143 }
3144
3145 list_foreach(p_dev->rc_supported_event_list, iterate_supported_event_list_for_interim_rsp,
3146 &p_rsp->event_id);
3147
3148 node = list_begin(p_dev->rc_supported_event_list);
3149
3150 while (node != NULL) {
3151 p_event = (btif_rc_supported_event_t*)list_node(node);
3152 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
3153 register_for_event_notification(p_event, p_dev);
3154 break;
3155 }
3156 node = list_next(node);
3157 p_event = NULL;
3158 }
3159 /* Registered for all events, we can request application settings */
3160 if (p_event == NULL && !p_dev->rc_app_settings.query_started) {
3161 /* we need to do this only if remote TG supports
3162 * player application settings
3163 */
3164 p_dev->rc_app_settings.query_started = true;
3165 if (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING) {
3166 list_player_app_setting_attrib_cmd(p_dev);
3167 } else {
3168 log::verbose("App setting not supported, complete procedure");
3169 rc_ctrl_procedure_complete(p_dev);
3170 }
3171 }
3172 } else if (pmeta_msg->code == AVRC_RSP_CHANGED) {
3173 btif_rc_supported_event_t* p_event;
3174 list_node_t* node;
3175
3176 log::verbose("Notification completed: 0x{:2X}", p_rsp->event_id);
3177
3178 node = list_begin(p_dev->rc_supported_event_list);
3179
3180 while (node != NULL) {
3181 p_event = (btif_rc_supported_event_t*)list_node(node);
3182 if (p_event != NULL && p_event->event_id == p_rsp->event_id) {
3183 p_event->status = eNOT_REGISTERED;
3184 register_for_event_notification(p_event, p_dev);
3185 break;
3186 }
3187 node = list_next(node);
3188 }
3189
3190 switch (p_rsp->event_id) {
3191 case AVRC_EVT_PLAY_STATUS_CHANGE:
3192 /* Start timer to get play status periodically
3193 * if the play state is playing.
3194 */
3195 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->play_status_changed_cb,
3196 p_dev->rc_addr,
3197 (btrc_play_status_t)p_rsp->param.play_status));
3198
3199 break;
3200
3201 case AVRC_EVT_TRACK_CHANGE:
3202 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3203 break;
3204 }
3205 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
3206 break;
3207
3208 case AVRC_EVT_APP_SETTING_CHANGE: {
3209 btrc_player_settings_t app_settings;
3210 uint16_t xx;
3211
3212 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
3213 for (xx = 0; xx < app_settings.num_attr; xx++) {
3214 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
3215 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
3216 }
3217 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
3218 p_dev->rc_addr, app_settings));
3219 } break;
3220
3221 case AVRC_EVT_NOW_PLAYING_CHANGE:
3222 break;
3223
3224 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3225 break;
3226
3227 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3228 break;
3229
3230 case AVRC_EVT_PLAY_POS_CHANGED:
3231 // handle on interim
3232 break;
3233
3234 case AVRC_EVT_UIDS_CHANGE:
3235 break;
3236
3237 case AVRC_EVT_TRACK_REACHED_END:
3238 case AVRC_EVT_TRACK_REACHED_START:
3239 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3240 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3241 default:
3242 log::error("Unhandled completion response: 0x{:2X}", p_rsp->event_id);
3243 return;
3244 }
3245 }
3246 }
3247
3248 /***************************************************************************
3249 *
3250 * Function handle_app_attr_response
3251 *
3252 * Description handles the the application attributes response and
3253 * initiates procedure to fetch the attribute values
3254 * Returns None
3255 *
3256 **************************************************************************/
handle_app_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_ATTR_RSP * p_rsp)3257 static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_LIST_APP_ATTR_RSP* p_rsp) {
3258 uint8_t xx;
3259 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3260
3261 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3262 log::error("Error getting Player application settings: 0x{:2X}", p_rsp->status);
3263 rc_ctrl_procedure_complete(p_dev);
3264 return;
3265 }
3266 p_dev->rc_app_settings.num_attrs = 0;
3267 p_dev->rc_app_settings.num_ext_attrs = 0;
3268
3269 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3270 uint8_t st_index;
3271
3272 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT) {
3273 st_index = p_dev->rc_app_settings.num_ext_attrs;
3274 p_dev->rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
3275 p_dev->rc_app_settings.num_ext_attrs++;
3276 } else {
3277 st_index = p_dev->rc_app_settings.num_attrs;
3278 p_dev->rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
3279 p_dev->rc_app_settings.num_attrs++;
3280 }
3281 }
3282 p_dev->rc_app_settings.attr_index = 0;
3283 p_dev->rc_app_settings.ext_attr_index = 0;
3284 p_dev->rc_app_settings.ext_val_index = 0;
3285 if (p_rsp->num_attr) {
3286 list_player_app_setting_value_cmd(p_dev->rc_app_settings.attrs[0].attr_id, p_dev);
3287 } else {
3288 log::error("No Player application settings found");
3289 }
3290 }
3291
3292 /***************************************************************************
3293 *
3294 * Function handle_app_val_response
3295 *
3296 * Description handles the the attributes value response and if extended
3297 * menu is available, it initiates query for the attribute
3298 * text. If not, it initiates procedure to get the current
3299 * attribute values and calls the HAL callback for provding
3300 * application settings information.
3301 * Returns None
3302 *
3303 **************************************************************************/
handle_app_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_VALUES_RSP * p_rsp)3304 static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_LIST_APP_VALUES_RSP* p_rsp) {
3305 uint8_t xx, attr_index;
3306 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3307 btif_rc_player_app_settings_t* p_app_settings;
3308 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3309
3310 /* Todo: Do we need to retry on command timeout */
3311 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3312 log::error("Error fetching attribute values: 0x{:02X}", p_rsp->status);
3313 return;
3314 }
3315
3316 p_app_settings = &p_dev->rc_app_settings;
3317
3318 if (p_app_settings->attr_index < p_app_settings->num_attrs) {
3319 attr_index = p_app_settings->attr_index;
3320 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
3321 for (xx = 0; xx < p_rsp->num_val; xx++) {
3322 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
3323 }
3324 attr_index++;
3325 p_app_settings->attr_index++;
3326 if (attr_index < p_app_settings->num_attrs) {
3327 list_player_app_setting_value_cmd(p_app_settings->attrs[p_app_settings->attr_index].attr_id,
3328 p_dev);
3329 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3330 attr_index = 0;
3331 p_app_settings->ext_attr_index = 0;
3332 list_player_app_setting_value_cmd(p_app_settings->ext_attrs[attr_index].attr_id, p_dev);
3333 } else {
3334 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3335 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3336 }
3337 get_player_app_setting_cmd(p_app_settings->num_attrs, attrs, p_dev);
3338 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3339 p_dev->rc_addr, p_app_settings->num_attrs,
3340 p_app_settings->attrs, 0, nullptr));
3341 }
3342 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3343 attr_index = p_app_settings->ext_attr_index;
3344 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
3345 for (xx = 0; xx < p_rsp->num_val; xx++) {
3346 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
3347 }
3348 attr_index++;
3349 p_app_settings->ext_attr_index++;
3350 if (attr_index < p_app_settings->num_ext_attrs) {
3351 list_player_app_setting_value_cmd(
3352 p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id, p_dev);
3353 } else {
3354 uint8_t attr[AVRC_MAX_APP_ATTR_SIZE];
3355
3356 for (uint8_t xx = 0; xx < p_app_settings->num_ext_attrs; xx++) {
3357 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
3358 }
3359 get_player_app_setting_attr_text_cmd(attr, p_app_settings->num_ext_attrs, p_dev);
3360 }
3361 }
3362 }
3363
3364 /***************************************************************************
3365 *
3366 * Function handle_app_cur_val_response
3367 *
3368 * Description handles the the get attributes value response.
3369 *
3370 * Returns None
3371 *
3372 **************************************************************************/
handle_app_cur_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp)3373 static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg,
3374 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp) {
3375 btrc_player_settings_t app_settings;
3376 uint16_t xx;
3377 btif_rc_device_cb_t* p_dev = NULL;
3378
3379 /* Todo: Do we need to retry on command timeout */
3380 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3381 log::error("Error fetching current settings: 0x{:02X}", p_rsp->status);
3382 return;
3383 }
3384 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3385 if (p_dev == NULL) {
3386 log::error("Error in getting Device Address");
3387 osi_free_and_reset((void**)&p_rsp->p_vals);
3388 return;
3389 }
3390
3391 app_settings.num_attr = p_rsp->num_val;
3392
3393 if (app_settings.num_attr > BTRC_MAX_APP_SETTINGS) {
3394 app_settings.num_attr = BTRC_MAX_APP_SETTINGS;
3395 }
3396
3397 for (xx = 0; xx < app_settings.num_attr; xx++) {
3398 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
3399 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
3400 }
3401
3402 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
3403 p_dev->rc_addr, app_settings));
3404 /* Application settings are fetched only once for initial values
3405 * initiate anything that follows after RC procedure.
3406 * Defer it if browsing is supported till players query
3407 */
3408 rc_ctrl_procedure_complete(p_dev);
3409 osi_free_and_reset((void**)&p_rsp->p_vals);
3410 }
3411
3412 /***************************************************************************
3413 *
3414 * Function handle_app_attr_txt_response
3415 *
3416 * Description handles the the get attributes text response, if fails
3417 * calls HAL callback with just normal settings and initiates
3418 * query for current settings else initiates query for value
3419 * text
3420 * Returns None
3421 *
3422 **************************************************************************/
handle_app_attr_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3423 static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg,
3424 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3425 uint8_t xx;
3426 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3427 btif_rc_player_app_settings_t* p_app_settings;
3428 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3429
3430 if (p_dev == NULL) {
3431 log::error("p_dev NULL");
3432 return;
3433 }
3434
3435 p_app_settings = &p_dev->rc_app_settings;
3436
3437 /* Todo: Do we need to retry on command timeout */
3438 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3439 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3440
3441 log::error("Error fetching attribute text: 0x{:02X}", p_rsp->status);
3442 /* Not able to fetch Text for extended Menu, skip the process
3443 * and cleanup used memory. Proceed to get the current settings
3444 * for standard attributes.
3445 */
3446 p_app_settings->num_ext_attrs = 0;
3447 for (xx = 0; xx < p_app_settings->ext_attr_index && xx < AVRC_MAX_APP_ATTR_SIZE; xx++) {
3448 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3449 }
3450 p_app_settings->ext_attr_index = 0;
3451
3452 for (xx = 0; xx < p_app_settings->num_attrs && xx < AVRC_MAX_APP_ATTR_SIZE; xx++) {
3453 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3454 }
3455
3456 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3457 p_dev->rc_addr, p_app_settings->num_attrs,
3458 p_app_settings->attrs, 0, nullptr));
3459 get_player_app_setting_cmd(xx, attrs, p_dev);
3460
3461 return;
3462 }
3463
3464 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3465 uint8_t x;
3466 for (x = 0; x < p_app_settings->num_ext_attrs && x < AVRC_MAX_APP_ATTR_SIZE; x++) {
3467 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id) {
3468 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3469 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
3470 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
3471 break;
3472 }
3473 }
3474 }
3475
3476 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val && xx < BTRC_MAX_APP_ATTR_SIZE; xx++) {
3477 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
3478 }
3479 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3480 }
3481
3482 /***************************************************************************
3483 *
3484 * Function handle_app_attr_val_txt_response
3485 *
3486 * Description handles the the get attributes value text response, if fails
3487 * calls HAL callback with just normal settings and initiates
3488 * query for current settings
3489 * Returns None
3490 *
3491 **************************************************************************/
handle_app_attr_val_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3492 static void handle_app_attr_val_txt_response(tBTA_AV_META_MSG* pmeta_msg,
3493 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3494 uint8_t xx, attr_index;
3495 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3496 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3497 btif_rc_player_app_settings_t* p_app_settings;
3498 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3499
3500 if (p_dev == NULL) {
3501 log::error("p_dev NULL");
3502 return;
3503 }
3504
3505 p_app_settings = &p_dev->rc_app_settings;
3506
3507 /* Todo: Do we need to retry on command timeout */
3508 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3509 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3510
3511 log::error("Error fetching attribute value text: 0x{:02X}", p_rsp->status);
3512
3513 /* Not able to fetch Text for extended Menu, skip the process
3514 * and cleanup used memory. Proceed to get the current settings
3515 * for standard attributes.
3516 */
3517 p_app_settings->num_ext_attrs = 0;
3518 for (xx = 0; xx < p_app_settings->ext_attr_index && xx < AVRC_MAX_APP_ATTR_SIZE; xx++) {
3519 int x;
3520 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3521
3522 for (x = 0; x < p_ext_attr->num_val && x < BTRC_MAX_APP_ATTR_SIZE; x++) {
3523 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3524 }
3525 p_ext_attr->num_val = 0;
3526 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3527 }
3528 p_app_settings->ext_attr_index = 0;
3529
3530 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3531 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3532 }
3533 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3534 p_dev->rc_addr, p_app_settings->num_attrs,
3535 p_app_settings->attrs, 0, nullptr));
3536
3537 get_player_app_setting_cmd(xx, attrs, p_dev);
3538 return;
3539 }
3540
3541 if (p_app_settings->ext_val_index >= AVRC_MAX_APP_ATTR_SIZE) {
3542 log::error("ext_val_index is 0x{:02x}, overflow!", p_app_settings->ext_val_index);
3543 return;
3544 }
3545
3546 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3547 uint8_t x;
3548 btrc_player_app_ext_attr_t* p_ext_attr;
3549 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
3550 for (x = 0; x < p_rsp->num_attr && x < BTRC_MAX_APP_ATTR_SIZE; x++) {
3551 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id) {
3552 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3553 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
3554 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
3555 break;
3556 }
3557 }
3558 }
3559 p_app_settings->ext_val_index++;
3560
3561 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs) {
3562 attr_index = p_app_settings->ext_val_index;
3563 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++) {
3564 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
3565 }
3566 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3567 } else {
3568 uint8_t x;
3569
3570 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3571 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3572 }
3573 for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
3574 attrs[xx + x] = p_app_settings->ext_attrs[x].attr_id;
3575 }
3576 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3577 p_dev->rc_addr, p_app_settings->num_attrs,
3578 p_app_settings->attrs, p_app_settings->num_ext_attrs,
3579 p_app_settings->ext_attrs));
3580 get_player_app_setting_cmd(xx + x, attrs, p_dev);
3581
3582 /* Free the application settings information after sending to
3583 * application.
3584 */
3585 do_in_jni_thread(base::BindOnce(cleanup_app_attr_val_txt_response, p_app_settings));
3586 p_app_settings->num_attrs = 0;
3587 }
3588 }
3589
3590 /***************************************************************************
3591 *
3592 * Function cleanup_app_attr_val_txt_response
3593 *
3594 * Description Frees the memory that was allocated for reporting player
3595 * application settings.
3596 * Returns None
3597 **************************************************************************/
cleanup_app_attr_val_txt_response(btif_rc_player_app_settings_t * p_app_settings)3598 static void cleanup_app_attr_val_txt_response(btif_rc_player_app_settings_t* p_app_settings) {
3599 for (uint8_t xx = 0; xx < p_app_settings->ext_attr_index && xx < AVRC_MAX_APP_ATTR_SIZE; xx++) {
3600 int x;
3601 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3602 for (x = 0; x < p_ext_attr->num_val && x < BTRC_MAX_APP_ATTR_SIZE; x++) {
3603 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3604 }
3605 p_ext_attr->num_val = 0;
3606 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3607 }
3608 }
3609
3610 /***************************************************************************
3611 *
3612 * Function handle_set_app_attr_val_response
3613 *
3614 * Description handles the the set attributes value response, if fails
3615 * calls HAL callback to indicate the failure
3616 * Returns None
3617 *
3618 **************************************************************************/
handle_set_app_attr_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP *)3619 static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* /*p_rsp*/) {
3620 uint8_t accepted = 0;
3621 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3622
3623 if (p_dev == NULL) {
3624 log::error("p_dev NULL");
3625 return;
3626 }
3627
3628 /* For timeout pmeta_msg will be NULL, else we need to
3629 * check if this is accepted by TG
3630 */
3631 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT)) {
3632 accepted = 1;
3633 }
3634 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->setplayerappsetting_rsp_cb, p_dev->rc_addr,
3635 accepted));
3636 }
3637
3638 /***************************************************************************
3639 *
3640 * Function handle_get_metadata_attr_response
3641 *
3642 * Description handles the the element attributes response, calls
3643 * HAL callback to update track change information.
3644 * Returns None
3645 *
3646 **************************************************************************/
handle_get_metadata_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ATTRS_RSP * p_rsp)3647 static void handle_get_metadata_attr_response(tBTA_AV_META_MSG* pmeta_msg,
3648 tAVRC_GET_ATTRS_RSP* p_rsp) {
3649 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3650
3651 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3652 size_t buf_size = p_rsp->num_attrs * sizeof(btrc_element_attr_val_t);
3653 btrc_element_attr_val_t* p_attr = (btrc_element_attr_val_t*)osi_calloc(buf_size);
3654
3655 if (p_dev == NULL) {
3656 log::error("p_dev NULL");
3657 return;
3658 }
3659
3660 for (int i = 0; i < p_rsp->num_attrs; i++) {
3661 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3662 /* Todo. Length limit check to include null */
3663 if (p_rsp->p_attrs[i].name.str_len && p_rsp->p_attrs[i].name.p_str) {
3664 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str, p_rsp->p_attrs[i].name.str_len);
3665 osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str);
3666 }
3667 }
3668
3669 osi_free_and_reset((void**)&p_rsp->p_attrs);
3670
3671 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->track_changed_cb, p_dev->rc_addr,
3672 p_rsp->num_attrs, p_attr));
3673 do_in_jni_thread(base::BindOnce(osi_free, p_attr));
3674 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3675 /* Retry for timeout case, this covers error handling
3676 * for continuation failure also.
3677 */
3678 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
3679 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
3680 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
3681 } else {
3682 log::error("Error in get element attr procedure: {}", p_rsp->status);
3683 }
3684 }
3685
3686 /***************************************************************************
3687 *
3688 * Function handle_get_playstatus_response
3689 *
3690 * Description handles the the play status response, calls
3691 * HAL callback to update play position.
3692 * Returns None
3693 *
3694 **************************************************************************/
handle_get_playstatus_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_PLAY_STATUS_RSP * p_rsp)3695 static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
3696 tAVRC_GET_PLAY_STATUS_RSP* p_rsp) {
3697 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3698
3699 if (p_dev == NULL) {
3700 log::error("p_dev NULL");
3701 return;
3702 }
3703
3704 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3705 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->play_status_changed_cb, p_dev->rc_addr,
3706 (btrc_play_status_t)p_rsp->play_status));
3707 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->play_position_changed_cb, p_dev->rc_addr,
3708 p_rsp->song_len, p_rsp->song_pos));
3709 } else {
3710 log::error("Error in get play status procedure: {}", p_rsp->status);
3711 }
3712 }
3713
3714 /***************************************************************************
3715 *
3716 * Function handle_set_addressed_player_response
3717 *
3718 * Description handles the the set addressed player response, calls
3719 * HAL callback
3720 * Returns None
3721 *
3722 **************************************************************************/
handle_set_addressed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)3723 static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* p_rsp) {
3724 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3725
3726 if (p_dev == NULL) {
3727 log::error("p_dev NULL");
3728 return;
3729 }
3730
3731 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3732 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->set_addressed_player_cb, p_dev->rc_addr,
3733 p_rsp->status));
3734 } else {
3735 log::error("Error in get play status procedure {}", p_rsp->status);
3736 }
3737 }
3738
3739 /***************************************************************************
3740 *
3741 * Function handle_get_folder_items_response
3742 *
3743 * Description handles the the get folder items response, calls
3744 * HAL callback to send the folder items.
3745 * Returns None
3746 *
3747 **************************************************************************/
handle_get_folder_items_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ITEMS_RSP * p_rsp)3748 static void handle_get_folder_items_response(tBTA_AV_META_MSG* pmeta_msg,
3749 tAVRC_GET_ITEMS_RSP* p_rsp) {
3750 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3751
3752 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3753 /* Convert the internal folder listing into a response that can
3754 * be passed onto JNI via HAL_CBACK
3755 */
3756 uint8_t item_count = p_rsp->item_count;
3757 btrc_folder_items_t* btrc_items =
3758 (btrc_folder_items_t*)osi_malloc(sizeof(btrc_folder_items_t) * item_count);
3759 for (uint8_t i = 0; i < item_count; i++) {
3760 const tAVRC_ITEM* avrc_item = &(p_rsp->p_item_list[i]);
3761 btrc_folder_items_t* btrc_item = &(btrc_items[i]);
3762 log::verbose("folder item type {}", avrc_item->item_type);
3763 switch (avrc_item->item_type) {
3764 case AVRC_ITEM_MEDIA:
3765 log::verbose("setting type to {}", BTRC_ITEM_MEDIA);
3766 /* Allocate Space for Attributes */
3767 btrc_item->media.num_attrs = avrc_item->u.media.attr_count;
3768 btrc_item->media.p_attrs = (btrc_element_attr_val_t*)osi_malloc(
3769 btrc_item->media.num_attrs * sizeof(btrc_element_attr_val_t));
3770 get_folder_item_type_media(avrc_item, btrc_item);
3771 break;
3772
3773 case AVRC_ITEM_FOLDER:
3774 log::verbose("setting type to BTRC_ITEM_FOLDER");
3775 get_folder_item_type_folder(avrc_item, btrc_item);
3776 break;
3777
3778 case AVRC_ITEM_PLAYER:
3779 log::verbose("setting type to BTRC_ITEM_PLAYER");
3780 get_folder_item_type_player(avrc_item, btrc_item);
3781 break;
3782
3783 default:
3784 log::error("cannot understand folder item type {}", avrc_item->item_type);
3785 }
3786 }
3787
3788 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
3789 BTRC_STS_NO_ERROR,
3790 /* We want to make the ownership explicit in native */
3791 btrc_items, item_count));
3792
3793 if (item_count > 0) {
3794 if (btrc_items[0].item_type == AVRC_ITEM_PLAYER &&
3795 (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING)) {
3796 list_player_app_setting_attrib_cmd(p_dev);
3797 }
3798 }
3799 /* Release the memory block for items and attributes allocated here.
3800 * Since the executor for do_in_jni_thread is a Single Thread Task Runner it
3801 * is okay to queue up the cleanup of btrc_items */
3802 do_in_jni_thread(base::BindOnce(cleanup_btrc_folder_items, btrc_items, item_count));
3803
3804 log::verbose("get_folder_items_cb sent to JNI thread");
3805 } else {
3806 log::error("Error {}", p_rsp->status);
3807 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
3808 (btrc_status_t)p_rsp->status, nullptr, 0));
3809 }
3810 }
3811 /***************************************************************************
3812 *
3813 * Function cleanup_btrc_folder_items
3814 *
3815 * Description Frees the memory that was allocated for a list of folder
3816 * items.
3817 * Returns None
3818 **************************************************************************/
cleanup_btrc_folder_items(btrc_folder_items_t * btrc_items,uint8_t item_count)3819 static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items, uint8_t item_count) {
3820 for (uint8_t i = 0; i < item_count; i++) {
3821 btrc_folder_items_t* btrc_item = &(btrc_items[i]);
3822 switch (btrc_item->item_type) {
3823 case BTRC_ITEM_MEDIA:
3824 osi_free(btrc_item->media.p_attrs);
3825 break;
3826 case BTRC_ITEM_PLAYER:
3827 case BTRC_ITEM_FOLDER:
3828 /*Nothing to free*/
3829 break;
3830 default:
3831 log::warn("free unspecified type");
3832 }
3833 }
3834 osi_free(btrc_items);
3835 }
3836
3837 /***************************************************************************
3838 *
3839 * Function get_folder_item_type_media
3840 *
3841 * Description Converts the AVRC representation of a folder item with
3842 * TYPE media to BTIF representation.
3843 * Returns None
3844 *
3845 **************************************************************************/
get_folder_item_type_media(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)3846 static void get_folder_item_type_media(const tAVRC_ITEM* avrc_item,
3847 btrc_folder_items_t* btrc_item) {
3848 btrc_item->item_type = BTRC_ITEM_MEDIA;
3849 const tAVRC_ITEM_MEDIA* avrc_item_media = &(avrc_item->u.media);
3850 btrc_item_media_t* btrc_item_media = &(btrc_item->media);
3851 /* UID */
3852 memset(btrc_item_media->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
3853 memcpy(btrc_item_media->uid, avrc_item_media->uid, sizeof(uint8_t) * BTRC_UID_SIZE);
3854
3855 /* Audio/Video type */
3856 switch (avrc_item_media->type) {
3857 case AVRC_MEDIA_TYPE_AUDIO:
3858 btrc_item_media->type = BTRC_MEDIA_TYPE_AUDIO;
3859 break;
3860 case AVRC_MEDIA_TYPE_VIDEO:
3861 btrc_item_media->type = BTRC_MEDIA_TYPE_VIDEO;
3862 break;
3863 }
3864
3865 /* Charset ID */
3866 btrc_item_media->charset_id = avrc_item_media->name.charset_id;
3867
3868 /* Copy the name */
3869 log::verbose("max len {} str len {}", BTRC_MAX_ATTR_STR_LEN, avrc_item_media->name.str_len);
3870 memset(btrc_item_media->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
3871 memcpy(btrc_item_media->name, avrc_item_media->name.p_str,
3872 sizeof(uint8_t) * (avrc_item_media->name.str_len));
3873
3874 /* Extract each attribute */
3875 for (int i = 0; i < avrc_item_media->attr_count; i++) {
3876 btrc_element_attr_val_t* btrc_attr_pair = &(btrc_item_media->p_attrs[i]);
3877 tAVRC_ATTR_ENTRY* avrc_attr_pair = &(avrc_item_media->p_attr_list[i]);
3878
3879 log::verbose("media attr id 0x{:x}", avrc_attr_pair->attr_id);
3880
3881 switch (avrc_attr_pair->attr_id) {
3882 case AVRC_MEDIA_ATTR_ID_TITLE:
3883 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TITLE;
3884 break;
3885 case AVRC_MEDIA_ATTR_ID_ARTIST:
3886 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ARTIST;
3887 break;
3888 case AVRC_MEDIA_ATTR_ID_ALBUM:
3889 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ALBUM;
3890 break;
3891 case AVRC_MEDIA_ATTR_ID_TRACK_NUM:
3892 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TRACK_NUM;
3893 break;
3894 case AVRC_MEDIA_ATTR_ID_NUM_TRACKS:
3895 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_NUM_TRACKS;
3896 break;
3897 case AVRC_MEDIA_ATTR_ID_GENRE:
3898 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_GENRE;
3899 break;
3900 case AVRC_MEDIA_ATTR_ID_PLAYING_TIME:
3901 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_PLAYING_TIME;
3902 break;
3903 case AVRC_MEDIA_ATTR_ID_COVER_ARTWORK_HANDLE:
3904 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_COVER_ARTWORK_HANDLE;
3905 break;
3906 default:
3907 log::error("invalid media attr id: 0x{:x}", avrc_attr_pair->attr_id);
3908 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_INVALID;
3909 }
3910
3911 memset(btrc_attr_pair->text, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
3912 memcpy(btrc_attr_pair->text, avrc_attr_pair->name.p_str, avrc_attr_pair->name.str_len);
3913 }
3914 }
3915
3916 /***************************************************************************
3917 *
3918 * Function get_folder_item_type_folder
3919 *
3920 * Description Converts the AVRC representation of a folder item with
3921 * TYPE folder to BTIF representation.
3922 * Returns None
3923 *
3924 **************************************************************************/
get_folder_item_type_folder(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)3925 static void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
3926 btrc_folder_items_t* btrc_item) {
3927 btrc_item->item_type = BTRC_ITEM_FOLDER;
3928 const tAVRC_ITEM_FOLDER* avrc_item_folder = &(avrc_item->u.folder);
3929 btrc_item_folder_t* btrc_item_folder = &(btrc_item->folder);
3930 /* Copy the UID */
3931 memset(btrc_item_folder->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
3932 memcpy(btrc_item_folder->uid, avrc_item_folder->uid, sizeof(uint8_t) * BTRC_UID_SIZE);
3933
3934 /* Copy the type */
3935 switch (avrc_item_folder->type) {
3936 case AVRC_FOLDER_TYPE_MIXED:
3937 btrc_item_folder->type = BTRC_FOLDER_TYPE_MIXED;
3938 break;
3939 case AVRC_FOLDER_TYPE_TITLES:
3940 btrc_item_folder->type = BTRC_FOLDER_TYPE_TITLES;
3941 break;
3942 case AVRC_FOLDER_TYPE_ALNUMS:
3943 btrc_item_folder->type = BTRC_FOLDER_TYPE_ALBUMS;
3944 break;
3945 case AVRC_FOLDER_TYPE_ARTISTS:
3946 btrc_item_folder->type = BTRC_FOLDER_TYPE_ARTISTS;
3947 break;
3948 case AVRC_FOLDER_TYPE_GENRES:
3949 btrc_item_folder->type = BTRC_FOLDER_TYPE_GENRES;
3950 break;
3951 case AVRC_FOLDER_TYPE_PLAYLISTS:
3952 btrc_item_folder->type = BTRC_FOLDER_TYPE_PLAYLISTS;
3953 break;
3954 case AVRC_FOLDER_TYPE_YEARS:
3955 btrc_item_folder->type = BTRC_FOLDER_TYPE_YEARS;
3956 break;
3957 }
3958
3959 /* Copy if playable */
3960 btrc_item_folder->playable = avrc_item_folder->playable;
3961
3962 /* Copy name */
3963 log::verbose("max len {} str len {}", BTRC_MAX_ATTR_STR_LEN, avrc_item_folder->name.str_len);
3964 memset(btrc_item_folder->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
3965 memcpy(btrc_item_folder->name, avrc_item_folder->name.p_str,
3966 avrc_item_folder->name.str_len * sizeof(uint8_t));
3967
3968 /* Copy charset */
3969 btrc_item_folder->charset_id = avrc_item_folder->name.charset_id;
3970 }
3971
3972 /***************************************************************************
3973 *
3974 * Function get_folder_item_type_player
3975 *
3976 * Description Converts the AVRC representation of a folder item with
3977 * TYPE player to BTIF representation.
3978 * Returns None
3979 *
3980 **************************************************************************/
get_folder_item_type_player(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)3981 static void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
3982 btrc_folder_items_t* btrc_item) {
3983 btrc_item->item_type = BTRC_ITEM_PLAYER;
3984 const tAVRC_ITEM_PLAYER* avrc_item_player = &(avrc_item->u.player);
3985 btrc_item_player_t* btrc_item_player = &(btrc_item->player);
3986 /* Player ID */
3987 btrc_item_player->player_id = avrc_item_player->player_id;
3988 /* Major type */
3989 btrc_item_player->major_type = avrc_item_player->major_type;
3990 /* Sub type */
3991 btrc_item_player->sub_type = avrc_item_player->sub_type;
3992 /* Play status */
3993 btrc_item_player->play_status = avrc_item_player->play_status;
3994 /* Features */
3995 memcpy(btrc_item_player->features, avrc_item_player->features, BTRC_FEATURE_BIT_MASK_SIZE);
3996
3997 memset(btrc_item_player->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
3998 memcpy(btrc_item_player->name, avrc_item_player->name.p_str, avrc_item_player->name.str_len);
3999 }
4000
4001 /***************************************************************************
4002 *
4003 * Function handle_change_path_response
4004 *
4005 * Description handles the the change path response, calls
4006 * HAL callback to send the updated folder
4007 * Returns None
4008 *
4009 **************************************************************************/
handle_change_path_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_CHG_PATH_RSP * p_rsp)4010 static void handle_change_path_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_CHG_PATH_RSP* p_rsp) {
4011 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4012
4013 if (p_dev == NULL) {
4014 log::error("Invalid rc handle");
4015 return;
4016 }
4017
4018 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4019 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->change_folder_path_cb, p_dev->rc_addr,
4020 p_rsp->num_items));
4021 } else {
4022 log::error("error in handle_change_path_response {}", p_rsp->status);
4023 }
4024 }
4025
4026 /***************************************************************************
4027 *
4028 * Function handle_set_browsed_player_response
4029 *
4030 * Description handles the the change path response, calls
4031 * HAL callback to send the updated folder
4032 * Returns None
4033 *
4034 **************************************************************************/
handle_set_browsed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_SET_BR_PLAYER_RSP * p_rsp)4035 static void handle_set_browsed_player_response(tBTA_AV_META_MSG* pmeta_msg,
4036 tAVRC_SET_BR_PLAYER_RSP* p_rsp) {
4037 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4038
4039 if (p_dev == NULL) {
4040 log::error("Invalid rc handle");
4041 return;
4042 }
4043
4044 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4045 do_in_jni_thread(base::BindOnce(bt_rc_ctrl_callbacks->set_browsed_player_cb, p_dev->rc_addr,
4046 p_rsp->num_items, p_rsp->folder_depth));
4047 } else {
4048 log::error("error {}", p_rsp->status);
4049 }
4050 }
4051
4052 /***************************************************************************
4053 *
4054 * Function clear_cmd_timeout
4055 *
4056 * Description helper function to stop the command timeout timer
4057 * Returns None
4058 *
4059 **************************************************************************/
clear_cmd_timeout(btif_rc_device_cb_t * p_dev,uint8_t label)4060 static void clear_cmd_timeout(btif_rc_device_cb_t* p_dev, uint8_t label) {
4061 rc_transaction_t* p_txn;
4062
4063 p_txn = get_transaction_by_lbl(p_dev, label);
4064 if (p_txn == NULL) {
4065 log::error("Error in transaction label lookup");
4066 return;
4067 }
4068
4069 if (p_txn->timer != NULL) {
4070 // Free also calls alarm_cancel() in its implementation
4071 alarm_free(p_txn->timer);
4072 }
4073 p_txn->timer = nullptr;
4074 }
4075
4076 /***************************************************************************
4077 *
4078 * Function handle_avk_rc_metamsg_rsp
4079 *
4080 * Description Handle RC metamessage response
4081 *
4082 * Returns void
4083 *
4084 **************************************************************************/
handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg)4085 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) {
4086 tAVRC_RESPONSE avrc_response = {0};
4087 uint8_t scratch_buf[512] = {0}; // this variable is unused
4088 uint16_t buf_len;
4089 tAVRC_STS status;
4090 btif_rc_device_cb_t* p_dev = NULL;
4091
4092 log::verbose("opcode: {} rsp_code: {}", pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4093
4094 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4095 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
4096 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) && (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) &&
4097 (pmeta_msg->code <= AVRC_RSP_INTERIM)) {
4098 log::verbose("parse status {} pdu = {} rsp_status = {}", status, avrc_response.pdu,
4099 pmeta_msg->p_msg->vendor.hdr.ctype);
4100
4101 switch (avrc_response.pdu) {
4102 case AVRC_PDU_REGISTER_NOTIFICATION:
4103 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
4104 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
4105 /* Don't free the transaction Id */
4106 clear_cmd_timeout(p_dev, pmeta_msg->label);
4107 return;
4108 }
4109 break;
4110
4111 case AVRC_PDU_GET_CAPABILITIES:
4112 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
4113 break;
4114
4115 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
4116 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
4117 break;
4118
4119 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
4120 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
4121 break;
4122
4123 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
4124 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
4125 break;
4126
4127 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
4128 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
4129 break;
4130
4131 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
4132 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
4133 break;
4134
4135 case AVRC_PDU_SET_PLAYER_APP_VALUE:
4136 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
4137 break;
4138
4139 case AVRC_PDU_GET_ELEMENT_ATTR:
4140 handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
4141 break;
4142
4143 case AVRC_PDU_GET_PLAY_STATUS:
4144 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
4145 break;
4146
4147 case AVRC_PDU_SET_ADDRESSED_PLAYER:
4148 handle_set_addressed_player_response(pmeta_msg, &avrc_response.rsp);
4149 break;
4150 }
4151 } else if (AVRC_OP_BROWSE == pmeta_msg->p_msg->hdr.opcode) {
4152 log::verbose("AVRC_OP_BROWSE pdu {}", avrc_response.pdu);
4153 /* check what kind of command it is for browsing */
4154 switch (avrc_response.pdu) {
4155 case AVRC_PDU_GET_FOLDER_ITEMS:
4156 handle_get_folder_items_response(pmeta_msg, &avrc_response.get_items);
4157 break;
4158 case AVRC_PDU_CHANGE_PATH:
4159 handle_change_path_response(pmeta_msg, &avrc_response.chg_path);
4160 break;
4161 case AVRC_PDU_SET_BROWSED_PLAYER:
4162 handle_set_browsed_player_response(pmeta_msg, &avrc_response.br_player);
4163 break;
4164 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
4165 handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
4166 break;
4167 default:
4168 log::error("cannot handle browse pdu {}", pmeta_msg->p_msg->hdr.opcode);
4169 }
4170 } else {
4171 log::verbose("Invalid Vendor Command code: {} len: {}. Not processing it.", pmeta_msg->code,
4172 pmeta_msg->len);
4173 return;
4174 }
4175 log::verbose("release transaction {}", pmeta_msg->label);
4176 release_transaction(p_dev, pmeta_msg->label);
4177 }
4178
4179 /***************************************************************************
4180 *
4181 * Function handle_avk_rc_metamsg_cmd
4182 *
4183 * Description Handle RC metamessage response
4184 *
4185 * Returns void
4186 *
4187 **************************************************************************/
handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)4188 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
4189 tAVRC_COMMAND avrc_cmd = {0};
4190 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4191 btif_rc_device_cb_t* p_dev = NULL;
4192
4193 log::verbose("opcode: {} rsp_code: {}", pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4194 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
4195 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) && (pmeta_msg->code <= AVRC_CMD_GEN_INQ)) {
4196 log::verbose("Received vendor command.code {}, PDU {} label {}", pmeta_msg->code, avrc_cmd.pdu,
4197 pmeta_msg->label);
4198
4199 if (status != AVRC_STS_NO_ERROR) {
4200 /* return error */
4201 log::warn("Error in parsing received metamsg command. status: 0x{:02x}", status);
4202 if (true == btif_av_both_enable()) {
4203 if (AVRC_PDU_GET_CAPABILITIES == avrc_cmd.pdu ||
4204 AVRC_PDU_GET_ELEMENT_ATTR == avrc_cmd.pdu || AVRC_PDU_GET_PLAY_STATUS == avrc_cmd.pdu ||
4205 AVRC_PDU_GET_FOLDER_ITEMS == avrc_cmd.pdu ||
4206 AVRC_PDU_GET_ITEM_ATTRIBUTES == avrc_cmd.pdu) {
4207 return;
4208 }
4209 }
4210 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status,
4211 pmeta_msg->p_msg->hdr.opcode);
4212 } else {
4213 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4214 if (p_dev == NULL) {
4215 log::error("avk rc meta msg cmd for Invalid rc handle");
4216 return;
4217 }
4218
4219 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
4220 uint8_t event_id = avrc_cmd.reg_notif.event_id;
4221 log::verbose("Register notification event_id: {}", dump_rc_notification_event_id(event_id));
4222 } else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) {
4223 log::verbose("Abs Volume Cmd Recvd");
4224 }
4225
4226 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label, p_dev);
4227 }
4228 } else {
4229 log::verbose("Invalid Vendor Command code: {} len: {}. Not processing it.", pmeta_msg->code,
4230 pmeta_msg->len);
4231 return;
4232 }
4233 }
4234
4235 /***************************************************************************
4236 *
4237 * Function cleanup
4238 *
4239 * Description Closes the AVRC interface
4240 *
4241 * Returns void
4242 *
4243 **************************************************************************/
cleanup()4244 static void cleanup() {
4245 log::verbose("");
4246 if (bt_rc_callbacks) {
4247 bt_rc_callbacks = NULL;
4248 }
4249
4250 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4251 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4252 memset(&btif_rc_cb.rc_multi_cb[idx], 0, sizeof(btif_rc_cb.rc_multi_cb[idx]));
4253 }
4254
4255 log::verbose("completed");
4256 }
4257
4258 /***************************************************************************
4259 *
4260 * Function cleanup_ctrl
4261 *
4262 * Description Closes the AVRC Controller interface
4263 *
4264 * Returns void
4265 *
4266 **************************************************************************/
cleanup_ctrl()4267 static void cleanup_ctrl() {
4268 log::verbose("");
4269
4270 if (bt_rc_ctrl_callbacks) {
4271 bt_rc_ctrl_callbacks = NULL;
4272 }
4273
4274 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4275 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4276 memset(&btif_rc_cb.rc_multi_cb[idx], 0, sizeof(btif_rc_cb.rc_multi_cb[idx]));
4277 }
4278
4279 memset(&btif_rc_cb.rc_multi_cb, 0, sizeof(btif_rc_cb.rc_multi_cb));
4280 log::verbose("completed");
4281 }
4282
4283 /***************************************************************************
4284 *
4285 * Function getcapabilities_cmd
4286 *
4287 * Description GetCapabilties from Remote(Company_ID, Events_Supported)
4288 *
4289 * Returns void
4290 *
4291 **************************************************************************/
getcapabilities_cmd(uint8_t cap_id,btif_rc_device_cb_t * p_dev)4292 static bt_status_t getcapabilities_cmd(uint8_t cap_id, btif_rc_device_cb_t* p_dev) {
4293 log::verbose("cap_id: {}", cap_id);
4294 CHECK_RC_CONNECTED(p_dev);
4295
4296 tAVRC_COMMAND avrc_cmd = {0};
4297 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
4298 avrc_cmd.get_caps.capability_id = cap_id;
4299 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
4300 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
4301
4302 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4303 }
4304
4305 /***************************************************************************
4306 *
4307 * Function list_player_app_setting_attrib_cmd
4308 *
4309 * Description Get supported List Player Attributes
4310 *
4311 * Returns void
4312 *
4313 **************************************************************************/
list_player_app_setting_attrib_cmd(btif_rc_device_cb_t * p_dev)4314 static bt_status_t list_player_app_setting_attrib_cmd(btif_rc_device_cb_t* p_dev) {
4315 log::verbose("");
4316 CHECK_RC_CONNECTED(p_dev);
4317
4318 tAVRC_COMMAND avrc_cmd = {0};
4319 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
4320 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
4321 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
4322
4323 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4324 }
4325
4326 /***************************************************************************
4327 *
4328 * Function list_player_app_setting_value_cmd
4329 *
4330 * Description Get values of supported Player Attributes
4331 *
4332 * Returns void
4333 *
4334 **************************************************************************/
list_player_app_setting_value_cmd(uint8_t attrib_id,btif_rc_device_cb_t * p_dev)4335 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id,
4336 btif_rc_device_cb_t* p_dev) {
4337 log::verbose("attrib_id: {}", attrib_id);
4338 CHECK_RC_CONNECTED(p_dev);
4339
4340 tAVRC_COMMAND avrc_cmd = {0};
4341 avrc_cmd.list_app_values.attr_id = attrib_id;
4342 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
4343 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
4344 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
4345
4346 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4347 }
4348
4349 /***************************************************************************
4350 *
4351 * Function get_player_app_setting_cmd
4352 *
4353 * Description Get current values of Player Attributes
4354 *
4355 * Returns void
4356 *
4357 **************************************************************************/
get_player_app_setting_cmd(uint8_t num_attrib,uint8_t * attrib_ids,btif_rc_device_cb_t * p_dev)4358 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids,
4359 btif_rc_device_cb_t* p_dev) {
4360 log::verbose("num_attrib: {}", num_attrib);
4361 CHECK_RC_CONNECTED(p_dev);
4362
4363 tAVRC_COMMAND avrc_cmd = {0};
4364 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
4365 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
4366 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
4367 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
4368
4369 for (int count = 0; count < num_attrib; count++) {
4370 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
4371 }
4372
4373 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4374 }
4375
4376 /***************************************************************************
4377 *
4378 * Function get_current_metadata_cmd
4379 *
4380 * Description Fetch the current track metadata for the device
4381 *
4382 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4383 * BT_STATUS_FAIL.
4384 *
4385 **************************************************************************/
get_current_metadata_cmd(const RawAddress & bd_addr)4386 static bt_status_t get_current_metadata_cmd(const RawAddress& bd_addr) {
4387 log::verbose("");
4388 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4389 if (p_dev == NULL) {
4390 log::error("p_dev NULL");
4391 return BT_STATUS_DEVICE_NOT_FOUND;
4392 }
4393 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
4394 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
4395 return get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
4396 }
4397
4398 /***************************************************************************
4399 *
4400 * Function get_playback_state_cmd
4401 *
4402 * Description Fetch the current playback state for the device
4403 *
4404 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4405 * BT_STATUS_FAIL.
4406 *
4407 **************************************************************************/
get_playback_state_cmd(const RawAddress & bd_addr)4408 static bt_status_t get_playback_state_cmd(const RawAddress& bd_addr) {
4409 log::verbose("");
4410 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4411 return get_play_status_cmd(p_dev);
4412 }
4413
4414 /***************************************************************************
4415 *
4416 * Function get_now_playing_list_cmd
4417 *
4418 * Description Fetch the now playing list
4419 *
4420 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4421 * end_item: Last item to fetch (0xffffffff to fetch until end)
4422 *
4423 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4424 * BT_STATUS_FAIL.
4425 *
4426 **************************************************************************/
get_now_playing_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4427 static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr, uint32_t start_item,
4428 uint32_t end_item) {
4429 log::verbose("start, end: ({}, {})", start_item, end_item);
4430 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item, end_item);
4431 }
4432
4433 /***************************************************************************
4434 *
4435 * Function get_item_attribute_cmd
4436 *
4437 * Description Fetch the item attributes for a given uid.
4438 *
4439 * Parameters uid: Track UID you want attributes for
4440 * scope: Constant representing which scope you're querying
4441 * (i.e AVRC_SCOPE_FILE_SYSTEM)
4442 * p_dev: Device control block
4443 *
4444 * Returns BT_STATUS_SUCCESS if command is issued successfully
4445 * otherwise BT_STATUS_FAIL
4446 *
4447 **************************************************************************/
get_item_attribute_cmd(uint64_t uid,int scope,uint8_t,const uint32_t *,btif_rc_device_cb_t * p_dev)4448 static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope, uint8_t /*num_attribute*/,
4449 const uint32_t* /*p_attr_ids*/,
4450 btif_rc_device_cb_t* p_dev) {
4451 tAVRC_COMMAND avrc_cmd = {0};
4452 avrc_cmd.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
4453 avrc_cmd.get_attrs.scope = scope;
4454 memcpy(avrc_cmd.get_attrs.uid, &uid, 8);
4455 avrc_cmd.get_attrs.uid_counter = 0;
4456 avrc_cmd.get_attrs.attr_count = 0;
4457
4458 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4459 }
4460
4461 /***************************************************************************
4462 *
4463 * Function get_folder_list_cmd
4464 *
4465 * Description Fetch the currently selected folder list
4466 *
4467 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4468 * end_item: Last item to fetch (0xffffffff to fetch until end)
4469 *
4470 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4471 * BT_STATUS_FAIL.
4472 *
4473 **************************************************************************/
get_folder_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4474 static bt_status_t get_folder_list_cmd(const RawAddress& bd_addr, uint32_t start_item,
4475 uint32_t end_item) {
4476 log::verbose("start, end: ({}, {})", start_item, end_item);
4477 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item, end_item);
4478 }
4479
4480 /***************************************************************************
4481 *
4482 * Function get_player_list_cmd
4483 *
4484 * Description Fetch the player list
4485 *
4486 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4487 * end_item: Last item to fetch (0xffffffff to fetch until end)
4488 *
4489 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4490 * BT_STATUS_FAIL.
4491 *
4492 **************************************************************************/
get_player_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4493 static bt_status_t get_player_list_cmd(const RawAddress& bd_addr, uint32_t start_item,
4494 uint32_t end_item) {
4495 log::verbose("start, end: ({}, {})", start_item, end_item);
4496 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item, end_item);
4497 }
4498
4499 /***************************************************************************
4500 *
4501 * Function change_folder_path_cmd
4502 *
4503 * Description Change the folder.
4504 *
4505 * Paramters direction: Direction (Up/Down) to change folder
4506 * uid: The UID of folder to move to
4507 * start_item: First item to fetch (0 to fetch from beganning)
4508 * end_item: Last item to fetch (0xffffffff to fetch until end)
4509 *
4510 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4511 * BT_STATUS_FAIL.
4512 *
4513 **************************************************************************/
change_folder_path_cmd(const RawAddress & bd_addr,uint8_t direction,uint8_t * uid)4514 static bt_status_t change_folder_path_cmd(const RawAddress& bd_addr, uint8_t direction,
4515 uint8_t* uid) {
4516 log::verbose("direction {}", direction);
4517 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4518 CHECK_RC_CONNECTED(p_dev);
4519 CHECK_BR_CONNECTED(p_dev);
4520
4521 tAVRC_COMMAND avrc_cmd = {0};
4522
4523 avrc_cmd.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
4524 avrc_cmd.chg_path.status = AVRC_STS_NO_ERROR;
4525 // TODO(sanketa): Improve for database aware clients.
4526 avrc_cmd.chg_path.uid_counter = 0;
4527 avrc_cmd.chg_path.direction = direction;
4528
4529 memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t));
4530 memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t));
4531
4532 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4533 }
4534
4535 /***************************************************************************
4536 *
4537 * Function set_browsed_player_cmd
4538 *
4539 * Description Change the browsed player.
4540 *
4541 * Paramters id: The UID of player to move to
4542 *
4543 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4544 * BT_STATUS_FAIL.
4545 *
4546 **************************************************************************/
set_browsed_player_cmd(const RawAddress & bd_addr,uint16_t id)4547 static bt_status_t set_browsed_player_cmd(const RawAddress& bd_addr, uint16_t id) {
4548 log::verbose("id {}", id);
4549 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4550 CHECK_RC_CONNECTED(p_dev);
4551 CHECK_BR_CONNECTED(p_dev);
4552
4553 tAVRC_COMMAND avrc_cmd = {0};
4554 avrc_cmd.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
4555 avrc_cmd.br_player.status = AVRC_STS_NO_ERROR;
4556 // TODO(sanketa): Improve for database aware clients.
4557 avrc_cmd.br_player.player_id = id;
4558
4559 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4560 }
4561
4562 /***************************************************************************
4563 **
4564 ** Function set_addressed_player_cmd
4565 **
4566 ** Description Change the addressed player.
4567 **
4568 ** Paramters id: The UID of player to move to
4569 **
4570 ** Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4571 ** BT_STATUS_FAIL.
4572 **
4573 ***************************************************************************/
set_addressed_player_cmd(const RawAddress & bd_addr,uint16_t id)4574 static bt_status_t set_addressed_player_cmd(const RawAddress& bd_addr, uint16_t id) {
4575 log::verbose("id {}", id);
4576
4577 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4578 CHECK_RC_CONNECTED(p_dev);
4579 CHECK_BR_CONNECTED(p_dev);
4580
4581 tAVRC_COMMAND avrc_cmd = {0};
4582 avrc_cmd.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
4583 avrc_cmd.addr_player.status = AVRC_STS_NO_ERROR;
4584 // TODO(sanketa): Improve for database aware clients.
4585 avrc_cmd.addr_player.player_id = id;
4586
4587 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4588 }
4589
4590 /***************************************************************************
4591 *
4592 * Function get_folder_items_cmd
4593 *
4594 * Description Helper function to browse the content hierarchy of the
4595 * TG device.
4596 *
4597 * Paramters scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable
4598 * content
4599 * start_item: First item to fetch (0 to fetch from beganning)
4600 * end_item: Last item to fetch (0xffff to fetch until end)
4601 *
4602 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4603 * BT_STATUS_FAIL.
4604 *
4605 **************************************************************************/
get_folder_items_cmd(const RawAddress & bd_addr,uint8_t scope,uint32_t start_item,uint32_t end_item)4606 static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr, uint8_t scope,
4607 uint32_t start_item, uint32_t end_item) {
4608 /* Check that both avrcp and browse channel are connected. */
4609 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4610 log::verbose("");
4611 CHECK_RC_CONNECTED(p_dev);
4612 CHECK_BR_CONNECTED(p_dev);
4613
4614 tAVRC_COMMAND avrc_cmd = {0};
4615
4616 /* Set the layer specific to point to browse although this should really
4617 * be done by lower layers and looking at the PDU
4618 */
4619 avrc_cmd.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
4620 avrc_cmd.get_items.status = AVRC_STS_NO_ERROR;
4621 avrc_cmd.get_items.scope = scope;
4622 avrc_cmd.get_items.start_item = start_item;
4623 avrc_cmd.get_items.end_item = end_item;
4624 avrc_cmd.get_items.attr_count = 0; /* p_attr_list does not matter hence */
4625
4626 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4627 }
4628
4629 /***************************************************************************
4630 *
4631 * Function change_player_app_setting
4632 *
4633 * Description Set current values of Player Attributes
4634 *
4635 * Returns void
4636 *
4637 **************************************************************************/
change_player_app_setting(const RawAddress & bd_addr,uint8_t num_attrib,uint8_t * attrib_ids,uint8_t * attrib_vals)4638 static bt_status_t change_player_app_setting(const RawAddress& bd_addr, uint8_t num_attrib,
4639 uint8_t* attrib_ids, uint8_t* attrib_vals) {
4640 log::verbose("num_attrib: {}", num_attrib);
4641 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4642 CHECK_RC_CONNECTED(p_dev);
4643
4644 tAVRC_COMMAND avrc_cmd = {0};
4645 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
4646 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
4647 avrc_cmd.set_app_val.num_val = num_attrib;
4648 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
4649 avrc_cmd.set_app_val.p_vals =
4650 (tAVRC_APP_SETTING*)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
4651 for (int count = 0; count < num_attrib; count++) {
4652 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
4653 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
4654 }
4655
4656 bt_status_t st = build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4657 osi_free_and_reset((void**)&avrc_cmd.set_app_val.p_vals);
4658 return st;
4659 }
4660
4661 /***************************************************************************
4662 *
4663 * Function play_item_cmd
4664 *
4665 * Description Play the item specified by UID & scope
4666 *
4667 * Returns void
4668 *
4669 **************************************************************************/
play_item_cmd(const RawAddress & bd_addr,uint8_t scope,uint8_t * uid,uint16_t uid_counter)4670 static bt_status_t play_item_cmd(const RawAddress& bd_addr, uint8_t scope, uint8_t* uid,
4671 uint16_t uid_counter) {
4672 log::verbose("scope {} uid_counter {}", scope, uid_counter);
4673 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4674 CHECK_RC_CONNECTED(p_dev);
4675 CHECK_BR_CONNECTED(p_dev);
4676
4677 tAVRC_COMMAND avrc_cmd = {0};
4678 avrc_cmd.pdu = AVRC_PDU_PLAY_ITEM;
4679 avrc_cmd.play_item.opcode = AVRC_OP_VENDOR;
4680 avrc_cmd.play_item.status = AVRC_STS_NO_ERROR;
4681 avrc_cmd.play_item.scope = scope;
4682 memcpy(avrc_cmd.play_item.uid, uid, AVRC_UID_SIZE);
4683 avrc_cmd.play_item.uid_counter = uid_counter;
4684
4685 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4686 }
4687
4688 /***************************************************************************
4689 *
4690 * Function get_player_app_setting_attr_text_cmd
4691 *
4692 * Description Get text description for app attribute
4693 *
4694 * Returns void
4695 *
4696 **************************************************************************/
get_player_app_setting_attr_text_cmd(uint8_t * attrs,uint8_t num_attrs,btif_rc_device_cb_t * p_dev)4697 static bt_status_t get_player_app_setting_attr_text_cmd(uint8_t* attrs, uint8_t num_attrs,
4698 btif_rc_device_cb_t* p_dev) {
4699 log::verbose("num attrs: {}", num_attrs);
4700 CHECK_RC_CONNECTED(p_dev);
4701
4702 tAVRC_COMMAND avrc_cmd = {0};
4703 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
4704 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
4705 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
4706
4707 for (int count = 0; count < num_attrs; count++) {
4708 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
4709 }
4710
4711 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4712 }
4713
4714 /***************************************************************************
4715 *
4716 * Function get_player_app_setting_val_text_cmd
4717 *
4718 * Description Get text description for app attribute values
4719 *
4720 * Returns void
4721 *
4722 **************************************************************************/
get_player_app_setting_value_text_cmd(uint8_t * vals,uint8_t num_vals,btif_rc_device_cb_t * p_dev)4723 static bt_status_t get_player_app_setting_value_text_cmd(uint8_t* vals, uint8_t num_vals,
4724 btif_rc_device_cb_t* p_dev) {
4725 log::verbose("num_vals: {}", num_vals);
4726 CHECK_RC_CONNECTED(p_dev);
4727
4728 tAVRC_COMMAND avrc_cmd = {0};
4729 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
4730 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
4731 avrc_cmd.get_app_val_txt.num_val = num_vals;
4732
4733 for (int count = 0; count < num_vals; count++) {
4734 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
4735 }
4736
4737 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4738 }
4739
4740 /***************************************************************************
4741 *
4742 * Function register_notification_cmd
4743 *
4744 * Description Send Command to register for a Notification ID
4745 *
4746 * Returns void
4747 *
4748 **************************************************************************/
register_notification_cmd(uint8_t event_id,uint32_t event_value,btif_rc_device_cb_t * p_dev)4749 static bt_status_t register_notification_cmd(uint8_t event_id, uint32_t event_value,
4750 btif_rc_device_cb_t* p_dev) {
4751 log::verbose("event_id: {} event_value {}", event_id, event_value);
4752 CHECK_RC_CONNECTED(p_dev);
4753
4754 tAVRC_COMMAND avrc_cmd = {0};
4755 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
4756 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
4757 avrc_cmd.reg_notif.event_id = event_id;
4758 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
4759 avrc_cmd.reg_notif.param = event_value;
4760
4761 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_NOTIF, p_dev);
4762 }
4763
4764 /***************************************************************************
4765 *
4766 * Function get_metadata_attribute_cmd
4767 *
4768 * Description Get metadata attributes for attributeIds. This function
4769 * will make the right determination of whether to use the
4770 * control or browsing channel for the request
4771 *
4772 * Returns BT_STATUS_SUCCESS if the command is successfully issued
4773 * otherwise BT_STATUS_FAIL
4774 *
4775 **************************************************************************/
get_metadata_attribute_cmd(uint8_t num_attribute,const uint32_t * p_attr_ids,btif_rc_device_cb_t * p_dev)4776 static bt_status_t get_metadata_attribute_cmd(uint8_t num_attribute, const uint32_t* p_attr_ids,
4777 btif_rc_device_cb_t* p_dev) {
4778 log::verbose("num_attribute: {} attribute_id: {}", num_attribute, p_attr_ids[0]);
4779
4780 // If browsing is connected then send the command out that channel
4781 if (p_dev->br_connected) {
4782 return get_item_attribute_cmd(p_dev->rc_playing_uid, AVRC_SCOPE_NOW_PLAYING, num_attribute,
4783 p_attr_ids, p_dev);
4784 }
4785
4786 // Otherwise, default to the control channel
4787 return get_element_attribute_cmd(num_attribute, p_attr_ids, p_dev);
4788 }
4789
4790 /***************************************************************************
4791 *
4792 * Function get_element_attribute_cmd
4793 *
4794 * Description Get Element Attribute for attributeIds
4795 *
4796 * Returns void
4797 *
4798 **************************************************************************/
get_element_attribute_cmd(uint8_t num_attribute,const uint32_t * p_attr_ids,btif_rc_device_cb_t * p_dev)4799 static bt_status_t get_element_attribute_cmd(uint8_t num_attribute, const uint32_t* p_attr_ids,
4800 btif_rc_device_cb_t* p_dev) {
4801 log::verbose("num_attribute: {} attribute_id: {}", num_attribute, p_attr_ids[0]);
4802 CHECK_RC_CONNECTED(p_dev);
4803 tAVRC_COMMAND avrc_cmd = {0};
4804 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
4805 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
4806 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
4807 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
4808 for (int count = 0; count < num_attribute; count++) {
4809 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
4810 }
4811
4812 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4813 }
4814
4815 /***************************************************************************
4816 *
4817 * Function get_play_status_cmd
4818 *
4819 * Description Get Playing Status of a Device
4820 *
4821 * Returns bt_status_t
4822 *
4823 **************************************************************************/
get_play_status_cmd(btif_rc_device_cb_t * p_dev)4824 static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev) {
4825 log::verbose("");
4826 CHECK_RC_CONNECTED(p_dev);
4827
4828 tAVRC_COMMAND avrc_cmd = {0};
4829 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
4830 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
4831 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
4832
4833 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4834 }
4835
4836 /***************************************************************************
4837 *
4838 * Function set_volume_rsp
4839 *
4840 * Description Rsp for SetAbsoluteVolume Command
4841 *
4842 * Returns void
4843 *
4844 **************************************************************************/
set_volume_rsp(const RawAddress & bd_addr,uint8_t abs_vol,uint8_t label)4845 static bt_status_t set_volume_rsp(const RawAddress& bd_addr, uint8_t abs_vol, uint8_t label) {
4846 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4847 tAVRC_RESPONSE avrc_rsp;
4848 BT_HDR* p_msg = NULL;
4849 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4850
4851 CHECK_RC_CONNECTED(p_dev);
4852
4853 log::verbose("abs_vol: {}", abs_vol);
4854
4855 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
4856 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
4857 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
4858 avrc_rsp.volume.volume = abs_vol;
4859 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
4860 if (status == AVRC_STS_NO_ERROR) {
4861 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
4862 log::verbose("msgreq being sent out with label: {}", p_dev->rc_vol_label);
4863 if (p_msg != NULL) {
4864 BTA_AvVendorRsp(p_dev->rc_handle, label, AVRC_RSP_ACCEPT, data_start, p_msg->len, 0);
4865 status = BT_STATUS_SUCCESS;
4866 }
4867 } else {
4868 log::error("failed to build command. status: 0x{:02x}", status);
4869 }
4870 osi_free(p_msg);
4871 return (bt_status_t)status;
4872 }
4873
4874 /***************************************************************************
4875 *
4876 * Function send_register_abs_vol_rsp
4877 *
4878 * Description Rsp for Notification of Absolute Volume
4879 *
4880 * Returns void
4881 *
4882 **************************************************************************/
volume_change_notification_rsp(const RawAddress & bd_addr,btrc_notification_type_t rsp_type,uint8_t abs_vol,uint8_t label)4883 static bt_status_t volume_change_notification_rsp(const RawAddress& bd_addr,
4884 btrc_notification_type_t rsp_type,
4885 uint8_t abs_vol, uint8_t label) {
4886 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4887 tAVRC_RESPONSE avrc_rsp;
4888 BT_HDR* p_msg = NULL;
4889 log::verbose("rsp_type: {} abs_vol: {}", rsp_type, abs_vol);
4890
4891 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4892
4893 CHECK_RC_CONNECTED(p_dev);
4894
4895 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
4896 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
4897 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
4898 avrc_rsp.reg_notif.param.volume = abs_vol;
4899 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
4900
4901 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
4902 if (status == AVRC_STS_NO_ERROR) {
4903 log::verbose("msgreq being sent out with label: {}", label);
4904 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
4905 BTA_AvVendorRsp(
4906 p_dev->rc_handle, label,
4907 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
4908 data_start, p_msg->len, 0);
4909 status = BT_STATUS_SUCCESS;
4910 } else {
4911 log::error("failed to build command. status: 0x{:02x}", status);
4912 }
4913 osi_free(p_msg);
4914
4915 return (bt_status_t)status;
4916 }
4917
4918 /***************************************************************************
4919 *
4920 * Function send_groupnavigation_cmd
4921 *
4922 * Description Send Pass-Through command
4923 *
4924 * Returns void
4925 *
4926 **************************************************************************/
send_groupnavigation_cmd(const RawAddress & bd_addr,uint8_t key_code,uint8_t key_state)4927 static bt_status_t send_groupnavigation_cmd(const RawAddress& bd_addr, uint8_t key_code,
4928 uint8_t key_state) {
4929 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4930 rc_transaction_t* p_transaction = NULL;
4931 log::verbose("key-code: {}, key-state: {}", key_code, key_state);
4932 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4933
4934 CHECK_RC_CONNECTED(p_dev);
4935
4936 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
4937 rc_transaction_context_t context = {
4938 .rc_addr = p_dev->rc_addr,
4939 .label = MAX_LABEL,
4940 .opcode = AVRC_OP_PASS_THRU,
4941 .command = {.passthru = {AVRC_ID_VENDOR, key_state, key_code}}};
4942 bt_status_t tran_status = get_transaction(p_dev, context, &p_transaction);
4943 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
4944 uint8_t buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
4945 uint8_t* start = buffer;
4946 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
4947 *(start)++ = 0;
4948 UINT8_TO_BE_STREAM(start, key_code);
4949 BTA_AvRemoteVendorUniqueCmd(p_dev->rc_handle, p_transaction->label, (tBTA_AV_STATE)key_state,
4950 buffer, AVRC_PASS_THRU_GROUP_LEN);
4951 status = BT_STATUS_SUCCESS;
4952 start_transaction_timer(p_dev, p_transaction->label, BTIF_RC_TIMEOUT_MS);
4953 log::verbose("Send command, key-code={}, key-state={}, label={}", key_code, key_state,
4954 p_transaction->label);
4955 } else {
4956 status = BT_STATUS_FAIL;
4957 log::error("failed to get label, key-code={}, key-state={}, status={}", key_code, key_state,
4958 tran_status);
4959 }
4960 } else {
4961 status = BT_STATUS_UNSUPPORTED;
4962 log::verbose("feature not supported");
4963 }
4964 return (bt_status_t)status;
4965 }
4966
4967 /***************************************************************************
4968 *
4969 * Function send_passthrough_cmd
4970 *
4971 * Description Send Pass-Through command
4972 *
4973 * Returns void
4974 *
4975 **************************************************************************/
send_passthrough_cmd(const RawAddress & bd_addr,uint8_t key_code,uint8_t key_state)4976 static bt_status_t send_passthrough_cmd(const RawAddress& bd_addr, uint8_t key_code,
4977 uint8_t key_state) {
4978 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4979 btif_rc_device_cb_t* p_dev = NULL;
4980 log::error("calling btif_rc_get_device_by_bda");
4981 p_dev = btif_rc_get_device_by_bda(bd_addr);
4982
4983 CHECK_RC_CONNECTED(p_dev);
4984
4985 rc_transaction_t* p_transaction = NULL;
4986 log::verbose("key-code: {}, key-state: {}", key_code, key_state);
4987 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
4988 rc_transaction_context_t context = {
4989 .rc_addr = p_dev->rc_addr,
4990 .label = MAX_LABEL,
4991 .opcode = AVRC_OP_PASS_THRU,
4992 .command = {.passthru = {AVRC_ID_VENDOR, key_state, key_code}}};
4993 bt_status_t tran_status = get_transaction(p_dev, context, &p_transaction);
4994 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) {
4995 BTA_AvRemoteCmd(p_dev->rc_handle, p_transaction->label, (tBTA_AV_RC)key_code,
4996 (tBTA_AV_STATE)key_state);
4997 status = BT_STATUS_SUCCESS;
4998 start_transaction_timer(p_dev, p_transaction->label, BTIF_RC_TIMEOUT_MS);
4999 log::verbose("Send command, key-code={}, key-state={}, label={}", key_code, key_state,
5000 p_transaction->label);
5001 } else {
5002 status = BT_STATUS_FAIL;
5003 log::error("failed to get label, key-code={}, key-state={}, status={}", key_code, key_state,
5004 tran_status);
5005 }
5006 } else {
5007 status = BT_STATUS_UNSUPPORTED;
5008 log::verbose("feature not supported");
5009 }
5010 return (bt_status_t)status;
5011 }
5012
5013 static const btrc_interface_t bt_rc_interface = {
5014 sizeof(bt_rc_interface),
5015 init,
5016 get_play_status_rsp,
5017 NULL, /* list_player_app_attr_rsp */
5018 NULL, /* list_player_app_value_rsp */
5019 NULL, /* get_player_app_value_rsp */
5020 NULL, /* get_player_app_attr_text_rsp */
5021 NULL, /* get_player_app_value_text_rsp */
5022 get_element_attr_rsp,
5023 NULL, /* set_player_app_value_rsp */
5024 register_notification_rsp,
5025 set_volume,
5026 set_addressed_player_rsp,
5027 set_browsed_player_rsp,
5028 get_folder_items_list_rsp,
5029 change_path_rsp,
5030 get_item_attr_rsp,
5031 play_item_rsp,
5032 get_total_num_of_items_rsp,
5033 search_rsp,
5034 add_to_now_playing_rsp,
5035 cleanup,
5036 };
5037
5038 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
5039 sizeof(bt_rc_ctrl_interface),
5040 init_ctrl,
5041 send_passthrough_cmd,
5042 send_groupnavigation_cmd,
5043 change_player_app_setting,
5044 play_item_cmd,
5045 get_current_metadata_cmd,
5046 get_playback_state_cmd,
5047 get_now_playing_list_cmd,
5048 get_folder_list_cmd,
5049 get_player_list_cmd,
5050 change_folder_path_cmd,
5051 set_browsed_player_cmd,
5052 set_addressed_player_cmd,
5053 set_volume_rsp,
5054 volume_change_notification_rsp,
5055 cleanup_ctrl,
5056 };
5057
5058 /*******************************************************************************
5059 *
5060 * Function btif_rc_get_interface
5061 *
5062 * Description Get the AVRCP Target callback interface
5063 *
5064 * Returns btrc_interface_t
5065 *
5066 ******************************************************************************/
btif_rc_get_interface(void)5067 const btrc_interface_t* btif_rc_get_interface(void) { return &bt_rc_interface; }
5068
5069 /*******************************************************************************
5070 *
5071 * Function btif_rc_ctrl_get_interface
5072 *
5073 * Description Get the AVRCP Controller callback interface
5074 *
5075 * Returns btrc_ctrl_interface_t
5076 *
5077 ******************************************************************************/
btif_rc_ctrl_get_interface(void)5078 const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) { return &bt_rc_ctrl_interface; }
5079
5080 /*******************************************************************************
5081 * Function initialize_transaction
5082 *
5083 * Description Initializes fields of the transaction structure
5084 *
5085 * Returns void
5086 ******************************************************************************/
initialize_transaction(btif_rc_device_cb_t * p_dev,uint8_t lbl)5087 static void initialize_transaction(btif_rc_device_cb_t* p_dev, uint8_t lbl) {
5088 if (p_dev == nullptr) {
5089 return;
5090 }
5091 rc_transaction_set_t* transaction_set = &(p_dev->transaction_set);
5092 std::unique_lock<std::recursive_mutex> lock(transaction_set->label_lock);
5093 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5094 log::verbose("initialize transaction, dev={}, label={}", p_dev->rc_addr, lbl);
5095 if (alarm_is_scheduled(transaction_set->transaction[lbl].timer)) {
5096 log::warn("clearing pending timer event, dev={}, label={}", p_dev->rc_addr, lbl);
5097 clear_cmd_timeout(p_dev, lbl);
5098 }
5099 transaction_set->transaction[lbl] = {
5100 .in_use = false,
5101 .label = lbl,
5102 .context =
5103 {
5104 .rc_addr = RawAddress::kEmpty,
5105 .label = MAX_LABEL,
5106 .opcode = AVRC_OP_INVALID,
5107 .command = {},
5108 },
5109 .timer = nullptr,
5110 };
5111 }
5112 }
5113
5114 /*******************************************************************************
5115 *
5116 * Function init_all_transactions
5117 *
5118 * Description Initializes all transactions
5119 *
5120 * Returns void
5121 ******************************************************************************/
init_all_transactions(btif_rc_device_cb_t * p_dev)5122 void init_all_transactions(btif_rc_device_cb_t* p_dev) {
5123 if (p_dev == nullptr) {
5124 return;
5125 }
5126 for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; ++i) {
5127 initialize_transaction(p_dev, i);
5128 }
5129 }
5130
5131 /*******************************************************************************
5132 *
5133 * Function get_transaction_by_lbl
5134 *
5135 * Description Will return a transaction based on the label. If not inuse
5136 * will return an error.
5137 *
5138 * Returns bt_status_t
5139 ******************************************************************************/
get_transaction_by_lbl(btif_rc_device_cb_t * p_dev,uint8_t lbl)5140 rc_transaction_t* get_transaction_by_lbl(btif_rc_device_cb_t* p_dev, uint8_t lbl) {
5141 if (p_dev == nullptr) {
5142 return nullptr;
5143 }
5144
5145 rc_transaction_t* transaction = NULL;
5146 rc_transaction_set_t* transaction_set = &(p_dev->transaction_set);
5147 std::unique_lock<std::recursive_mutex> lock(transaction_set->label_lock);
5148
5149 /* Determine if this is a valid label */
5150 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5151 if (!transaction_set->transaction[lbl].in_use) {
5152 transaction = NULL;
5153 } else {
5154 transaction = &(transaction_set->transaction[lbl]);
5155 }
5156 }
5157 return transaction;
5158 }
5159
5160 /*******************************************************************************
5161 *
5162 * Function get_transaction
5163 *
5164 * Description Obtains the transaction details.
5165 *
5166 * Returns bt_status_t
5167 ******************************************************************************/
get_transaction(btif_rc_device_cb_t * p_dev,rc_transaction_context_t & context,rc_transaction_t ** ptransaction)5168 static bt_status_t get_transaction(btif_rc_device_cb_t* p_dev, rc_transaction_context_t& context,
5169 rc_transaction_t** ptransaction) {
5170 if (p_dev == NULL) {
5171 return BT_STATUS_PARM_INVALID;
5172 }
5173 rc_transaction_set_t* transaction_set = &(p_dev->transaction_set);
5174 std::unique_lock<std::recursive_mutex> lock(transaction_set->label_lock);
5175
5176 // Check for unused transactions in the device's transaction set
5177 for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; i++) {
5178 if (!transaction_set->transaction[i].in_use) {
5179 context.label = i;
5180 transaction_set->transaction[i].context = context;
5181 transaction_set->transaction[i].in_use = true;
5182 *ptransaction = &(transaction_set->transaction[i]);
5183 log::verbose("Assigned transaction, dev={}, transaction={}", p_dev->rc_addr,
5184 dump_transaction(*ptransaction));
5185 return BT_STATUS_SUCCESS;
5186 }
5187 }
5188 log::error("p_dev={}, failed to find free transaction", p_dev->rc_addr);
5189 return BT_STATUS_NOMEM;
5190 }
5191
5192 /*******************************************************************************
5193 *
5194 * Function start_transaction_timer
5195 *
5196 * Description Starts a timer to release the label in case we don't get a
5197 * response. Uses the central timeout handler, which will route
5198 * timeout events based on context opcode and pdu_id
5199 *
5200 * Returns void
5201 ******************************************************************************/
start_transaction_timer(btif_rc_device_cb_t * p_dev,uint8_t label,uint64_t timeout_ms)5202 static void start_transaction_timer(btif_rc_device_cb_t* p_dev, uint8_t label,
5203 uint64_t timeout_ms) {
5204 rc_transaction_t* transaction = get_transaction_by_lbl(p_dev, label);
5205 if (transaction == nullptr) {
5206 log::error("transaction is null");
5207 return;
5208 }
5209
5210 if (alarm_is_scheduled(transaction->timer)) {
5211 log::warn("Restarting timer that's already scheduled");
5212 }
5213
5214 std::stringstream ss;
5215 ss << "btif_rc." << p_dev->rc_addr.ToColonSepHexString() << "." << transaction->label;
5216 alarm_free(transaction->timer);
5217 transaction->timer = alarm_new(ss.str().c_str());
5218 alarm_set_on_mloop(transaction->timer, timeout_ms, btif_rc_transaction_timer_timeout,
5219 &transaction->context);
5220 }
5221
5222 /*******************************************************************************
5223 *
5224 * Function release_transaction
5225 *
5226 * Description Will release a transaction for reuse
5227 *
5228 * Returns bt_status_t
5229 ******************************************************************************/
release_transaction(btif_rc_device_cb_t * p_dev,uint8_t lbl)5230 void release_transaction(btif_rc_device_cb_t* p_dev, uint8_t lbl) {
5231 if (p_dev == nullptr) {
5232 log::warn("Failed to release transaction, dev=null, label={}", lbl);
5233 return;
5234 }
5235 rc_transaction_set_t* transaction_set = &(p_dev->transaction_set);
5236 std::unique_lock<std::recursive_mutex> lock(transaction_set->label_lock);
5237
5238 rc_transaction_t* transaction = get_transaction_by_lbl(p_dev, lbl);
5239
5240 /* If the transaction is in use... */
5241 if (transaction != NULL) {
5242 log::verbose("Released transaction, dev={}, label={}", p_dev->rc_addr, lbl);
5243 initialize_transaction(p_dev, lbl);
5244 } else {
5245 log::warn("Failed to release transaction, could not find dev={}, label={}", p_dev->rc_addr,
5246 lbl);
5247 }
5248 }
5249
5250 /*******************************************************************************
5251 *
5252 * Function dump_transaction
5253 *
5254 * Description Dump transactions info for debugging
5255 *
5256 * Returns String of transaction info
5257 ******************************************************************************/
dump_transaction(const rc_transaction_t * const transaction)5258 static std::string dump_transaction(const rc_transaction_t* const transaction) {
5259 std::stringstream ss;
5260
5261 ss << "label=" << (int)transaction->label;
5262 ss << " in_use=" << (transaction->in_use ? "true" : "false");
5263
5264 rc_transaction_context_t context = transaction->context;
5265 ss << " context=(";
5266 uint8_t opcode_id = context.opcode;
5267 ss << "opcode=" << dump_rc_opcode(opcode_id);
5268 switch (opcode_id) {
5269 case AVRC_OP_VENDOR:
5270 ss << " pdu_id=" << dump_rc_pdu(context.command.vendor.pdu_id);
5271 if (context.command.vendor.pdu_id == AVRC_PDU_REGISTER_NOTIFICATION) {
5272 ss << " event_id=" << dump_rc_notification_event_id(context.command.vendor.event_id);
5273 }
5274 break;
5275 case AVRC_OP_BROWSE:
5276 ss << " pdu_id=" << dump_rc_pdu(context.command.browse.pdu_id);
5277 break;
5278 case AVRC_OP_PASS_THRU:
5279 ss << " rc_id=" << context.command.passthru.rc_id;
5280 ss << " key_state=" << context.command.passthru.key_state;
5281 break;
5282 }
5283 ss << ")";
5284
5285 ss << " alarm=";
5286 alarm_t* alarm = transaction->timer;
5287 if (alarm != nullptr) {
5288 ss << "(set=" << alarm_is_scheduled(alarm) << " left=" << alarm_get_remaining_ms(alarm) << ")";
5289 } else {
5290 ss << "null";
5291 }
5292 return ss.str();
5293 }
5294
5295 /***************************************************************************
5296 *
5297 * Function vendor_cmd_timeout_handler
5298 *
5299 * Description vendor dependent command timeout handler
5300 * Returns None
5301 *
5302 **************************************************************************/
vendor_cmd_timeout_handler(btif_rc_device_cb_t * p_dev,uint8_t label,rc_vendor_context_t * p_context)5303 static void vendor_cmd_timeout_handler(btif_rc_device_cb_t* p_dev, uint8_t label,
5304 rc_vendor_context_t* p_context) {
5305 if (p_dev == NULL) {
5306 log::error("p_dev NULL");
5307 return;
5308 }
5309
5310 tAVRC_RESPONSE avrc_response = {0};
5311 tBTA_AV_META_MSG meta_msg = {.rc_handle = p_dev->rc_handle};
5312
5313 log::warn("timeout, addr={}, label={}, pdu_id={}, event_id={}", p_dev->rc_addr, label,
5314 dump_rc_pdu(p_context->pdu_id), dump_rc_notification_event_id(p_context->event_id));
5315
5316 switch (p_context->pdu_id) {
5317 case AVRC_PDU_REGISTER_NOTIFICATION:
5318 rc_notification_interim_timeout(p_dev, p_context->event_id);
5319 break;
5320
5321 case AVRC_PDU_GET_CAPABILITIES:
5322 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
5323 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
5324 break;
5325
5326 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
5327 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
5328 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
5329 break;
5330
5331 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
5332 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
5333 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
5334 break;
5335
5336 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
5337 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
5338 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
5339 break;
5340
5341 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
5342 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
5343 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
5344 break;
5345
5346 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
5347 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
5348 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
5349 break;
5350
5351 case AVRC_PDU_GET_ELEMENT_ATTR:
5352 avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT;
5353 handle_get_metadata_attr_response(&meta_msg, &avrc_response.get_attrs);
5354 break;
5355
5356 case AVRC_PDU_GET_PLAY_STATUS:
5357 avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT;
5358 handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status);
5359 break;
5360
5361 case AVRC_PDU_SET_PLAYER_APP_VALUE:
5362 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
5363 handle_set_app_attr_val_response(&meta_msg, &avrc_response.set_app_val);
5364 break;
5365
5366 case AVRC_PDU_PLAY_ITEM:
5367 // Nothing to notify on, just release the label
5368 break;
5369
5370 default:
5371 log::warn("timeout for unknown pdu_id={}", p_context->pdu_id);
5372 break;
5373 }
5374 }
5375
5376 /***************************************************************************
5377 *
5378 * Function browse_cmd_timeout_handler
5379 *
5380 * Description Browse command timeout handler
5381 * Returns None
5382 *
5383 **************************************************************************/
browse_cmd_timeout_handler(btif_rc_device_cb_t * p_dev,uint8_t label,rc_browse_context_t * p_context)5384 static void browse_cmd_timeout_handler(btif_rc_device_cb_t* p_dev, uint8_t label,
5385 rc_browse_context_t* p_context) {
5386 if (p_dev == NULL) {
5387 log::error("p_dev NULL");
5388 return;
5389 }
5390
5391 tAVRC_RESPONSE avrc_response = {0};
5392 tBTA_AV_META_MSG meta_msg = {
5393 .rc_handle = p_dev->rc_handle,
5394 .len = 0,
5395 .label = 0,
5396 .code = 0,
5397 .company_id = 0,
5398 .p_data = nullptr,
5399 .p_msg = nullptr,
5400 };
5401
5402 log::warn("timeout, addr={}, label={}, pdu_id={}", p_dev->rc_addr, label,
5403 dump_rc_pdu(p_context->pdu_id));
5404
5405 switch (p_context->pdu_id) {
5406 case AVRC_PDU_GET_FOLDER_ITEMS:
5407 avrc_response.get_items.status = BTIF_RC_STS_TIMEOUT;
5408 handle_get_folder_items_response(&meta_msg, &avrc_response.get_items);
5409 break;
5410 case AVRC_PDU_CHANGE_PATH:
5411 avrc_response.chg_path.status = BTIF_RC_STS_TIMEOUT;
5412 handle_change_path_response(&meta_msg, &avrc_response.chg_path);
5413 break;
5414 case AVRC_PDU_SET_BROWSED_PLAYER:
5415 avrc_response.br_player.status = BTIF_RC_STS_TIMEOUT;
5416 handle_set_browsed_player_response(&meta_msg, &avrc_response.br_player);
5417 break;
5418 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
5419 avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT;
5420 handle_get_metadata_attr_response(&meta_msg, &avrc_response.get_attrs);
5421 break;
5422 default:
5423 log::warn("timeout for unknown pdu_id={}", p_context->pdu_id);
5424 break;
5425 }
5426 }
5427
5428 /***************************************************************************
5429 *
5430 * Function passthru_cmd_timeout_handler
5431 *
5432 * Description Pass-thru command timeout handler
5433 * Returns None
5434 *
5435 **************************************************************************/
passthru_cmd_timeout_handler(btif_rc_device_cb_t * p_dev,uint8_t label,rc_passthru_context_t * p_context)5436 static void passthru_cmd_timeout_handler(btif_rc_device_cb_t* p_dev, uint8_t label,
5437 rc_passthru_context_t* p_context) {
5438 if (p_dev == NULL) {
5439 log::error("p_dev NULL");
5440 return;
5441 }
5442
5443 log::warn("timeout, addr={}, label={}, rc_id={}, key_state={}", p_dev->rc_addr, label,
5444 p_context->rc_id, p_context->key_state);
5445
5446 // Other requests are wrapped in a tAVRC_RESPONSE response object, but these
5447 // passthru events are not in there. As well, the upper layers don't handle
5448 // these events anyways. If that were to change, we could check the rc_id and
5449 // choose to route either the passthrough handler or vendorunique handler here
5450 return;
5451 }
5452
5453 /***************************************************************************
5454 *
5455 * Function btif_rc_transaction_timeout_handler
5456 *
5457 * Description RC transaction timeout handler (Runs in BTIF context).
5458 * Returns None
5459 *
5460 **************************************************************************/
btif_rc_transaction_timeout_handler(uint16_t,char * data)5461 static void btif_rc_transaction_timeout_handler(uint16_t /* event */, char* data) {
5462 rc_transaction_context_t* p_context = (rc_transaction_context_t*)data;
5463 if (p_context == nullptr) {
5464 log::error("p_context is null");
5465 return;
5466 }
5467
5468 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(p_context->rc_addr);
5469 if (p_dev == NULL) {
5470 log::error("p_dev is null");
5471 return;
5472 }
5473
5474 uint8_t label = p_context->label;
5475 switch (p_context->opcode) {
5476 case AVRC_OP_VENDOR:
5477 vendor_cmd_timeout_handler(p_dev, label, &(p_context->command.vendor));
5478 break;
5479 case AVRC_OP_BROWSE:
5480 browse_cmd_timeout_handler(p_dev, label, &(p_context->command.browse));
5481 break;
5482 case AVRC_OP_PASS_THRU:
5483 passthru_cmd_timeout_handler(p_dev, label, &(p_context->command.passthru));
5484 break;
5485 default:
5486 log::warn("received timeout for unknown opcode={}", p_context->opcode);
5487 return;
5488 }
5489 release_transaction(p_dev, label);
5490 }
5491
5492 /***************************************************************************
5493 *
5494 * Function btif_rc_transaction_timer_timeout
5495 *
5496 * Description RC transaction timeout callback.
5497 * This is called from BTU context and switches to BTIF
5498 * context to handle the timeout events
5499 * Returns None
5500 *
5501 **************************************************************************/
btif_rc_transaction_timer_timeout(void * data)5502 static void btif_rc_transaction_timer_timeout(void* data) {
5503 rc_transaction_context_t* p_data = (rc_transaction_context_t*)data;
5504
5505 btif_transfer_context(btif_rc_transaction_timeout_handler, 0, (char*)p_data,
5506 sizeof(rc_transaction_context_t), NULL);
5507 }
5508
5509 /*******************************************************************************
5510 * Function sleep_ms
5511 *
5512 * Description Sleep the calling thread unconditionally for
5513 * |timeout_ms| milliseconds.
5514 *
5515 * Returns void
5516 ******************************************************************************/
sleep_ms(uint64_t timeout_ms)5517 static void sleep_ms(uint64_t timeout_ms) {
5518 struct timespec delay;
5519 delay.tv_sec = timeout_ms / 1000;
5520 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
5521
5522 OSI_NO_INTR(nanosleep(&delay, &delay));
5523 }
5524
5525 /*******************************************************************************
5526 * Function btif_debug_rc_dump
5527 *
5528 * Description Dumps the state of the btif_rc subsytem
5529 *
5530 * Returns void
5531 ******************************************************************************/
btif_debug_rc_dump(int fd)5532 void btif_debug_rc_dump(int fd) {
5533 dprintf(fd, "\nAVRCP Native State:\n");
5534
5535 int connected_count = 0;
5536 for (int i = 0; i < BTIF_RC_NUM_CONN; ++i) {
5537 const btrc_connection_state_t state = btif_rc_cb.rc_multi_cb[i].rc_state;
5538 if (state != BTRC_CONNECTION_STATE_DISCONNECTED) {
5539 ++connected_count;
5540 }
5541 }
5542
5543 dprintf(fd, " Devices (%d / %d):\n", connected_count, BTIF_RC_NUM_CONN - 1);
5544 for (int i = 0; i < BTIF_RC_NUM_CONN; ++i) {
5545 btif_rc_device_cb_t* p_dev = &btif_rc_cb.rc_multi_cb[i];
5546 if (p_dev->rc_state != BTRC_CONNECTION_STATE_DISCONNECTED) {
5547 dprintf(fd, " %s:\n", ADDRESS_TO_LOGGABLE_CSTR(p_dev->rc_addr));
5548
5549 rc_transaction_set_t* transaction_set = &(p_dev->transaction_set);
5550 std::unique_lock<std::recursive_mutex> lock(transaction_set->label_lock);
5551 dprintf(fd, " Transaction Labels:\n");
5552 for (auto j = 0; j < MAX_TRANSACTIONS_PER_SESSION; ++j) {
5553 dprintf(fd, " %s\n", dump_transaction(&transaction_set->transaction[j]).c_str());
5554 }
5555 }
5556 }
5557 }
5558
absolute_volume_disabled()5559 static bool absolute_volume_disabled() {
5560 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
5561 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
5562 if (strncmp(volume_disabled, "true", 4) == 0) {
5563 log::warn("Absolute volume disabled by property");
5564 return true;
5565 }
5566 return false;
5567 }
5568