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