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