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 "log/log.h"
50 #include "osi/include/list.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,btrc_media_attr_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, btrc_media_attr_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,
1520 (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs,
1521 BTRC_MAX_ELEM_ATTR_SIZE, element_attrs);
1522 if (num_attr == 0) {
1523 BTIF_TRACE_ERROR(
1524 "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES",
1525 __func__);
1526 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1527 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1528 return;
1529 }
1530 fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev);
1531 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs,
1532 p_dev->rc_addr);
1533 } break;
1534 case AVRC_PDU_REGISTER_NOTIFICATION: {
1535 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1536 pavrc_cmd->reg_notif.param == 0) {
1537 BTIF_TRACE_WARNING(
1538 "%s: Device registering position changed with illegal param 0.",
1539 __func__);
1540 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1541 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1542 /* de-register this notification for a rejected response */
1543 p_dev->rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = false;
1544 return;
1545 }
1546 HAL_CBACK(bt_rc_callbacks, register_notification_cb,
1547 (btrc_event_id_t)pavrc_cmd->reg_notif.event_id,
1548 pavrc_cmd->reg_notif.param, p_dev->rc_addr);
1549 } break;
1550 case AVRC_PDU_INFORM_DISPLAY_CHARSET: {
1551 tAVRC_RESPONSE avrc_rsp;
1552 BTIF_TRACE_EVENT("%s: AVRC_PDU_INFORM_DISPLAY_CHARSET", __func__);
1553 if (p_dev->rc_connected) {
1554 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1555 avrc_rsp.inform_charset.opcode =
1556 opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1557 avrc_rsp.inform_charset.pdu = AVRC_PDU_INFORM_DISPLAY_CHARSET;
1558 avrc_rsp.inform_charset.status = AVRC_STS_NO_ERROR;
1559 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1560 }
1561 } break;
1562
1563 case AVRC_PDU_GET_FOLDER_ITEMS: {
1564 uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE] = {0};
1565 uint8_t num_attr;
1566 num_attr = pavrc_cmd->get_items.attr_count;
1567
1568 BTIF_TRACE_EVENT(
1569 "%s: AVRC_PDU_GET_FOLDER_ITEMS num_attr: %d, start_item [%d] \
1570 end_item [%d]",
1571 __func__, num_attr, pavrc_cmd->get_items.start_item,
1572 pavrc_cmd->get_items.end_item);
1573
1574 /* num_attr requested:
1575 * 0x00: All attributes requested
1576 * 0xFF: No Attributes requested
1577 * 0x01 to 0x07: Specified number of attributes
1578 */
1579 if ((num_attr != 0xFF && num_attr > BTRC_MAX_ELEM_ATTR_SIZE)) {
1580 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1581 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1582 return;
1583 }
1584
1585 /* Except num_attr is None(0xff) / All(0x00), request follows with an
1586 * Attribute List */
1587 if ((num_attr != 0xFF) && (num_attr != 0x00)) {
1588 memcpy(attr_ids, pavrc_cmd->get_items.p_attr_list,
1589 sizeof(uint32_t) * num_attr);
1590 }
1591
1592 fill_pdu_queue(IDX_GET_FOLDER_ITEMS_RSP, ctype, label, true, p_dev);
1593 HAL_CBACK(bt_rc_callbacks, get_folder_items_cb,
1594 pavrc_cmd->get_items.scope, pavrc_cmd->get_items.start_item,
1595 pavrc_cmd->get_items.end_item, num_attr, attr_ids,
1596 p_dev->rc_addr);
1597 } break;
1598
1599 case AVRC_PDU_SET_ADDRESSED_PLAYER: {
1600 fill_pdu_queue(IDX_SET_ADDR_PLAYER_RSP, ctype, label, true, p_dev);
1601 HAL_CBACK(bt_rc_callbacks, set_addressed_player_cb,
1602 pavrc_cmd->addr_player.player_id, p_dev->rc_addr);
1603 } break;
1604
1605 case AVRC_PDU_SET_BROWSED_PLAYER: {
1606 fill_pdu_queue(IDX_SET_BROWSED_PLAYER_RSP, ctype, label, true, p_dev);
1607 HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb,
1608 pavrc_cmd->br_player.player_id, p_dev->rc_addr);
1609 } break;
1610
1611 case AVRC_PDU_REQUEST_CONTINUATION_RSP: {
1612 BTIF_TRACE_EVENT("%s() REQUEST CONTINUATION: target_pdu: 0x%02d",
1613 __func__, pavrc_cmd->continu.target_pdu);
1614 tAVRC_RESPONSE avrc_rsp;
1615 if (p_dev->rc_connected == TRUE) {
1616 memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP));
1617 avrc_rsp.continu.opcode =
1618 opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP);
1619 avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
1620 avrc_rsp.continu.status = AVRC_STS_NO_ERROR;
1621 avrc_rsp.continu.target_pdu = pavrc_cmd->continu.target_pdu;
1622 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1623 }
1624 } break;
1625
1626 case AVRC_PDU_ABORT_CONTINUATION_RSP: {
1627 BTIF_TRACE_EVENT("%s() ABORT CONTINUATION: target_pdu: 0x%02d", __func__,
1628 pavrc_cmd->abort.target_pdu);
1629 tAVRC_RESPONSE avrc_rsp;
1630 if (p_dev->rc_connected == TRUE) {
1631 memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP));
1632 avrc_rsp.abort.opcode =
1633 opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP);
1634 avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP;
1635 avrc_rsp.abort.status = AVRC_STS_NO_ERROR;
1636 avrc_rsp.abort.target_pdu = pavrc_cmd->continu.target_pdu;
1637 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1638 }
1639 } break;
1640
1641 case AVRC_PDU_CHANGE_PATH: {
1642 fill_pdu_queue(IDX_CHG_PATH_RSP, ctype, label, true, p_dev);
1643 HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction,
1644 pavrc_cmd->chg_path.folder_uid, p_dev->rc_addr);
1645 } break;
1646
1647 case AVRC_PDU_SEARCH: {
1648 fill_pdu_queue(IDX_SEARCH_RSP, ctype, label, true, p_dev);
1649 HAL_CBACK(bt_rc_callbacks, search_cb, pavrc_cmd->search.string.charset_id,
1650 pavrc_cmd->search.string.str_len,
1651 pavrc_cmd->search.string.p_str, p_dev->rc_addr);
1652 } break;
1653
1654 case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
1655 btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE] = {};
1656 uint8_t num_attr = fill_attribute_id_array(
1657 pavrc_cmd->get_attrs.attr_count,
1658 (btrc_media_attr_t*)pavrc_cmd->get_attrs.p_attr_list,
1659 BTRC_MAX_ELEM_ATTR_SIZE, item_attrs);
1660 if (num_attr == 0) {
1661 BTIF_TRACE_ERROR(
1662 "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES",
1663 __func__);
1664 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1665 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1666 return;
1667 }
1668 fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev);
1669 BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__,
1670 num_attr);
1671 HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
1672 pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter,
1673 num_attr, item_attrs, p_dev->rc_addr);
1674 } break;
1675
1676 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: {
1677 fill_pdu_queue(IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, ctype, label, true, p_dev);
1678 HAL_CBACK(bt_rc_callbacks, get_total_num_of_items_cb,
1679 pavrc_cmd->get_num_of_items.scope, p_dev->rc_addr);
1680 } break;
1681
1682 case AVRC_PDU_ADD_TO_NOW_PLAYING: {
1683 fill_pdu_queue(IDX_ADD_TO_NOW_PLAYING_RSP, ctype, label, true, p_dev);
1684 HAL_CBACK(bt_rc_callbacks, add_to_now_playing_cb,
1685 pavrc_cmd->add_to_play.scope, pavrc_cmd->add_to_play.uid,
1686 pavrc_cmd->add_to_play.uid_counter, p_dev->rc_addr);
1687 } break;
1688
1689 case AVRC_PDU_PLAY_ITEM: {
1690 fill_pdu_queue(IDX_PLAY_ITEM_RSP, ctype, label, true, p_dev);
1691 HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
1692 pavrc_cmd->play_item.uid_counter, pavrc_cmd->play_item.uid,
1693 p_dev->rc_addr);
1694 } break;
1695
1696 default: {
1697 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1698 AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode);
1699 return;
1700 } break;
1701 }
1702 }
1703
1704 /*******************************************************************************
1705 *
1706 * Function btif_rc_ctrl_upstreams_rsp_cmd
1707 *
1708 * Description Executes AVRC UPSTREAMS response events in btif context.
1709 *
1710 * Returns void
1711 *
1712 ******************************************************************************/
btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,tAVRC_COMMAND * pavrc_cmd,uint8_t label,btif_rc_device_cb_t * p_dev)1713 static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,
1714 tAVRC_COMMAND* pavrc_cmd,
1715 uint8_t label,
1716 btif_rc_device_cb_t* p_dev) {
1717 BTIF_TRACE_DEBUG("%s: pdu: %s: handle: 0x%x", __func__,
1718 dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle);
1719 switch (event) {
1720 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1721 do_in_jni_thread(
1722 FROM_HERE,
1723 base::Bind(bt_rc_ctrl_callbacks->setabsvol_cmd_cb, p_dev->rc_addr,
1724 pavrc_cmd->volume.volume, label));
1725 break;
1726 case AVRC_PDU_REGISTER_NOTIFICATION:
1727 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE) {
1728 do_in_jni_thread(
1729 FROM_HERE,
1730 base::Bind(bt_rc_ctrl_callbacks->registernotification_absvol_cb,
1731 p_dev->rc_addr, label));
1732 }
1733 break;
1734 }
1735 }
1736
1737 /*******************************************************************************
1738 *
1739 * Function btif_rc_upstreams_rsp_evt
1740 *
1741 * Description Executes AVRC UPSTREAMS response events in btif context.
1742 *
1743 * Returns void
1744 *
1745 ******************************************************************************/
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)1746 static void btif_rc_upstreams_rsp_evt(uint16_t event,
1747 tAVRC_RESPONSE* pavrc_resp, uint8_t ctype,
1748 uint8_t label,
1749 btif_rc_device_cb_t* p_dev) {
1750 BTIF_TRACE_EVENT("%s: pdu: %s: handle: 0x%x ctype: %x label: %x", __func__,
1751 dump_rc_pdu(pavrc_resp->pdu), p_dev->rc_handle, ctype,
1752 label);
1753
1754 switch (event) {
1755 case AVRC_PDU_REGISTER_NOTIFICATION: {
1756 if (AVRC_RSP_CHANGED == ctype)
1757 p_dev->rc_volume = pavrc_resp->reg_notif.param.volume;
1758 HAL_CBACK(bt_rc_callbacks, volume_change_cb,
1759 pavrc_resp->reg_notif.param.volume, ctype, p_dev->rc_addr);
1760 } break;
1761
1762 case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
1763 BTIF_TRACE_DEBUG(
1764 "%s: Set absolute volume change event received: volume: %d, ctype: "
1765 "%d",
1766 __func__, pavrc_resp->volume.volume, ctype);
1767 if (AVRC_RSP_ACCEPT == ctype)
1768 p_dev->rc_volume = pavrc_resp->volume.volume;
1769 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->volume.volume,
1770 ctype, p_dev->rc_addr);
1771 } break;
1772
1773 default:
1774 return;
1775 }
1776 }
1777
1778 /*******************************************************************************
1779 * AVRCP API Functions
1780 ******************************************************************************/
1781
1782 /*******************************************************************************
1783 *
1784 * Function init
1785 *
1786 * Description Initializes the AVRC interface
1787 *
1788 * Returns bt_status_t
1789 *
1790 ******************************************************************************/
init(btrc_callbacks_t * callbacks)1791 static bt_status_t init(btrc_callbacks_t* callbacks) {
1792 BTIF_TRACE_EVENT("%s: ", __func__);
1793 bt_status_t result = BT_STATUS_SUCCESS;
1794
1795 if (bt_rc_callbacks) return BT_STATUS_DONE;
1796
1797 bt_rc_callbacks = callbacks;
1798 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1799 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
1800 sizeof(btif_rc_cb.rc_multi_cb[idx]));
1801 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL;
1802 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME;
1803 btif_rc_cb.rc_multi_cb[idx].rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
1804 }
1805 lbl_init();
1806
1807 return result;
1808 }
1809
1810 /*******************************************************************************
1811 *
1812 * Function init_ctrl
1813 *
1814 * Description Initializes the AVRC interface
1815 *
1816 * Returns bt_status_t
1817 *
1818 ******************************************************************************/
init_ctrl(btrc_ctrl_callbacks_t * callbacks)1819 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks) {
1820 BTIF_TRACE_EVENT("%s: ", __func__);
1821 bt_status_t result = BT_STATUS_SUCCESS;
1822
1823 if (bt_rc_ctrl_callbacks) return BT_STATUS_DONE;
1824
1825 bt_rc_ctrl_callbacks = callbacks;
1826 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1827 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
1828 sizeof(btif_rc_cb.rc_multi_cb[idx]));
1829 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL;
1830 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME;
1831 btif_rc_cb.rc_multi_cb[idx].rc_features_processed = FALSE;
1832 }
1833 lbl_init();
1834
1835 return result;
1836 }
1837
rc_ctrl_procedure_complete(btif_rc_device_cb_t * p_dev)1838 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev) {
1839 if (p_dev == NULL) {
1840 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
1841 return;
1842 }
1843
1844 if (p_dev->rc_procedure_complete) {
1845 return;
1846 }
1847 p_dev->rc_procedure_complete = true;
1848 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
1849 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
1850 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
1851 }
1852
1853 /***************************************************************************
1854 *
1855 * Function get_play_status_rsp
1856 *
1857 * Description Returns the current play status.
1858 * This method is called in response to
1859 * GetPlayStatus request.
1860 *
1861 * Returns bt_status_t
1862 *
1863 **************************************************************************/
get_play_status_rsp(const RawAddress & bd_addr,btrc_play_status_t play_status,uint32_t song_len,uint32_t song_pos)1864 static bt_status_t get_play_status_rsp(const RawAddress& bd_addr,
1865 btrc_play_status_t play_status,
1866 uint32_t song_len, uint32_t song_pos) {
1867 tAVRC_RESPONSE avrc_rsp;
1868 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1869
1870 BTIF_TRACE_DEBUG("%s: song len %d song pos %d", __func__, song_len, song_pos);
1871 CHECK_RC_CONNECTED(p_dev);
1872
1873 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1874
1875 avrc_rsp.get_play_status.song_len = song_len;
1876 avrc_rsp.get_play_status.song_pos = song_pos;
1877 avrc_rsp.get_play_status.play_status = play_status;
1878
1879 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1880 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1881 avrc_rsp.get_play_status.status =
1882 ((play_status != BTRC_PLAYSTATE_ERROR) ? AVRC_STS_NO_ERROR
1883 : AVRC_STS_BAD_PARAM);
1884
1885 /* Send the response */
1886 send_metamsg_rsp(p_dev, IDX_GET_PLAY_STATUS_RSP,
1887 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].label,
1888 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].ctype,
1889 &avrc_rsp);
1890
1891 return BT_STATUS_SUCCESS;
1892 }
1893
1894 /***************************************************************************
1895 *
1896 * Function get_element_attr_rsp
1897 *
1898 * Description Returns the current songs' element attributes
1899 * in text.
1900 *
1901 * Returns bt_status_t
1902 *
1903 **************************************************************************/
get_element_attr_rsp(const RawAddress & bd_addr,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)1904 static bt_status_t get_element_attr_rsp(const RawAddress& bd_addr,
1905 uint8_t num_attr,
1906 btrc_element_attr_val_t* p_attrs) {
1907 tAVRC_RESPONSE avrc_rsp;
1908 uint32_t i;
1909 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1910 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1911
1912 BTIF_TRACE_DEBUG("%s", __func__);
1913 CHECK_RC_CONNECTED(p_dev);
1914
1915 if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) {
1916 LOG(WARNING) << __func__
1917 << " Exceeded number attributes:" << static_cast<int>(num_attr)
1918 << " max:" << BTRC_MAX_ELEM_ATTR_SIZE;
1919 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1920 }
1921 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1922
1923 if (num_attr == 0) {
1924 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1925 } else {
1926 for (i = 0; i < num_attr; i++) {
1927 element_attrs[i].attr_id = p_attrs[i].attr_id;
1928 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1929 element_attrs[i].name.str_len =
1930 (uint16_t)strnlen((char*)p_attrs[i].text, BTRC_MAX_ATTR_STR_LEN);
1931 element_attrs[i].name.p_str = p_attrs[i].text;
1932 BTIF_TRACE_DEBUG(
1933 "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__,
1934 (unsigned int)element_attrs[i].attr_id,
1935 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1936 element_attrs[i].name.p_str);
1937 }
1938 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1939 }
1940 avrc_rsp.get_attrs.num_attrs = num_attr;
1941 avrc_rsp.get_attrs.p_attrs = element_attrs;
1942 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1943 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1944
1945 /* Send the response */
1946 send_metamsg_rsp(p_dev, IDX_GET_ELEMENT_ATTR_RSP,
1947 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].label,
1948 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].ctype,
1949 &avrc_rsp);
1950
1951 return BT_STATUS_SUCCESS;
1952 }
1953
1954 /***************************************************************************
1955 *
1956 * Function register_notification_rsp
1957 *
1958 * Description Response to the register notification request.
1959 *
1960 * Returns bt_status_t
1961 *
1962 **************************************************************************/
register_notification_rsp(btrc_event_id_t event_id,btrc_notification_type_t type,btrc_register_notification_t * p_param)1963 static bt_status_t register_notification_rsp(
1964 btrc_event_id_t event_id, btrc_notification_type_t type,
1965 btrc_register_notification_t* p_param) {
1966 tAVRC_RESPONSE avrc_rsp;
1967 BTIF_TRACE_EVENT("%s: event_id: %s", __func__,
1968 dump_rc_notification_event_id(event_id));
1969 std::unique_lock<std::mutex> lock(btif_rc_cb.lock);
1970
1971 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1972
1973 avrc_rsp.reg_notif.event_id = event_id;
1974 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1975 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1976 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1977
1978 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1979 memset(&(avrc_rsp.reg_notif.param), 0, sizeof(tAVRC_NOTIF_RSP_PARAM));
1980
1981 if (!(btif_rc_cb.rc_multi_cb[idx].rc_connected)) {
1982 BTIF_TRACE_ERROR("%s: Avrcp device is not connected, handle: 0x%x",
1983 __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1984 continue;
1985 }
1986
1987 if (!btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify) {
1988 BTIF_TRACE_WARNING(
1989 "%s: Avrcp Event id is not registered: event_id: %x, handle: 0x%x",
1990 __func__, event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1991 continue;
1992 }
1993
1994 BTIF_TRACE_DEBUG(
1995 "%s: Avrcp Event id is registered: event_id: %x handle: 0x%x", __func__,
1996 event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1997
1998 switch (event_id) {
1999 case BTRC_EVT_PLAY_STATUS_CHANGED:
2000 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
2001 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
2002 btif_av_clear_remote_suspend_flag();
2003 break;
2004 case BTRC_EVT_TRACK_CHANGE:
2005 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track),
2006 sizeof(btrc_uid_t));
2007 break;
2008 case BTRC_EVT_PLAY_POS_CHANGED:
2009 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
2010 break;
2011 case BTRC_EVT_AVAL_PLAYER_CHANGE:
2012 break;
2013 case BTRC_EVT_ADDR_PLAYER_CHANGE:
2014 avrc_rsp.reg_notif.param.addr_player.player_id =
2015 p_param->addr_player_changed.player_id;
2016 avrc_rsp.reg_notif.param.addr_player.uid_counter =
2017 p_param->addr_player_changed.uid_counter;
2018 break;
2019 case BTRC_EVT_UIDS_CHANGED:
2020 avrc_rsp.reg_notif.param.uid_counter =
2021 p_param->uids_changed.uid_counter;
2022 break;
2023 case BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED:
2024 break;
2025
2026 default:
2027 BTIF_TRACE_WARNING("%s: Unhandled event ID: 0x%x", __func__, event_id);
2028 return BT_STATUS_UNHANDLED;
2029 }
2030
2031 /* Send the response. */
2032 send_metamsg_rsp(
2033 &btif_rc_cb.rc_multi_cb[idx], -1,
2034 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label,
2035 ((type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_CMD_NOTIF
2036 : AVRC_RSP_CHANGED),
2037 &avrc_rsp);
2038 }
2039 return BT_STATUS_SUCCESS;
2040 }
2041
2042 /***************************************************************************
2043 *
2044 * Function get_folder_items_list_rsp
2045 *
2046 * Description Returns the list of media items in current folder along with
2047 * requested attributes. This is called in response to
2048 * GetFolderItems request.
2049 *
2050 * Returns bt_status_t
2051 * BT_STATUS_NOT_READY - when RC is not connected.
2052 * BT_STATUS_SUCCESS - always if RC is connected
2053 * BT_STATUS_UNHANDLED - when rsp is not pending for
2054 * get_folder_items_list PDU
2055 *
2056 **************************************************************************/
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)2057 static bt_status_t get_folder_items_list_rsp(const RawAddress& bd_addr,
2058 btrc_status_t rsp_status,
2059 uint16_t uid_counter,
2060 uint8_t num_items,
2061 btrc_folder_items_t* p_items) {
2062 tAVRC_RESPONSE avrc_rsp;
2063 tAVRC_ITEM item;
2064 tBTA_AV_CODE code = 0, ctype = 0;
2065 BT_HDR* p_msg = NULL;
2066 int item_cnt;
2067 tAVRC_STS status = AVRC_STS_NO_ERROR;
2068 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2069 btrc_folder_items_t* cur_item = NULL;
2070
2071 BTIF_TRACE_DEBUG("%s: uid_counter %d num_items %d", __func__, uid_counter,
2072 num_items);
2073 CHECK_RC_CONNECTED(p_dev);
2074
2075 /* check if rsp to previous cmd was completed */
2076 if (!p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending) {
2077 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
2078 __func__);
2079 return BT_STATUS_UNHANDLED;
2080 }
2081
2082 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2083 memset(&item, 0, sizeof(tAVRC_ITEM));
2084
2085 avrc_rsp.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
2086 avrc_rsp.get_items.opcode = opcode_from_pdu(AVRC_PDU_GET_FOLDER_ITEMS);
2087 avrc_rsp.get_items.status = status_code_map[rsp_status];
2088
2089 if (avrc_rsp.get_items.status != AVRC_STS_NO_ERROR) {
2090 BTIF_TRACE_WARNING(
2091 "%s: Error in parsing the received getfolderitems cmd. status: 0x%02x",
2092 __func__, avrc_rsp.get_items.status);
2093 status = avrc_rsp.get_items.status;
2094 } else {
2095 avrc_rsp.get_items.uid_counter = uid_counter;
2096 avrc_rsp.get_items.item_count = 1;
2097
2098 /* create single item and build response iteratively for all num_items */
2099 for (item_cnt = 0; item_cnt < num_items; item_cnt++) {
2100 cur_item = &p_items[item_cnt];
2101 item.item_type = p_items->item_type;
2102 /* build respective item based on item_type. All items should be of same
2103 * type within
2104 * a response */
2105 switch (p_items->item_type) {
2106 case AVRC_ITEM_PLAYER: {
2107 item.u.player.name.charset_id = cur_item->player.charset_id;
2108 memcpy(&(item.u.player.features), &(cur_item->player.features),
2109 sizeof(cur_item->player.features));
2110 item.u.player.major_type = cur_item->player.major_type;
2111 item.u.player.sub_type = cur_item->player.sub_type;
2112 item.u.player.play_status = cur_item->player.play_status;
2113 item.u.player.player_id = cur_item->player.player_id;
2114 item.u.player.name.p_str = cur_item->player.name;
2115 item.u.player.name.str_len =
2116 (uint16_t)strlen((char*)(cur_item->player.name));
2117 } break;
2118
2119 case AVRC_ITEM_FOLDER: {
2120 memcpy(item.u.folder.uid, cur_item->folder.uid, sizeof(tAVRC_UID));
2121 item.u.folder.type = cur_item->folder.type;
2122 item.u.folder.playable = cur_item->folder.playable;
2123 item.u.folder.name.charset_id = AVRC_CHARSET_ID_UTF8;
2124 item.u.folder.name.str_len = strlen((char*)cur_item->folder.name);
2125 item.u.folder.name.p_str = cur_item->folder.name;
2126 } break;
2127
2128 case AVRC_ITEM_MEDIA: {
2129 tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE] = {};
2130
2131 memcpy(item.u.media.uid, cur_item->media.uid, sizeof(tAVRC_UID));
2132 item.u.media.type = cur_item->media.type;
2133 item.u.media.name.charset_id = cur_item->media.charset_id;
2134 item.u.media.name.str_len = strlen((char*)cur_item->media.name);
2135 item.u.media.name.p_str = cur_item->media.name;
2136 item.u.media.attr_count = cur_item->media.num_attrs;
2137
2138 /* Handle attributes of given item */
2139 if (item.u.media.attr_count == 0) {
2140 item.u.media.p_attr_list = NULL;
2141 } else {
2142 memset(&attr_vals, 0,
2143 sizeof(tAVRC_ATTR_ENTRY) * BTRC_MAX_ELEM_ATTR_SIZE);
2144 fill_avrc_attr_entry(attr_vals, item.u.media.attr_count,
2145 cur_item->media.p_attrs);
2146 item.u.media.p_attr_list = attr_vals;
2147 }
2148 } break;
2149
2150 default: {
2151 BTIF_TRACE_ERROR("%s: Unknown item_type: %d. Internal Error",
2152 __func__, p_items->item_type);
2153 status = AVRC_STS_INTERNAL_ERR;
2154 } break;
2155 }
2156
2157 avrc_rsp.get_items.p_item_list = &item;
2158
2159 /* Add current item to buffer and build response if no error in item type
2160 */
2161 if (status != AVRC_STS_NO_ERROR) {
2162 /* Reject response due to error occured for unknown item_type, break the
2163 * loop */
2164 break;
2165 }
2166
2167 int len_before = p_msg ? p_msg->len : 0;
2168 BTIF_TRACE_DEBUG("%s: item_cnt: %d len: %d", __func__, item_cnt,
2169 len_before);
2170 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2171 BTIF_TRACE_DEBUG("%s: Build rsp status: %d len: %d", __func__, status,
2172 (p_msg ? p_msg->len : 0));
2173 int len_after = p_msg ? p_msg->len : 0;
2174 if (status != AVRC_STS_NO_ERROR || len_before == len_after) {
2175 /* Error occured in build response or we ran out of buffer so break the
2176 * loop */
2177 break;
2178 }
2179 }
2180
2181 /* setting the error status */
2182 avrc_rsp.get_items.status = status;
2183 }
2184
2185 /* if packet built successfully, send the built items to BTA layer */
2186 if (status == AVRC_STS_NO_ERROR) {
2187 code = p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype;
2188 ctype = get_rsp_type_code(avrc_rsp.get_items.status, code);
2189 BTA_AvMetaRsp(p_dev->rc_handle,
2190 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label, ctype,
2191 p_msg);
2192 } else /* Error occured, send reject response */
2193 {
2194 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__,
2195 avrc_rsp.rsp.status);
2196 send_reject_response(
2197 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label,
2198 avrc_rsp.pdu, avrc_rsp.get_items.status, avrc_rsp.get_items.opcode);
2199 }
2200
2201 /* Reset values for current pdu. */
2202 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype = 0;
2203 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label = 0;
2204 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending = false;
2205
2206 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2207 }
2208
2209 /***************************************************************************
2210 *
2211 * Function set_addressed_player_rsp
2212 *
2213 * Description Response to set the addressed player for specified media
2214 * player based on id in the media player list.
2215 *
2216 * Returns bt_status_t
2217 * BT_STATUS_NOT_READY - when RC is not connected.
2218 * BT_STATUS_SUCCESS - always if RC is connected
2219 *
2220 **************************************************************************/
set_addressed_player_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2221 static bt_status_t set_addressed_player_rsp(const RawAddress& bd_addr,
2222 btrc_status_t rsp_status) {
2223 tAVRC_RESPONSE avrc_rsp;
2224 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2225
2226 BTIF_TRACE_DEBUG("%s", __func__);
2227 CHECK_RC_CONNECTED(p_dev);
2228
2229 avrc_rsp.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
2230 avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER);
2231 avrc_rsp.addr_player.status = status_code_map[rsp_status];
2232
2233 /* Send the response. */
2234 send_metamsg_rsp(p_dev, IDX_SET_ADDR_PLAYER_RSP,
2235 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].label,
2236 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].ctype,
2237 &avrc_rsp);
2238
2239 return BT_STATUS_SUCCESS;
2240 }
2241
2242 /***************************************************************************
2243 *
2244 * Function set_browsed_player_rsp
2245 *
2246 * Description Response to set the browsed player command which contains
2247 * current browsed path of the media player. By default,
2248 * current_path = root and folder_depth = 0 for
2249 * every set_browsed_player request.
2250 *
2251 * Returns bt_status_t
2252 * BT_STATUS_NOT_READY - when RC is not connected.
2253 * BT_STATUS_SUCCESS - if RC is connected and reponse
2254 * sent successfully
2255 * BT_STATUS_UNHANDLED - when rsp is not pending for
2256 * set_browsed_player PDU
2257 *
2258 **************************************************************************/
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)2259 static bt_status_t set_browsed_player_rsp(const RawAddress& bd_addr,
2260 btrc_status_t rsp_status,
2261 uint32_t num_items,
2262 uint16_t charset_id,
2263 uint8_t folder_depth,
2264 btrc_br_folder_name_t* p_folders) {
2265 tAVRC_RESPONSE avrc_rsp;
2266 tAVRC_NAME item;
2267 BT_HDR* p_msg = NULL;
2268 tBTA_AV_CODE code = 0;
2269 tBTA_AV_CODE ctype = 0;
2270 unsigned int item_cnt;
2271 tAVRC_STS status = AVRC_STS_NO_ERROR;
2272 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2273
2274 CHECK_RC_CONNECTED(p_dev);
2275
2276 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2277 memset(&item, 0, sizeof(tAVRC_NAME));
2278
2279 avrc_rsp.br_player.status = status_code_map[rsp_status];
2280 avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
2281 avrc_rsp.br_player.opcode = opcode_from_pdu(AVRC_PDU_SET_BROWSED_PLAYER);
2282
2283 BTIF_TRACE_DEBUG("%s: rsp_status: 0x%02X avrc_rsp.br_player.status: 0x%02X",
2284 __func__, rsp_status, avrc_rsp.br_player.status);
2285
2286 /* check if rsp to previous cmd was completed */
2287 if (!p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending) {
2288 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
2289 __func__);
2290 return BT_STATUS_UNHANDLED;
2291 }
2292
2293 if (AVRC_STS_NO_ERROR == avrc_rsp.get_items.status) {
2294 avrc_rsp.br_player.num_items = num_items;
2295 avrc_rsp.br_player.charset_id = charset_id;
2296 avrc_rsp.br_player.folder_depth = folder_depth;
2297 avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_folders;
2298
2299 BTIF_TRACE_DEBUG("%s: folder_depth: 0x%02X num_items: %d", __func__,
2300 folder_depth, num_items);
2301
2302 if (folder_depth > 0) {
2303 /* Iteratively build response for all folders across folder depth upto
2304 * current path */
2305 avrc_rsp.br_player.folder_depth = 1;
2306 for (item_cnt = 0; item_cnt < folder_depth; item_cnt++) {
2307 BTIF_TRACE_DEBUG("%s: iteration: %d", __func__, item_cnt);
2308 item.str_len = p_folders[item_cnt].str_len;
2309 item.p_str = p_folders[item_cnt].p_str;
2310 avrc_rsp.br_player.p_folders = &item;
2311
2312 /* Add current item to buffer and build response */
2313 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2314 if (AVRC_STS_NO_ERROR != status) {
2315 BTIF_TRACE_WARNING("%s: Build rsp status: %d", __func__, status);
2316 /* if the build fails, it is likely that we ran out of buffer. so if
2317 * we have
2318 * some items to send, reset this error to no error for sending what we
2319 * have */
2320 if (item_cnt > 0) status = AVRC_STS_NO_ERROR;
2321
2322 /* Error occured in build response so break the loop */
2323 break;
2324 }
2325 }
2326 } else /* current path is root folder, no folders navigated yet */
2327 {
2328 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2329 }
2330
2331 /* setting the error status */
2332 avrc_rsp.br_player.status = status;
2333 } else /* error received from above layer */
2334 {
2335 BTIF_TRACE_WARNING(
2336 "%s: Error in parsing the received setbrowsed command. status: 0x%02x",
2337 __func__, avrc_rsp.br_player.status);
2338 status = avrc_rsp.br_player.status;
2339 }
2340
2341 /* if packet built successfully, send the built items to BTA layer */
2342 if (status == AVRC_STS_NO_ERROR) {
2343 code = p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype;
2344 ctype = get_rsp_type_code(avrc_rsp.br_player.status, code);
2345 BTA_AvMetaRsp(p_dev->rc_handle,
2346 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label, ctype,
2347 p_msg);
2348 } else /* Error occured, send reject response */
2349 {
2350 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__,
2351 avrc_rsp.br_player.status);
2352 send_reject_response(
2353 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label,
2354 avrc_rsp.pdu, avrc_rsp.br_player.status, avrc_rsp.get_items.opcode);
2355 }
2356
2357 /* Reset values for set_browsed_player pdu.*/
2358 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype = 0;
2359 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label = 0;
2360 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending = false;
2361
2362 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2363 }
2364
2365 /*******************************************************************************
2366 *
2367 * Function change_path_rsp
2368 *
2369 * Description Response to the change path command which
2370 * contains number of items in the changed path.
2371 *
2372 * Returns bt_status_t
2373 * BT_STATUS_NOT_READY - when RC is not connected.
2374 * BT_STATUS_SUCCESS - always if RC is connected
2375 *
2376 **************************************************************************/
change_path_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t num_items)2377 static bt_status_t change_path_rsp(const RawAddress& bd_addr,
2378 btrc_status_t rsp_status,
2379 uint32_t num_items) {
2380 tAVRC_RESPONSE avrc_rsp;
2381 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2382
2383 BTIF_TRACE_DEBUG("%s", __func__);
2384 CHECK_RC_CONNECTED(p_dev);
2385
2386 avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
2387 avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH);
2388 avrc_rsp.chg_path.num_items = num_items;
2389 avrc_rsp.chg_path.status = status_code_map[rsp_status];
2390
2391 /* Send the response. */
2392 send_metamsg_rsp(p_dev, IDX_CHG_PATH_RSP,
2393 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].label,
2394 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].ctype, &avrc_rsp);
2395
2396 return BT_STATUS_SUCCESS;
2397 }
2398
2399 /***************************************************************************
2400 *
2401 * Function search_rsp
2402 *
2403 * Description Response to search a string from media content command.
2404 *
2405 * Returns bt_status_t
2406 * BT_STATUS_NOT_READY - when RC is not connected.
2407 * BT_STATUS_SUCCESS - always if RC is connected
2408 *
2409 **************************************************************************/
search_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2410 static bt_status_t search_rsp(const RawAddress& bd_addr,
2411 btrc_status_t rsp_status, uint32_t uid_counter,
2412 uint32_t num_items) {
2413 tAVRC_RESPONSE avrc_rsp;
2414 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2415
2416 BTIF_TRACE_DEBUG("%s", __func__);
2417 CHECK_RC_CONNECTED(p_dev);
2418
2419 avrc_rsp.search.pdu = AVRC_PDU_SEARCH;
2420 avrc_rsp.search.opcode = opcode_from_pdu(AVRC_PDU_SEARCH);
2421 avrc_rsp.search.num_items = num_items;
2422 avrc_rsp.search.uid_counter = uid_counter;
2423 avrc_rsp.search.status = status_code_map[rsp_status];
2424
2425 /* Send the response. */
2426 send_metamsg_rsp(p_dev, IDX_SEARCH_RSP,
2427 p_dev->rc_pdu_info[IDX_SEARCH_RSP].label,
2428 p_dev->rc_pdu_info[IDX_SEARCH_RSP].ctype, &avrc_rsp);
2429
2430 return BT_STATUS_SUCCESS;
2431 }
2432 /***************************************************************************
2433 *
2434 * Function get_item_attr_rsp
2435 *
2436 * Description Response to the get item's attributes command which
2437 * contains number of attributes and values list in text.
2438 *
2439 * Returns bt_status_t
2440 * BT_STATUS_NOT_READY - when RC is not connected.
2441 * BT_STATUS_SUCCESS - always if RC is connected
2442 *
2443 **************************************************************************/
get_item_attr_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)2444 static bt_status_t get_item_attr_rsp(const RawAddress& bd_addr,
2445 btrc_status_t rsp_status, uint8_t num_attr,
2446 btrc_element_attr_val_t* p_attrs) {
2447 tAVRC_RESPONSE avrc_rsp;
2448 tAVRC_ATTR_ENTRY item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
2449 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2450
2451 BTIF_TRACE_DEBUG("%s", __func__);
2452 CHECK_RC_CONNECTED(p_dev);
2453
2454 memset(item_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
2455
2456 avrc_rsp.get_attrs.status = status_code_map[rsp_status];
2457 if (rsp_status == BTRC_STS_NO_ERROR) {
2458 fill_avrc_attr_entry(item_attrs, num_attr, p_attrs);
2459 }
2460
2461 avrc_rsp.get_attrs.num_attrs = num_attr;
2462 avrc_rsp.get_attrs.p_attrs = item_attrs;
2463 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
2464 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);
2465
2466 /* Send the response. */
2467 send_metamsg_rsp(p_dev, IDX_GET_ITEM_ATTR_RSP,
2468 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].label,
2469 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].ctype, &avrc_rsp);
2470
2471 return BT_STATUS_SUCCESS;
2472 }
2473
2474 /***************************************************************************
2475 *
2476 * Function add_to_now_playing_rsp
2477 *
2478 * Description Response to command for adding speciafied media item
2479 * to Now Playing queue.
2480 *
2481 * Returns bt_status_t
2482 * BT_STATUS_NOT_READY - when RC is not connected.
2483 * BT_STATUS_SUCCESS - always if RC is connected
2484 *
2485 **************************************************************************/
add_to_now_playing_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2486 static bt_status_t add_to_now_playing_rsp(const RawAddress& bd_addr,
2487 btrc_status_t rsp_status) {
2488 tAVRC_RESPONSE avrc_rsp;
2489 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2490
2491 BTIF_TRACE_DEBUG("%s", __func__);
2492 CHECK_RC_CONNECTED(p_dev);
2493
2494 avrc_rsp.add_to_play.pdu = AVRC_PDU_ADD_TO_NOW_PLAYING;
2495 avrc_rsp.add_to_play.opcode = opcode_from_pdu(AVRC_PDU_ADD_TO_NOW_PLAYING);
2496 avrc_rsp.add_to_play.status = status_code_map[rsp_status];
2497
2498 /* Send the response. */
2499 send_metamsg_rsp(p_dev, IDX_ADD_TO_NOW_PLAYING_RSP,
2500 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].label,
2501 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].ctype,
2502 &avrc_rsp);
2503
2504 return BT_STATUS_SUCCESS;
2505 }
2506
2507 /***************************************************************************
2508 *
2509 * Function play_item_rsp
2510 *
2511 * Description Response to command for playing the specified media item.
2512 *
2513 * Returns bt_status_t
2514 * BT_STATUS_NOT_READY - when RC is not connected.
2515 * BT_STATUS_SUCCESS - always if RC is connected
2516 *
2517 **************************************************************************/
play_item_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status)2518 static bt_status_t play_item_rsp(const RawAddress& bd_addr,
2519 btrc_status_t rsp_status) {
2520 tAVRC_RESPONSE avrc_rsp;
2521 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2522
2523 BTIF_TRACE_DEBUG("%s", __func__);
2524 CHECK_RC_CONNECTED(p_dev);
2525
2526 avrc_rsp.play_item.pdu = AVRC_PDU_PLAY_ITEM;
2527 avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM);
2528 avrc_rsp.play_item.status = status_code_map[rsp_status];
2529
2530 /* Send the response. */
2531 send_metamsg_rsp(p_dev, IDX_PLAY_ITEM_RSP,
2532 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].label,
2533 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].ctype, &avrc_rsp);
2534
2535 return BT_STATUS_SUCCESS;
2536 }
2537
2538 /***************************************************************************
2539 *
2540 * Function get_total_num_of_items_rsp
2541 *
2542 * Description response to command to get the Number of Items
2543 * in the selected folder at the selected scope
2544 *
2545 * Returns bt_status_t
2546 * BT_STATUS_NOT_READY - when RC is not connected.
2547 * BT_STATUS_SUCCESS - always if RC is connected
2548 *
2549 **************************************************************************/
get_total_num_of_items_rsp(const RawAddress & bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2550 static bt_status_t get_total_num_of_items_rsp(const RawAddress& bd_addr,
2551 btrc_status_t rsp_status,
2552 uint32_t uid_counter,
2553 uint32_t num_items) {
2554 tAVRC_RESPONSE avrc_rsp;
2555 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2556
2557 BTIF_TRACE_DEBUG("%s", __func__);
2558 CHECK_RC_CONNECTED(p_dev);
2559
2560 avrc_rsp.get_num_of_items.pdu = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS;
2561 avrc_rsp.get_num_of_items.opcode =
2562 opcode_from_pdu(AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS);
2563 avrc_rsp.get_num_of_items.num_items = num_items;
2564 avrc_rsp.get_num_of_items.uid_counter = uid_counter;
2565 avrc_rsp.get_num_of_items.status = status_code_map[rsp_status];
2566
2567 /* Send the response. */
2568 send_metamsg_rsp(p_dev, IDX_GET_TOTAL_NUM_OF_ITEMS_RSP,
2569 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].label,
2570 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].ctype,
2571 &avrc_rsp);
2572
2573 return BT_STATUS_SUCCESS;
2574 }
2575
2576 /***************************************************************************
2577 *
2578 * Function set_volume
2579 *
2580 * Description Send current volume setting to remote side.
2581 * Support limited to SetAbsoluteVolume
2582 * This can be enhanced to support Relative Volume (AVRCP 1.0).
2583 * With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
2584 * as opposed to absolute volume level
2585 * volume: Should be in the range 0-127. bit7 is reseved and cannot be set
2586 *
2587 * Returns bt_status_t
2588 *
2589 **************************************************************************/
set_volume(uint8_t volume)2590 static bt_status_t set_volume(uint8_t volume) {
2591 BTIF_TRACE_DEBUG("%s: volume: %d", __func__, volume);
2592 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2593
2594 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
2595 if (!btif_rc_cb.rc_multi_cb[idx].rc_connected) continue;
2596
2597 if (btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) {
2598 status = BT_STATUS_DONE;
2599 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x", __func__,
2600 volume);
2601 continue;
2602 }
2603
2604 if ((btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) ||
2605 btif_rc_cb.rc_multi_cb[idx].rc_state !=
2606 BTRC_CONNECTION_STATE_CONNECTED) {
2607 continue;
2608 }
2609
2610 if ((btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_RCTG) == 0) {
2611 status = BT_STATUS_NOT_READY;
2612 continue;
2613 }
2614
2615 if (!(btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_ADV_CTRL))
2616 continue;
2617
2618 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume: %d",
2619 __func__, volume);
2620
2621 tAVRC_COMMAND avrc_cmd = {.volume = {.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME,
2622 .status = AVRC_STS_NO_ERROR,
2623 .opcode = AVRC_OP_VENDOR,
2624 .volume = volume}};
2625
2626 BT_HDR* p_msg = NULL;
2627 if (AVRC_BldCommand(&avrc_cmd, &p_msg) != AVRC_STS_NO_ERROR) {
2628 BTIF_TRACE_ERROR(
2629 "%s: failed to build absolute volume command. status: 0x%02x",
2630 __func__, status);
2631 status = BT_STATUS_FAIL;
2632 continue;
2633 }
2634
2635 rc_transaction_t* p_transaction = NULL;
2636 bt_status_t tran_status = get_transaction(&p_transaction);
2637
2638 if (tran_status != BT_STATUS_SUCCESS || !p_transaction) {
2639 osi_free_and_reset((void**)&p_msg);
2640 BTIF_TRACE_ERROR(
2641 "%s: failed to obtain transaction details. status: 0x%02x", __func__,
2642 tran_status);
2643 status = BT_STATUS_FAIL;
2644 continue;
2645 }
2646
2647 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
2648 p_transaction->lbl);
2649 BTA_AvMetaCmd(btif_rc_cb.rc_multi_cb[idx].rc_handle, p_transaction->lbl,
2650 AVRC_CMD_CTRL, p_msg);
2651 status = BT_STATUS_SUCCESS;
2652 }
2653 return (bt_status_t)status;
2654 }
2655
2656 /***************************************************************************
2657 *
2658 * Function register_volumechange
2659 *
2660 * Description Register for volume change notification from remote side.
2661 *
2662 * Returns void
2663 *
2664 **************************************************************************/
2665
register_volumechange(uint8_t lbl,btif_rc_device_cb_t * p_dev)2666 static void register_volumechange(uint8_t lbl, btif_rc_device_cb_t* p_dev) {
2667 tAVRC_COMMAND avrc_cmd = {0};
2668 BT_HDR* p_msg = NULL;
2669 tAVRC_STS BldResp = AVRC_STS_BAD_CMD;
2670 rc_transaction_t* p_transaction = NULL;
2671
2672 BTIF_TRACE_DEBUG("%s: label: %d", __func__, lbl);
2673
2674 avrc_cmd.cmd.opcode = 0x00;
2675 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
2676 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
2677 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
2678 avrc_cmd.reg_notif.param = 0;
2679
2680 BldResp = AVRC_BldCommand(&avrc_cmd, &p_msg);
2681 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
2682 p_transaction = get_transaction_by_lbl(lbl);
2683 if (p_transaction != NULL) {
2684 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_NOTIF,
2685 p_msg);
2686 BTIF_TRACE_DEBUG("%s: BTA_AvMetaCmd called", __func__);
2687 } else {
2688 osi_free(p_msg);
2689 BTIF_TRACE_ERROR("%s: transaction not obtained with label: %d", __func__,
2690 lbl);
2691 }
2692 } else {
2693 BTIF_TRACE_ERROR("%s: failed to build command: %d", __func__, BldResp);
2694 }
2695 }
2696
2697 /***************************************************************************
2698 *
2699 * Function handle_rc_metamsg_rsp
2700 *
2701 * Description Handle RC metamessage response
2702 *
2703 * Returns void
2704 *
2705 **************************************************************************/
handle_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg,btif_rc_device_cb_t * p_dev)2706 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg,
2707 btif_rc_device_cb_t* p_dev) {
2708 tAVRC_RESPONSE avrc_response = {0};
2709 uint8_t scratch_buf[512] = {0};
2710 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2711
2712 BTIF_TRACE_DEBUG("%s: ", __func__);
2713
2714 if (AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode &&
2715 (AVRC_RSP_CHANGED == pmeta_msg->code ||
2716 AVRC_RSP_INTERIM == pmeta_msg->code ||
2717 AVRC_RSP_ACCEPT == pmeta_msg->code || AVRC_RSP_REJ == pmeta_msg->code ||
2718 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2719 status = AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf,
2720 sizeof(scratch_buf));
2721 BTIF_TRACE_DEBUG(
2722 "%s: code:%d, event ID: %d, PDU: %x, parsing status: %d, label: %d",
2723 __func__, pmeta_msg->code, avrc_response.reg_notif.event_id,
2724 avrc_response.reg_notif.pdu, status, pmeta_msg->label);
2725
2726 if (status != AVRC_STS_NO_ERROR) {
2727 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2728 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2729 p_dev->rc_vol_label == pmeta_msg->label) {
2730 p_dev->rc_vol_label = MAX_LABEL;
2731 release_transaction(p_dev->rc_vol_label);
2732 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2733 release_transaction(pmeta_msg->label);
2734 }
2735 return;
2736 }
2737
2738 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2739 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2740 p_dev->rc_vol_label != pmeta_msg->label) {
2741 // Just discard the message, if the device sends back with an incorrect
2742 // label
2743 BTIF_TRACE_DEBUG(
2744 "%s: Discarding register notification in rsp.code: %d and label: %d",
2745 __func__, pmeta_msg->code, pmeta_msg->label);
2746 return;
2747 }
2748
2749 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2750 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2751 (AVRC_RSP_REJ == pmeta_msg->code ||
2752 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2753 BTIF_TRACE_DEBUG("%s remove AbsoluteVolume feature flag.", __func__);
2754 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
2755 handle_rc_features(p_dev);
2756 return;
2757 }
2758 } else {
2759 BTIF_TRACE_DEBUG(
2760 "%s: Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not "
2761 "processing it.",
2762 __func__, pmeta_msg->code, pmeta_msg->len);
2763 return;
2764 }
2765
2766 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2767 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2768 AVRC_RSP_CHANGED == pmeta_msg->code) {
2769 /* re-register for volume change notification */
2770 // Do not re-register for rejected case, as it might get into endless loop
2771 register_volumechange(p_dev->rc_vol_label, p_dev);
2772 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2773 /* free up the label here */
2774 release_transaction(pmeta_msg->label);
2775 }
2776
2777 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
2778 __func__, dump_rc_pdu(avrc_response.pdu));
2779 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response,
2780 pmeta_msg->code, pmeta_msg->label, p_dev);
2781 }
2782
2783 /***************************************************************************
2784 *
2785 * Function iterate_supported_event_list_for_interim_rsp
2786 *
2787 * Description iterator callback function to match the event and handle
2788 * timer cleanup
2789 * Returns true to continue iterating, false to stop
2790 *
2791 **************************************************************************/
iterate_supported_event_list_for_interim_rsp(void * data,void * cb_data)2792 bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) {
2793 uint8_t* p_event_id;
2794 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
2795
2796 p_event_id = (uint8_t*)cb_data;
2797
2798 if (p_event->event_id == *p_event_id) {
2799 p_event->status = eINTERIM;
2800 return false;
2801 }
2802 return true;
2803 }
2804
2805 /***************************************************************************
2806 *
2807 * Function iterate_supported_event_list_for_timeout
2808 *
2809 * Description Iterator callback function for timeout handling.
2810 * As part of the failure handling, it releases the
2811 * transaction label and removes the event from list,
2812 * this event will not be requested again during
2813 * the lifetime of the connection.
2814 * Returns false to stop iterating, true to continue
2815 *
2816 **************************************************************************/
iterate_supported_event_list_for_timeout(void * data,void * cb_data)2817 bool iterate_supported_event_list_for_timeout(void* data, void* cb_data) {
2818 rc_context_t* cntxt = (rc_context_t*)cb_data;
2819 uint8_t label = cntxt->label & 0xFF;
2820 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(cntxt->rc_addr);
2821 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
2822
2823 if (p_event->label == label) {
2824 list_remove(p_dev->rc_supported_event_list, p_event);
2825 return false;
2826 }
2827 return true;
2828 }
2829
2830 /***************************************************************************
2831 *
2832 * Function rc_notification_interim_timout
2833 *
2834 * Description Interim response timeout handler.
2835 * Runs the iterator to check and clear the timed out event.
2836 * Proceeds to register for the unregistered events.
2837 * Returns None
2838 *
2839 **************************************************************************/
rc_notification_interim_timout(uint8_t label,btif_rc_device_cb_t * p_dev)2840 static void rc_notification_interim_timout(uint8_t label,
2841 btif_rc_device_cb_t* p_dev) {
2842 list_node_t* node;
2843 rc_context_t cntxt;
2844 memset(&cntxt, 0, sizeof(rc_context_t));
2845 cntxt.label = label;
2846 cntxt.rc_addr = p_dev->rc_addr;
2847
2848 list_foreach(p_dev->rc_supported_event_list,
2849 iterate_supported_event_list_for_timeout, &cntxt);
2850 /* Timeout happened for interim response for the registered event,
2851 * check if there are any pending for registration
2852 */
2853 node = list_begin(p_dev->rc_supported_event_list);
2854 while (node != NULL) {
2855 btif_rc_supported_event_t* p_event;
2856
2857 p_event = (btif_rc_supported_event_t*)list_node(node);
2858 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
2859 register_for_event_notification(p_event, p_dev);
2860 break;
2861 }
2862 node = list_next(node);
2863 }
2864 /* Todo. Need to initiate application settings query if this
2865 * is the last event registration.
2866 */
2867 }
2868
2869 /***************************************************************************
2870 *
2871 * Function btif_rc_status_cmd_timeout_handler
2872 *
2873 * Description RC status command timeout handler (Runs in BTIF context).
2874 * Returns None
2875 *
2876 **************************************************************************/
btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2877 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2878 char* data) {
2879 btif_rc_timer_context_t* p_context;
2880 tAVRC_RESPONSE avrc_response = {0};
2881 tBTA_AV_META_MSG meta_msg;
2882 btif_rc_device_cb_t* p_dev = NULL;
2883
2884 p_context = (btif_rc_timer_context_t*)data;
2885 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2886 p_dev = btif_rc_get_device_by_bda(p_context->rc_addr);
2887 if (p_dev == NULL) {
2888 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
2889 return;
2890 }
2891 meta_msg.rc_handle = p_dev->rc_handle;
2892
2893 switch (p_context->rc_status_cmd.pdu_id) {
2894 case AVRC_PDU_REGISTER_NOTIFICATION:
2895 rc_notification_interim_timout(p_context->rc_status_cmd.label, p_dev);
2896 break;
2897
2898 case AVRC_PDU_GET_CAPABILITIES:
2899 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2900 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2901 break;
2902
2903 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2904 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2905 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2906 break;
2907
2908 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2909 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2910 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2911 break;
2912
2913 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2914 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2915 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2916 break;
2917
2918 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2919 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2920 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2921 break;
2922
2923 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2924 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2925 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2926 break;
2927
2928 case AVRC_PDU_GET_ELEMENT_ATTR:
2929 avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT;
2930 handle_get_metadata_attr_response(&meta_msg, &avrc_response.get_attrs);
2931 break;
2932
2933 case AVRC_PDU_GET_PLAY_STATUS:
2934 avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT;
2935 handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status);
2936 break;
2937 }
2938 release_transaction(p_context->rc_status_cmd.label);
2939 }
2940
2941 /***************************************************************************
2942 *
2943 * Function btif_rc_status_cmd_timer_timeout
2944 *
2945 * Description RC status command timeout callback.
2946 * This is called from BTU context and switches to BTIF
2947 * context to handle the timeout events
2948 * Returns None
2949 *
2950 **************************************************************************/
btif_rc_status_cmd_timer_timeout(void * data)2951 static void btif_rc_status_cmd_timer_timeout(void* data) {
2952 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data;
2953
2954 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0, (char*)p_data,
2955 sizeof(btif_rc_timer_context_t), NULL);
2956 }
2957
2958 /***************************************************************************
2959 *
2960 * Function btif_rc_control_cmd_timeout_handler
2961 *
2962 * Description RC control command timeout handler (Runs in BTIF context).
2963 * Returns None
2964 *
2965 **************************************************************************/
btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2966 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2967 char* data) {
2968 btif_rc_timer_context_t* p_context = (btif_rc_timer_context_t*)data;
2969 tAVRC_RESPONSE avrc_response = {0};
2970 tBTA_AV_META_MSG meta_msg;
2971 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(p_context->rc_addr);
2972 if (p_dev == NULL) {
2973 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
2974 return;
2975 }
2976
2977 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2978 meta_msg.rc_handle = p_dev->rc_handle;
2979
2980 switch (p_context->rc_control_cmd.pdu_id) {
2981 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2982 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2983 handle_set_app_attr_val_response(&meta_msg, &avrc_response.set_app_val);
2984 break;
2985 }
2986 release_transaction(p_context->rc_control_cmd.label);
2987 }
2988
2989 /***************************************************************************
2990 *
2991 * Function btif_rc_control_cmd_timer_timeout
2992 *
2993 * Description RC control command timeout callback.
2994 * This is called from BTU context and switches to BTIF
2995 * context to handle the timeout events
2996 * Returns None
2997 *
2998 **************************************************************************/
btif_rc_control_cmd_timer_timeout(void * data)2999 static void btif_rc_control_cmd_timer_timeout(void* data) {
3000 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data;
3001
3002 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0, (char*)p_data,
3003 sizeof(btif_rc_timer_context_t), NULL);
3004 }
3005
3006 /***************************************************************************
3007 *
3008 * Function register_for_event_notification
3009 *
3010 * Description Helper function registering notification events
3011 * sets an interim response timeout to handle if the remote
3012 * does not respond.
3013 * Returns None
3014 *
3015 **************************************************************************/
register_for_event_notification(btif_rc_supported_event_t * p_event,btif_rc_device_cb_t * p_dev)3016 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
3017 btif_rc_device_cb_t* p_dev) {
3018 rc_transaction_t* p_transaction = NULL;
3019 bt_status_t status = get_transaction(&p_transaction);
3020 if (status != BT_STATUS_SUCCESS) {
3021 BTIF_TRACE_ERROR("%s: no more transaction labels: %d", __func__, status);
3022 return;
3023 }
3024 // interval is only valid for AVRC_EVT_PLAY_POS_CHANGED
3025 uint32_t interval_in_seconds = 0;
3026 if (p_event->event_id == AVRC_EVT_PLAY_POS_CHANGED) {
3027 interval_in_seconds = 2;
3028 }
3029 status = register_notification_cmd(p_transaction->lbl, p_event->event_id,
3030 interval_in_seconds, p_dev);
3031 if (status != BT_STATUS_SUCCESS) {
3032 BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__,
3033 status);
3034 release_transaction(p_transaction->lbl);
3035 return;
3036 }
3037
3038 btif_rc_timer_context_t* p_context = &p_transaction->txn_timer_context;
3039 p_event->label = p_transaction->lbl;
3040 p_event->status = eREGISTERED;
3041 p_context->rc_status_cmd.label = p_transaction->lbl;
3042 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
3043 p_context->rc_addr = p_dev->rc_addr;
3044
3045 alarm_free(p_transaction->txn_timer);
3046 p_transaction->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
3047 alarm_set_on_mloop(p_transaction->txn_timer, BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
3048 btif_rc_status_cmd_timer_timeout, p_context);
3049 }
3050
start_status_command_timer(uint8_t pdu_id,rc_transaction_t * p_txn,btif_rc_device_cb_t * p_dev)3051 static void start_status_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn,
3052 btif_rc_device_cb_t* p_dev) {
3053 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context;
3054 p_context->rc_status_cmd.label = p_txn->lbl;
3055 p_context->rc_status_cmd.pdu_id = pdu_id;
3056 p_context->rc_addr = p_dev->rc_addr;
3057
3058 alarm_free(p_txn->txn_timer);
3059 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
3060 alarm_set_on_mloop(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
3061 btif_rc_status_cmd_timer_timeout, p_context);
3062 }
3063
start_control_command_timer(uint8_t pdu_id,rc_transaction_t * p_txn,btif_rc_device_cb_t * p_dev)3064 static void start_control_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn,
3065 btif_rc_device_cb_t* p_dev) {
3066 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context;
3067 p_context->rc_control_cmd.label = p_txn->lbl;
3068 p_context->rc_control_cmd.pdu_id = pdu_id;
3069 p_context->rc_addr = p_dev->rc_addr;
3070
3071 alarm_free(p_txn->txn_timer);
3072 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
3073 alarm_set_on_mloop(p_txn->txn_timer, BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
3074 btif_rc_control_cmd_timer_timeout, p_context);
3075 }
3076
build_and_send_vendor_cmd(tAVRC_COMMAND * avrc_cmd,tBTA_AV_CODE cmd_code,btif_rc_device_cb_t * p_dev)3077 bt_status_t build_and_send_vendor_cmd(tAVRC_COMMAND* avrc_cmd,
3078 tBTA_AV_CODE cmd_code,
3079 btif_rc_device_cb_t* p_dev) {
3080 rc_transaction_t* p_transaction = NULL;
3081 bt_status_t tran_status = get_transaction(&p_transaction);
3082 if (BT_STATUS_SUCCESS != tran_status) return BT_STATUS_FAIL;
3083
3084 BT_HDR* p_msg = NULL;
3085 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
3086 if (status == AVRC_STS_NO_ERROR && p_msg != NULL) {
3087 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
3088 BTIF_TRACE_DEBUG("%s: %s msgreq being sent out with label: %d", __func__,
3089 dump_rc_pdu(avrc_cmd->pdu), p_transaction->lbl);
3090 BTA_AvVendorCmd(p_dev->rc_handle, p_transaction->lbl, cmd_code, data_start,
3091 p_msg->len);
3092 status = BT_STATUS_SUCCESS;
3093 if (cmd_code == AVRC_CMD_STATUS) {
3094 start_status_command_timer(avrc_cmd->pdu, p_transaction, p_dev);
3095 } else if (cmd_code == AVRC_CMD_CTRL) {
3096 start_control_command_timer(avrc_cmd->pdu, p_transaction, p_dev);
3097 }
3098 } else {
3099 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
3100 status);
3101 }
3102 osi_free(p_msg);
3103 return (bt_status_t)status;
3104 }
3105
3106 /***************************************************************************
3107 *
3108 * Function send_browsing_command
3109 *
3110 * Description Send a command to a device on the browsing channel
3111 *
3112 * Parameters avrc_cmd: The command you're sending
3113 * p_dev: Device control block
3114 *
3115 * Returns BT_STATUS_SUCCESS if command is issued successfully
3116 * otherwise BT_STATUS_FAIL
3117 *
3118 **************************************************************************/
build_and_send_browsing_cmd(tAVRC_COMMAND * avrc_cmd,btif_rc_device_cb_t * p_dev)3119 static bt_status_t build_and_send_browsing_cmd(tAVRC_COMMAND* avrc_cmd,
3120 btif_rc_device_cb_t* p_dev) {
3121 BT_HDR* p_msg = NULL;
3122 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
3123 if (status != AVRC_STS_NO_ERROR) {
3124 BTIF_TRACE_ERROR("%s: failed to build command status %d", __func__, status);
3125 return BT_STATUS_FAIL;
3126 }
3127
3128 rc_transaction_t* p_transaction = NULL;
3129 bt_status_t tran_status = get_transaction(&p_transaction);
3130
3131 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
3132 osi_free(p_msg);
3133 BTIF_TRACE_ERROR("%s: failed to obtain txn details. status: 0x%02x",
3134 __func__, tran_status);
3135 return BT_STATUS_FAIL;
3136 }
3137
3138 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
3139 p_transaction->lbl);
3140 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
3141 return BT_STATUS_SUCCESS;
3142 }
3143
3144 /***************************************************************************
3145 *
3146 * Function handle_get_capability_response
3147 *
3148 * Description Handles the get_cap_response to populate company id info
3149 * and query the supported events.
3150 * Initiates Notification registration for events supported
3151 * Returns None
3152 *
3153 **************************************************************************/
handle_get_capability_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CAPS_RSP * p_rsp)3154 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg,
3155 tAVRC_GET_CAPS_RSP* p_rsp) {
3156 int xx = 0;
3157 btif_rc_device_cb_t* p_dev =
3158 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3159
3160 /* Todo: Do we need to retry on command timeout */
3161 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3162 BTIF_TRACE_ERROR("%s: Error capability response: 0x%02X", __func__,
3163 p_rsp->status);
3164 return;
3165 }
3166
3167 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
3168 btif_rc_supported_event_t* p_event;
3169
3170 /* Todo: Check if list can be active when we hit here */
3171 p_dev->rc_supported_event_list = list_new(osi_free);
3172 for (xx = 0; xx < p_rsp->count; xx++) {
3173 /* Skip registering for Play position change notification */
3174 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) ||
3175 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) ||
3176 (p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_POS_CHANGED) ||
3177 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) ||
3178 (p_rsp->param.event_id[xx] == AVRC_EVT_NOW_PLAYING_CHANGE) ||
3179 (p_rsp->param.event_id[xx] == AVRC_EVT_ADDR_PLAYER_CHANGE) ||
3180 (p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE) ||
3181 (p_rsp->param.event_id[xx] == AVRC_EVT_AVAL_PLAYERS_CHANGE)) {
3182 p_event = (btif_rc_supported_event_t*)osi_malloc(
3183 sizeof(btif_rc_supported_event_t));
3184 p_event->event_id = p_rsp->param.event_id[xx];
3185 p_event->status = eNOT_REGISTERED;
3186 list_append(p_dev->rc_supported_event_list, p_event);
3187 }
3188 }
3189
3190 // On occasion a remote device can intermittently send a poorly configured
3191 // packet with 0 capabilities. This check ensures the stack does not crash.
3192 // Typically the remote device will send a proper packet in the future and
3193 // continue operation.
3194 if (list_is_empty(p_dev->rc_supported_event_list)) {
3195 return;
3196 }
3197
3198 p_event =
3199 (btif_rc_supported_event_t*)list_front(p_dev->rc_supported_event_list);
3200 if (p_event != NULL) {
3201 register_for_event_notification(p_event, p_dev);
3202 }
3203 } else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
3204 getcapabilities_cmd(AVRC_CAP_EVENTS_SUPPORTED, p_dev);
3205 BTIF_TRACE_EVENT("%s: AVRC_CAP_COMPANY_ID: ", __func__);
3206 for (xx = 0; xx < p_rsp->count; xx++) {
3207 BTIF_TRACE_EVENT("%s: company_id: %d", __func__,
3208 p_rsp->param.company_id[xx]);
3209 }
3210 }
3211 }
3212
rc_is_track_id_valid(tAVRC_UID uid)3213 bool rc_is_track_id_valid(tAVRC_UID uid) {
3214 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3215
3216 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0) {
3217 return false;
3218 } else {
3219 return true;
3220 }
3221 }
3222
3223 /***************************************************************************
3224 *
3225 * Function handle_notification_response
3226 *
3227 * Description Main handler for notification responses to registered events
3228 * 1. Register for unregistered event(in interim response path)
3229 * 2. After registering for all supported events, start
3230 * retrieving application settings and values
3231 * 3. Reregister for events on getting changed response
3232 * 4. Run play status timer for getting position when the
3233 * status changes to playing
3234 * 5. Get the Media details when the track change happens
3235 * or track change interim response is received with
3236 * valid track id
3237 * 6. HAL callback for play status change and application
3238 * setting change
3239 * Returns None
3240 *
3241 **************************************************************************/
handle_notification_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_REG_NOTIF_RSP * p_rsp)3242 static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
3243 tAVRC_REG_NOTIF_RSP* p_rsp) {
3244 btif_rc_device_cb_t* p_dev =
3245 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3246
3247 if (p_dev == NULL) {
3248 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3249 return;
3250 }
3251
3252 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
3253 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
3254
3255 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
3256 btif_rc_supported_event_t* p_event;
3257 list_node_t* node;
3258
3259 BTIF_TRACE_DEBUG("%s: Interim response: 0x%2X ", __func__, p_rsp->event_id);
3260 switch (p_rsp->event_id) {
3261 case AVRC_EVT_PLAY_STATUS_CHANGE:
3262 get_play_status_cmd(p_dev);
3263 do_in_jni_thread(
3264 FROM_HERE,
3265 base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb,
3266 p_dev->rc_addr,
3267 (btrc_play_status_t)p_rsp->param.play_status));
3268 break;
3269
3270 case AVRC_EVT_TRACK_CHANGE:
3271 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3272 break;
3273 } else {
3274 uint8_t* p_data = p_rsp->param.track;
3275 BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
3276 get_play_status_cmd(p_dev);
3277 get_metadata_attribute_cmd(attr_list_size, attr_list,
3278 p_dev);
3279 }
3280 break;
3281
3282 case AVRC_EVT_APP_SETTING_CHANGE:
3283 break;
3284
3285 case AVRC_EVT_NOW_PLAYING_CHANGE:
3286 do_in_jni_thread(
3287 FROM_HERE,
3288 base::Bind(bt_rc_ctrl_callbacks->now_playing_contents_changed_cb,
3289 p_dev->rc_addr));
3290 break;
3291
3292 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3293 BTIF_TRACE_DEBUG("%s: AVRC_EVT_AVAL_PLAYERS_CHANGE", __func__);
3294 do_in_jni_thread(
3295 FROM_HERE,
3296 base::Bind(bt_rc_ctrl_callbacks->available_player_changed_cb,
3297 p_dev->rc_addr));
3298 break;
3299
3300 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3301 do_in_jni_thread(
3302 FROM_HERE,
3303 base::Bind(bt_rc_ctrl_callbacks->addressed_player_changed_cb,
3304 p_dev->rc_addr, p_rsp->param.addr_player.player_id));
3305 break;
3306
3307 case AVRC_EVT_PLAY_POS_CHANGED:
3308 do_in_jni_thread(FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb, p_dev->rc_addr, 0,
3309 p_rsp->param.play_pos));
3310
3311 break;
3312 case AVRC_EVT_UIDS_CHANGE:
3313 break;
3314
3315 case AVRC_EVT_TRACK_REACHED_END:
3316 case AVRC_EVT_TRACK_REACHED_START:
3317 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3318 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3319 default:
3320 BTIF_TRACE_ERROR("%s: Unhandled interim response: 0x%2X", __func__,
3321 p_rsp->event_id);
3322 return;
3323 }
3324
3325 list_foreach(p_dev->rc_supported_event_list,
3326 iterate_supported_event_list_for_interim_rsp,
3327 &p_rsp->event_id);
3328
3329 node = list_begin(p_dev->rc_supported_event_list);
3330
3331 while (node != NULL) {
3332 p_event = (btif_rc_supported_event_t*)list_node(node);
3333 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
3334 register_for_event_notification(p_event, p_dev);
3335 break;
3336 }
3337 node = list_next(node);
3338 p_event = NULL;
3339 }
3340 /* Registered for all events, we can request application settings */
3341 if (p_event == NULL && !p_dev->rc_app_settings.query_started) {
3342 /* we need to do this only if remote TG supports
3343 * player application settings
3344 */
3345 p_dev->rc_app_settings.query_started = true;
3346 if (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING) {
3347 list_player_app_setting_attrib_cmd(p_dev);
3348 } else {
3349 BTIF_TRACE_DEBUG("%s: App setting not supported, complete procedure",
3350 __func__);
3351 rc_ctrl_procedure_complete(p_dev);
3352 }
3353 }
3354 } else if (pmeta_msg->code == AVRC_RSP_CHANGED) {
3355 btif_rc_supported_event_t* p_event;
3356 list_node_t* node;
3357
3358 BTIF_TRACE_DEBUG("%s: Notification completed: 0x%2X ", __func__,
3359 p_rsp->event_id);
3360
3361 node = list_begin(p_dev->rc_supported_event_list);
3362
3363 while (node != NULL) {
3364 p_event = (btif_rc_supported_event_t*)list_node(node);
3365 if (p_event != NULL && p_event->event_id == p_rsp->event_id) {
3366 p_event->status = eNOT_REGISTERED;
3367 register_for_event_notification(p_event, p_dev);
3368 break;
3369 }
3370 node = list_next(node);
3371 }
3372
3373 switch (p_rsp->event_id) {
3374 case AVRC_EVT_PLAY_STATUS_CHANGE:
3375 /* Start timer to get play status periodically
3376 * if the play state is playing.
3377 */
3378 do_in_jni_thread(
3379 FROM_HERE,
3380 base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb,
3381 p_dev->rc_addr,
3382 (btrc_play_status_t)p_rsp->param.play_status));
3383
3384 break;
3385
3386 case AVRC_EVT_TRACK_CHANGE:
3387 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3388 break;
3389 }
3390 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
3391 break;
3392
3393 case AVRC_EVT_APP_SETTING_CHANGE: {
3394 btrc_player_settings_t app_settings;
3395 uint16_t xx;
3396
3397 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
3398 for (xx = 0; xx < app_settings.num_attr; xx++) {
3399 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
3400 app_settings.attr_values[xx] =
3401 p_rsp->param.player_setting.attr_value[xx];
3402 }
3403 do_in_jni_thread(
3404 FROM_HERE,
3405 base::Bind(
3406 bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
3407 p_dev->rc_addr, app_settings));
3408 } break;
3409
3410 case AVRC_EVT_NOW_PLAYING_CHANGE:
3411 break;
3412
3413 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3414 break;
3415
3416 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3417 break;
3418
3419 case AVRC_EVT_PLAY_POS_CHANGED:
3420 // handle on interim
3421 break;
3422
3423 case AVRC_EVT_UIDS_CHANGE:
3424 break;
3425
3426 case AVRC_EVT_TRACK_REACHED_END:
3427 case AVRC_EVT_TRACK_REACHED_START:
3428 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3429 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3430 default:
3431 BTIF_TRACE_ERROR("%s: Unhandled completion response: 0x%2X", __func__,
3432 p_rsp->event_id);
3433 return;
3434 }
3435 }
3436 }
3437
3438 /***************************************************************************
3439 *
3440 * Function handle_app_attr_response
3441 *
3442 * Description handles the the application attributes response and
3443 * initiates procedure to fetch the attribute values
3444 * Returns None
3445 *
3446 **************************************************************************/
handle_app_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_ATTR_RSP * p_rsp)3447 static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg,
3448 tAVRC_LIST_APP_ATTR_RSP* p_rsp) {
3449 uint8_t xx;
3450 btif_rc_device_cb_t* p_dev =
3451 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3452
3453 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3454 BTIF_TRACE_ERROR("%s: Error getting Player application settings: 0x%2X",
3455 __func__, p_rsp->status);
3456 rc_ctrl_procedure_complete(p_dev);
3457 return;
3458 }
3459 p_dev->rc_app_settings.num_attrs = 0;
3460 p_dev->rc_app_settings.num_ext_attrs = 0;
3461
3462 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3463 uint8_t st_index;
3464
3465 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT) {
3466 st_index = p_dev->rc_app_settings.num_ext_attrs;
3467 p_dev->rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
3468 p_dev->rc_app_settings.num_ext_attrs++;
3469 } else {
3470 st_index = p_dev->rc_app_settings.num_attrs;
3471 p_dev->rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
3472 p_dev->rc_app_settings.num_attrs++;
3473 }
3474 }
3475 p_dev->rc_app_settings.attr_index = 0;
3476 p_dev->rc_app_settings.ext_attr_index = 0;
3477 p_dev->rc_app_settings.ext_val_index = 0;
3478 if (p_rsp->num_attr) {
3479 list_player_app_setting_value_cmd(p_dev->rc_app_settings.attrs[0].attr_id,
3480 p_dev);
3481 } else {
3482 BTIF_TRACE_ERROR("%s: No Player application settings found", __func__);
3483 }
3484 }
3485
3486 /***************************************************************************
3487 *
3488 * Function handle_app_val_response
3489 *
3490 * Description handles the the attributes value response and if extended
3491 * menu is available, it initiates query for the attribute
3492 * text. If not, it initiates procedure to get the current
3493 * attribute values and calls the HAL callback for provding
3494 * application settings information.
3495 * Returns None
3496 *
3497 **************************************************************************/
handle_app_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_VALUES_RSP * p_rsp)3498 static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg,
3499 tAVRC_LIST_APP_VALUES_RSP* p_rsp) {
3500 uint8_t xx, attr_index;
3501 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3502 btif_rc_player_app_settings_t* p_app_settings;
3503 btif_rc_device_cb_t* p_dev =
3504 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3505
3506 /* Todo: Do we need to retry on command timeout */
3507 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3508 BTIF_TRACE_ERROR("%s: Error fetching attribute values: 0x%02X", __func__,
3509 p_rsp->status);
3510 return;
3511 }
3512
3513 p_app_settings = &p_dev->rc_app_settings;
3514
3515 if (p_app_settings->attr_index < p_app_settings->num_attrs) {
3516 attr_index = p_app_settings->attr_index;
3517 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
3518 for (xx = 0; xx < p_rsp->num_val; xx++) {
3519 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
3520 }
3521 attr_index++;
3522 p_app_settings->attr_index++;
3523 if (attr_index < p_app_settings->num_attrs) {
3524 list_player_app_setting_value_cmd(
3525 p_app_settings->attrs[p_app_settings->attr_index].attr_id, p_dev);
3526 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3527 attr_index = 0;
3528 p_app_settings->ext_attr_index = 0;
3529 list_player_app_setting_value_cmd(
3530 p_app_settings->ext_attrs[attr_index].attr_id, p_dev);
3531 } else {
3532 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3533 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3534 }
3535 get_player_app_setting_cmd(p_app_settings->num_attrs, attrs, p_dev);
3536 do_in_jni_thread(
3537 FROM_HERE,
3538 base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3539 p_dev->rc_addr, p_app_settings->num_attrs,
3540 p_app_settings->attrs, 0, nullptr));
3541 }
3542 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3543 attr_index = p_app_settings->ext_attr_index;
3544 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
3545 for (xx = 0; xx < p_rsp->num_val; xx++) {
3546 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val =
3547 p_rsp->vals[xx];
3548 }
3549 attr_index++;
3550 p_app_settings->ext_attr_index++;
3551 if (attr_index < p_app_settings->num_ext_attrs) {
3552 list_player_app_setting_value_cmd(
3553 p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id,
3554 p_dev);
3555 } else {
3556 uint8_t attr[AVRC_MAX_APP_ATTR_SIZE];
3557
3558 for (uint8_t xx = 0; xx < p_app_settings->num_ext_attrs; xx++) {
3559 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
3560 }
3561 get_player_app_setting_attr_text_cmd(attr, p_app_settings->num_ext_attrs,
3562 p_dev);
3563 }
3564 }
3565 }
3566
3567 /***************************************************************************
3568 *
3569 * Function handle_app_cur_val_response
3570 *
3571 * Description handles the the get attributes value response.
3572 *
3573 * Returns None
3574 *
3575 **************************************************************************/
handle_app_cur_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp)3576 static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg,
3577 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp) {
3578 btrc_player_settings_t app_settings;
3579 uint16_t xx;
3580 btif_rc_device_cb_t* p_dev = NULL;
3581
3582 /* Todo: Do we need to retry on command timeout */
3583 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3584 BTIF_TRACE_ERROR("%s: Error fetching current settings: 0x%02X", __func__,
3585 p_rsp->status);
3586 return;
3587 }
3588 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3589 if (p_dev == NULL) {
3590 BTIF_TRACE_ERROR("%s: Error in getting Device Address", __func__);
3591 osi_free_and_reset((void**)&p_rsp->p_vals);
3592 return;
3593 }
3594
3595
3596 app_settings.num_attr = p_rsp->num_val;
3597
3598 if (app_settings.num_attr > BTRC_MAX_APP_SETTINGS) {
3599 android_errorWriteLog(0x534e4554, "73824150");
3600 app_settings.num_attr = BTRC_MAX_APP_SETTINGS;
3601 }
3602
3603 for (xx = 0; xx < app_settings.num_attr; xx++) {
3604 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
3605 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
3606 }
3607
3608 do_in_jni_thread(
3609 FROM_HERE,
3610 base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
3611 p_dev->rc_addr, app_settings));
3612 /* Application settings are fetched only once for initial values
3613 * initiate anything that follows after RC procedure.
3614 * Defer it if browsing is supported till players query
3615 */
3616 rc_ctrl_procedure_complete(p_dev);
3617 osi_free_and_reset((void**)&p_rsp->p_vals);
3618 }
3619
3620 /***************************************************************************
3621 *
3622 * Function handle_app_attr_txt_response
3623 *
3624 * Description handles the the get attributes text response, if fails
3625 * calls HAL callback with just normal settings and initiates
3626 * query for current settings else initiates query for value
3627 * text
3628 * Returns None
3629 *
3630 **************************************************************************/
handle_app_attr_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3631 static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg,
3632 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3633 uint8_t xx;
3634 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3635 btif_rc_player_app_settings_t* p_app_settings;
3636 btif_rc_device_cb_t* p_dev =
3637 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3638
3639 if (p_dev == NULL) {
3640 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3641 return;
3642 }
3643
3644 p_app_settings = &p_dev->rc_app_settings;
3645
3646 /* Todo: Do we need to retry on command timeout */
3647 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3648 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3649
3650 BTIF_TRACE_ERROR("%s: Error fetching attribute text: 0x%02X", __func__,
3651 p_rsp->status);
3652 /* Not able to fetch Text for extended Menu, skip the process
3653 * and cleanup used memory. Proceed to get the current settings
3654 * for standard attributes.
3655 */
3656 p_app_settings->num_ext_attrs = 0;
3657 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3658 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3659 }
3660 p_app_settings->ext_attr_index = 0;
3661
3662 if (p_dev) {
3663 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3664 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3665 }
3666
3667 do_in_jni_thread(
3668 FROM_HERE,
3669 base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3670 p_dev->rc_addr, p_app_settings->num_attrs,
3671 p_app_settings->attrs, 0, nullptr));
3672 get_player_app_setting_cmd(xx, attrs, p_dev);
3673 }
3674 return;
3675 }
3676
3677 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3678 uint8_t x;
3679 for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
3680 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id) {
3681 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3682 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
3683 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
3684 break;
3685 }
3686 }
3687 }
3688
3689 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++) {
3690 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
3691 }
3692 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3693 }
3694
3695 /***************************************************************************
3696 *
3697 * Function handle_app_attr_val_txt_response
3698 *
3699 * Description handles the the get attributes value text response, if fails
3700 * calls HAL callback with just normal settings and initiates
3701 * query for current settings
3702 * Returns None
3703 *
3704 **************************************************************************/
handle_app_attr_val_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3705 static void handle_app_attr_val_txt_response(
3706 tBTA_AV_META_MSG* pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3707 uint8_t xx, attr_index;
3708 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3709 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3710 btif_rc_player_app_settings_t* p_app_settings;
3711 btif_rc_device_cb_t* p_dev =
3712 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3713
3714 if (p_dev == NULL) {
3715 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3716 return;
3717 }
3718
3719 p_app_settings = &p_dev->rc_app_settings;
3720
3721 /* Todo: Do we need to retry on command timeout */
3722 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3723 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3724
3725 BTIF_TRACE_ERROR("%s: Error fetching attribute value text: 0x%02X",
3726 __func__, p_rsp->status);
3727
3728 /* Not able to fetch Text for extended Menu, skip the process
3729 * and cleanup used memory. Proceed to get the current settings
3730 * for standard attributes.
3731 */
3732 p_app_settings->num_ext_attrs = 0;
3733 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3734 int x;
3735 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3736
3737 for (x = 0; x < p_ext_attr->num_val; x++)
3738 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3739 p_ext_attr->num_val = 0;
3740 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3741 }
3742 p_app_settings->ext_attr_index = 0;
3743
3744 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3745 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3746 }
3747 do_in_jni_thread(
3748 FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3749 p_dev->rc_addr, p_app_settings->num_attrs,
3750 p_app_settings->attrs, 0, nullptr));
3751
3752 get_player_app_setting_cmd(xx, attrs, p_dev);
3753 return;
3754 }
3755
3756 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3757 uint8_t x;
3758 btrc_player_app_ext_attr_t* p_ext_attr;
3759 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
3760 for (x = 0; x < p_rsp->num_attr; x++) {
3761 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id) {
3762 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3763 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
3764 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
3765 break;
3766 }
3767 }
3768 }
3769 p_app_settings->ext_val_index++;
3770
3771 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs) {
3772 attr_index = p_app_settings->ext_val_index;
3773 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++) {
3774 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
3775 }
3776 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3777 } else {
3778 uint8_t x;
3779
3780 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3781 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3782 }
3783 for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
3784 attrs[xx + x] = p_app_settings->ext_attrs[x].attr_id;
3785 }
3786 do_in_jni_thread(
3787 FROM_HERE,
3788 base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
3789 p_dev->rc_addr, p_app_settings->num_attrs,
3790 p_app_settings->attrs, p_app_settings->num_ext_attrs,
3791 p_app_settings->ext_attrs));
3792 get_player_app_setting_cmd(xx + x, attrs, p_dev);
3793
3794 /* Free the application settings information after sending to
3795 * application.
3796 */
3797 do_in_jni_thread(FROM_HERE, base::Bind(cleanup_app_attr_val_txt_response,
3798 p_app_settings));
3799 p_app_settings->num_attrs = 0;
3800 }
3801 }
3802
3803 /***************************************************************************
3804 *
3805 * Function cleanup_app_attr_val_txt_response
3806 *
3807 * Description Frees the memory that was allocated for reporting player
3808 * application settings.
3809 * Returns None
3810 **************************************************************************/
cleanup_app_attr_val_txt_response(btif_rc_player_app_settings_t * p_app_settings)3811 static void cleanup_app_attr_val_txt_response(
3812 btif_rc_player_app_settings_t* p_app_settings) {
3813 for (uint8_t xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3814 int x;
3815 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3816 for (x = 0; x < p_ext_attr->num_val; x++) {
3817 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3818 }
3819 p_ext_attr->num_val = 0;
3820 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3821 }
3822 }
3823
3824 /***************************************************************************
3825 *
3826 * Function handle_set_app_attr_val_response
3827 *
3828 * Description handles the the set attributes value response, if fails
3829 * calls HAL callback to indicate the failure
3830 * Returns None
3831 *
3832 **************************************************************************/
handle_set_app_attr_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)3833 static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
3834 tAVRC_RSP* p_rsp) {
3835 uint8_t accepted = 0;
3836 btif_rc_device_cb_t* p_dev =
3837 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3838
3839 if (p_dev == NULL) {
3840 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3841 return;
3842 }
3843
3844
3845 /* For timeout pmeta_msg will be NULL, else we need to
3846 * check if this is accepted by TG
3847 */
3848 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT)) {
3849 accepted = 1;
3850 }
3851 do_in_jni_thread(FROM_HERE,
3852 base::Bind(bt_rc_ctrl_callbacks->setplayerappsetting_rsp_cb,
3853 p_dev->rc_addr, accepted));
3854 }
3855
3856 /***************************************************************************
3857 *
3858 * Function handle_get_metadata_attr_response
3859 *
3860 * Description handles the the element attributes response, calls
3861 * HAL callback to update track change information.
3862 * Returns None
3863 *
3864 **************************************************************************/
handle_get_metadata_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ATTRS_RSP * p_rsp)3865 static void handle_get_metadata_attr_response(tBTA_AV_META_MSG* pmeta_msg,
3866 tAVRC_GET_ATTRS_RSP* p_rsp) {
3867 btif_rc_device_cb_t* p_dev =
3868 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3869
3870 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3871 size_t buf_size = p_rsp->num_attrs * sizeof(btrc_element_attr_val_t);
3872 btrc_element_attr_val_t* p_attr =
3873 (btrc_element_attr_val_t*)osi_calloc(buf_size);
3874
3875 if (p_dev == NULL) {
3876 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3877 return;
3878 }
3879
3880
3881 for (int i = 0; i < p_rsp->num_attrs; i++) {
3882 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3883 /* Todo. Legth limit check to include null */
3884 if (p_rsp->p_attrs[i].name.str_len && p_rsp->p_attrs[i].name.p_str) {
3885 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3886 p_rsp->p_attrs[i].name.str_len);
3887 osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str);
3888 }
3889 }
3890 do_in_jni_thread(FROM_HERE,
3891 base::Bind(bt_rc_ctrl_callbacks->track_changed_cb,
3892 p_dev->rc_addr, p_rsp->num_attrs, p_attr));
3893 do_in_jni_thread(FROM_HERE, base::Bind(osi_free, p_attr));
3894 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3895 /* Retry for timeout case, this covers error handling
3896 * for continuation failure also.
3897 */
3898 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
3899 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
3900 get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
3901 } else {
3902 BTIF_TRACE_ERROR("%s: Error in get element attr procedure: %d", __func__,
3903 p_rsp->status);
3904 }
3905 }
3906
3907 /***************************************************************************
3908 *
3909 * Function handle_get_playstatus_response
3910 *
3911 * Description handles the the play status response, calls
3912 * HAL callback to update play position.
3913 * Returns None
3914 *
3915 **************************************************************************/
handle_get_playstatus_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_PLAY_STATUS_RSP * p_rsp)3916 static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
3917 tAVRC_GET_PLAY_STATUS_RSP* p_rsp) {
3918
3919 btif_rc_device_cb_t* p_dev =
3920 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3921
3922 if (p_dev == NULL) {
3923 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3924 return;
3925 }
3926
3927
3928 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3929 do_in_jni_thread(
3930 FROM_HERE,
3931 base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb, p_dev->rc_addr,
3932 (btrc_play_status_t)p_rsp->play_status));
3933 do_in_jni_thread(
3934 FROM_HERE,
3935 base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb,
3936 p_dev->rc_addr, p_rsp->song_len, p_rsp->song_pos));
3937 } else {
3938 BTIF_TRACE_ERROR("%s: Error in get play status procedure: %d", __func__,
3939 p_rsp->status);
3940 }
3941 }
3942
3943 /***************************************************************************
3944 *
3945 * Function handle_set_addressed_player_response
3946 *
3947 * Description handles the the set addressed player response, calls
3948 * HAL callback
3949 * Returns None
3950 *
3951 **************************************************************************/
handle_set_addressed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)3952 static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg,
3953 tAVRC_RSP* p_rsp) {
3954
3955 btif_rc_device_cb_t* p_dev =
3956 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3957
3958 if (p_dev == NULL) {
3959 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3960 return;
3961 }
3962
3963
3964 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3965 do_in_jni_thread(FROM_HERE,
3966 base::Bind(bt_rc_ctrl_callbacks->set_addressed_player_cb,
3967 p_dev->rc_addr, p_rsp->status));
3968 } else {
3969 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d", __func__,
3970 p_rsp->status);
3971 }
3972 }
3973
3974 /***************************************************************************
3975 *
3976 * Function handle_get_folder_items_response
3977 *
3978 * Description handles the the get folder items response, calls
3979 * HAL callback to send the folder items.
3980 * Returns None
3981 *
3982 **************************************************************************/
handle_get_folder_items_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ITEMS_RSP * p_rsp)3983 static void handle_get_folder_items_response(tBTA_AV_META_MSG* pmeta_msg,
3984 tAVRC_GET_ITEMS_RSP* p_rsp) {
3985 btif_rc_device_cb_t* p_dev =
3986 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3987
3988 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3989 /* Convert the internal folder listing into a response that can
3990 * be passed onto JNI via HAL_CBACK
3991 */
3992 uint8_t item_count = p_rsp->item_count;
3993 btrc_folder_items_t* btrc_items = (btrc_folder_items_t*)osi_malloc(
3994 sizeof(btrc_folder_items_t) * item_count);
3995 for (uint8_t i = 0; i < item_count; i++) {
3996 const tAVRC_ITEM* avrc_item = &(p_rsp->p_item_list[i]);
3997 btrc_folder_items_t* btrc_item = &(btrc_items[i]);
3998 BTIF_TRACE_DEBUG("%s folder item type %d", __func__,
3999 avrc_item->item_type);
4000 switch (avrc_item->item_type) {
4001 case AVRC_ITEM_MEDIA:
4002 BTIF_TRACE_DEBUG("%s setting type to %d", __func__, BTRC_ITEM_MEDIA);
4003 /* Allocate Space for Attributes */
4004 btrc_item->media.num_attrs = avrc_item->u.media.attr_count;
4005 btrc_item->media.p_attrs = (btrc_element_attr_val_t*)osi_malloc(
4006 btrc_item->media.num_attrs * sizeof(btrc_element_attr_val_t));
4007 get_folder_item_type_media(avrc_item, btrc_item);
4008 break;
4009
4010 case AVRC_ITEM_FOLDER:
4011 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_FOLDER", __func__);
4012 get_folder_item_type_folder(avrc_item, btrc_item);
4013 break;
4014
4015 case AVRC_ITEM_PLAYER:
4016 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_PLAYER", __func__);
4017 get_folder_item_type_player(avrc_item, btrc_item);
4018 break;
4019
4020 default:
4021 BTIF_TRACE_ERROR("%s cannot understand folder item type %d", __func__,
4022 avrc_item->item_type);
4023 }
4024 }
4025
4026 do_in_jni_thread(
4027 FROM_HERE,
4028 base::Bind(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
4029 BTRC_STS_NO_ERROR,
4030 /* We want to make the ownership explicit in native */
4031 btrc_items, item_count));
4032
4033 if (item_count > 0) {
4034 if (btrc_items[0].item_type == AVRC_ITEM_PLAYER &&
4035 (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING)) {
4036 list_player_app_setting_attrib_cmd(p_dev);
4037 }
4038 }
4039 /* Release the memory block for items and attributes allocated here.
4040 * Since the executor for do_in_jni_thread is a Single Thread Task Runner it
4041 * is okay to queue up the cleanup of btrc_items */
4042 do_in_jni_thread(FROM_HERE, base::Bind(cleanup_btrc_folder_items,
4043 btrc_items, item_count));
4044
4045 BTIF_TRACE_DEBUG("%s get_folder_items_cb sent to JNI thread", __func__);
4046 } else {
4047 BTIF_TRACE_ERROR("%s: Error %d", __func__, p_rsp->status);
4048 do_in_jni_thread(
4049 FROM_HERE,
4050 base::Bind(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
4051 (btrc_status_t)p_rsp->status, nullptr, 0));
4052 }
4053 }
4054 /***************************************************************************
4055 *
4056 * Function cleanup_btrc_folder_items
4057 *
4058 * Description Frees the memory that was allocated for a list of folder
4059 * items.
4060 * Returns None
4061 **************************************************************************/
cleanup_btrc_folder_items(btrc_folder_items_t * btrc_items,uint8_t item_count)4062 static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items,
4063 uint8_t item_count) {
4064 for (uint8_t i = 0; i < item_count; i++) {
4065 btrc_folder_items_t* btrc_item = &(btrc_items[i]);
4066 switch (btrc_item->item_type) {
4067 case BTRC_ITEM_MEDIA:
4068 osi_free(btrc_item->media.p_attrs);
4069 break;
4070 case BTRC_ITEM_PLAYER:
4071 case BTRC_ITEM_FOLDER:
4072 /*Nothing to free*/
4073 break;
4074 default:
4075 BTIF_TRACE_WARNING("%s free unspecified type", __func__);
4076 }
4077 }
4078 osi_free(btrc_items);
4079 }
4080
4081 /***************************************************************************
4082 *
4083 * Function get_folder_item_type_media
4084 *
4085 * Description Converts the AVRC representation of a folder item with
4086 * TYPE media to BTIF representation.
4087 * Returns None
4088 *
4089 **************************************************************************/
get_folder_item_type_media(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4090 void get_folder_item_type_media(const tAVRC_ITEM* avrc_item,
4091 btrc_folder_items_t* btrc_item) {
4092 btrc_item->item_type = BTRC_ITEM_MEDIA;
4093 const tAVRC_ITEM_MEDIA* avrc_item_media = &(avrc_item->u.media);
4094 btrc_item_media_t* btrc_item_media = &(btrc_item->media);
4095 /* UID */
4096 memset(btrc_item_media->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
4097 memcpy(btrc_item_media->uid, avrc_item_media->uid,
4098 sizeof(uint8_t) * BTRC_UID_SIZE);
4099
4100 /* Audio/Video type */
4101 switch (avrc_item_media->type) {
4102 case AVRC_MEDIA_TYPE_AUDIO:
4103 btrc_item_media->type = BTRC_MEDIA_TYPE_AUDIO;
4104 break;
4105 case AVRC_MEDIA_TYPE_VIDEO:
4106 btrc_item_media->type = BTRC_MEDIA_TYPE_VIDEO;
4107 break;
4108 }
4109
4110 /* Charset ID */
4111 btrc_item_media->charset_id = avrc_item_media->name.charset_id;
4112
4113 /* Copy the name */
4114 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN,
4115 avrc_item_media->name.str_len);
4116 memset(btrc_item_media->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4117 memcpy(btrc_item_media->name, avrc_item_media->name.p_str,
4118 sizeof(uint8_t) * (avrc_item_media->name.str_len));
4119
4120 /* Extract each attribute */
4121 for (int i = 0; i < avrc_item_media->attr_count; i++) {
4122 btrc_element_attr_val_t* btrc_attr_pair = &(btrc_item_media->p_attrs[i]);
4123 tAVRC_ATTR_ENTRY* avrc_attr_pair = &(avrc_item_media->p_attr_list[i]);
4124
4125 BTIF_TRACE_DEBUG("%s media attr id 0x%x", __func__,
4126 avrc_attr_pair->attr_id);
4127
4128 switch (avrc_attr_pair->attr_id) {
4129 case AVRC_MEDIA_ATTR_ID_TITLE:
4130 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TITLE;
4131 break;
4132 case AVRC_MEDIA_ATTR_ID_ARTIST:
4133 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ARTIST;
4134 break;
4135 case AVRC_MEDIA_ATTR_ID_ALBUM:
4136 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ALBUM;
4137 break;
4138 case AVRC_MEDIA_ATTR_ID_TRACK_NUM:
4139 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TRACK_NUM;
4140 break;
4141 case AVRC_MEDIA_ATTR_ID_NUM_TRACKS:
4142 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_NUM_TRACKS;
4143 break;
4144 case AVRC_MEDIA_ATTR_ID_GENRE:
4145 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_GENRE;
4146 break;
4147 case AVRC_MEDIA_ATTR_ID_PLAYING_TIME:
4148 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_PLAYING_TIME;
4149 break;
4150 case AVRC_MEDIA_ATTR_ID_COVER_ARTWORK_HANDLE:
4151 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_COVER_ARTWORK_HANDLE;
4152 break;
4153 default:
4154 BTIF_TRACE_ERROR("%s invalid media attr id: 0x%x", __func__,
4155 avrc_attr_pair->attr_id);
4156 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_INVALID;
4157 }
4158
4159 memset(btrc_attr_pair->text, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4160 memcpy(btrc_attr_pair->text, avrc_attr_pair->name.p_str,
4161 avrc_attr_pair->name.str_len);
4162 }
4163 }
4164
4165 /***************************************************************************
4166 *
4167 * Function get_folder_item_type_folder
4168 *
4169 * Description Converts the AVRC representation of a folder item with
4170 * TYPE folder to BTIF representation.
4171 * Returns None
4172 *
4173 **************************************************************************/
get_folder_item_type_folder(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4174 void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
4175 btrc_folder_items_t* btrc_item) {
4176 btrc_item->item_type = BTRC_ITEM_FOLDER;
4177 const tAVRC_ITEM_FOLDER* avrc_item_folder = &(avrc_item->u.folder);
4178 btrc_item_folder_t* btrc_item_folder = &(btrc_item->folder);
4179 /* Copy the UID */
4180 memset(btrc_item_folder->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
4181 memcpy(btrc_item_folder->uid, avrc_item_folder->uid,
4182 sizeof(uint8_t) * BTRC_UID_SIZE);
4183
4184 /* Copy the type */
4185 switch (avrc_item_folder->type) {
4186 case AVRC_FOLDER_TYPE_MIXED:
4187 btrc_item_folder->type = BTRC_FOLDER_TYPE_MIXED;
4188 break;
4189 case AVRC_FOLDER_TYPE_TITLES:
4190 btrc_item_folder->type = BTRC_FOLDER_TYPE_TITLES;
4191 break;
4192 case AVRC_FOLDER_TYPE_ALNUMS:
4193 btrc_item_folder->type = BTRC_FOLDER_TYPE_ALBUMS;
4194 break;
4195 case AVRC_FOLDER_TYPE_ARTISTS:
4196 btrc_item_folder->type = BTRC_FOLDER_TYPE_ARTISTS;
4197 break;
4198 case AVRC_FOLDER_TYPE_GENRES:
4199 btrc_item_folder->type = BTRC_FOLDER_TYPE_GENRES;
4200 break;
4201 case AVRC_FOLDER_TYPE_PLAYLISTS:
4202 btrc_item_folder->type = BTRC_FOLDER_TYPE_PLAYLISTS;
4203 break;
4204 case AVRC_FOLDER_TYPE_YEARS:
4205 btrc_item_folder->type = BTRC_FOLDER_TYPE_YEARS;
4206 break;
4207 }
4208
4209 /* Copy if playable */
4210 btrc_item_folder->playable = avrc_item_folder->playable;
4211
4212 /* Copy name */
4213 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN,
4214 avrc_item_folder->name.str_len);
4215 memset(btrc_item_folder->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4216 memcpy(btrc_item_folder->name, avrc_item_folder->name.p_str,
4217 avrc_item_folder->name.str_len * sizeof(uint8_t));
4218
4219 /* Copy charset */
4220 btrc_item_folder->charset_id = avrc_item_folder->name.charset_id;
4221 }
4222
4223 /***************************************************************************
4224 *
4225 * Function get_folder_item_type_player
4226 *
4227 * Description Converts the AVRC representation of a folder item with
4228 * TYPE player to BTIF representation.
4229 * Returns None
4230 *
4231 **************************************************************************/
get_folder_item_type_player(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4232 void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
4233 btrc_folder_items_t* btrc_item) {
4234 btrc_item->item_type = BTRC_ITEM_PLAYER;
4235 const tAVRC_ITEM_PLAYER* avrc_item_player = &(avrc_item->u.player);
4236 btrc_item_player_t* btrc_item_player = &(btrc_item->player);
4237 /* Player ID */
4238 btrc_item_player->player_id = avrc_item_player->player_id;
4239 /* Major type */
4240 btrc_item_player->major_type = avrc_item_player->major_type;
4241 /* Sub type */
4242 btrc_item_player->sub_type = avrc_item_player->sub_type;
4243 /* Play status */
4244 btrc_item_player->play_status = avrc_item_player->play_status;
4245 /* Features */
4246 memcpy(btrc_item_player->features, avrc_item_player->features,
4247 BTRC_FEATURE_BIT_MASK_SIZE);
4248
4249 memset(btrc_item_player->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4250 memcpy(btrc_item_player->name, avrc_item_player->name.p_str,
4251 avrc_item_player->name.str_len);
4252 }
4253
4254 /***************************************************************************
4255 *
4256 * Function handle_change_path_response
4257 *
4258 * Description handles the the change path response, calls
4259 * HAL callback to send the updated folder
4260 * Returns None
4261 *
4262 **************************************************************************/
handle_change_path_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_CHG_PATH_RSP * p_rsp)4263 static void handle_change_path_response(tBTA_AV_META_MSG* pmeta_msg,
4264 tAVRC_CHG_PATH_RSP* p_rsp) {
4265 btif_rc_device_cb_t* p_dev =
4266 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4267
4268 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4269 do_in_jni_thread(FROM_HERE,
4270 base::Bind(bt_rc_ctrl_callbacks->change_folder_path_cb,
4271 p_dev->rc_addr, p_rsp->num_items));
4272 } else {
4273 BTIF_TRACE_ERROR("%s error in handle_change_path_response %d", __func__,
4274 p_rsp->status);
4275 }
4276 }
4277
4278 /***************************************************************************
4279 *
4280 * Function handle_set_browsed_player_response
4281 *
4282 * Description handles the the change path response, calls
4283 * HAL callback to send the updated folder
4284 * Returns None
4285 *
4286 **************************************************************************/
handle_set_browsed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_SET_BR_PLAYER_RSP * p_rsp)4287 static void handle_set_browsed_player_response(tBTA_AV_META_MSG* pmeta_msg,
4288 tAVRC_SET_BR_PLAYER_RSP* p_rsp) {
4289 btif_rc_device_cb_t* p_dev =
4290 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4291
4292 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4293 do_in_jni_thread(
4294 FROM_HERE,
4295 base::Bind(bt_rc_ctrl_callbacks->set_browsed_player_cb, p_dev->rc_addr,
4296 p_rsp->num_items, p_rsp->folder_depth));
4297 } else {
4298 BTIF_TRACE_ERROR("%s error %d", __func__, p_rsp->status);
4299 }
4300 }
4301
4302 /***************************************************************************
4303 *
4304 * Function clear_cmd_timeout
4305 *
4306 * Description helper function to stop the command timeout timer
4307 * Returns None
4308 *
4309 **************************************************************************/
clear_cmd_timeout(uint8_t label)4310 static void clear_cmd_timeout(uint8_t label) {
4311 rc_transaction_t* p_txn;
4312
4313 p_txn = get_transaction_by_lbl(label);
4314 if (p_txn == NULL) {
4315 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __func__);
4316 return;
4317 }
4318
4319 if (p_txn->txn_timer != NULL) alarm_cancel(p_txn->txn_timer);
4320 }
4321
4322 /***************************************************************************
4323 *
4324 * Function handle_avk_rc_metamsg_rsp
4325 *
4326 * Description Handle RC metamessage response
4327 *
4328 * Returns void
4329 *
4330 **************************************************************************/
handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg)4331 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) {
4332 tAVRC_RESPONSE avrc_response = {0};
4333 uint8_t scratch_buf[512] = {0}; // this variable is unused
4334 uint16_t buf_len;
4335 tAVRC_STS status;
4336
4337 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d ", __func__,
4338 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4339
4340 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf,
4341 &buf_len);
4342 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) &&
4343 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) &&
4344 (pmeta_msg->code <= AVRC_RSP_INTERIM)) {
4345 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d", __func__,
4346 status, avrc_response.pdu,
4347 pmeta_msg->p_msg->vendor.hdr.ctype);
4348
4349 switch (avrc_response.pdu) {
4350 case AVRC_PDU_REGISTER_NOTIFICATION:
4351 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
4352 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
4353 /* Don't free the transaction Id */
4354 clear_cmd_timeout(pmeta_msg->label);
4355 return;
4356 }
4357 break;
4358
4359 case AVRC_PDU_GET_CAPABILITIES:
4360 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
4361 break;
4362
4363 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
4364 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
4365 break;
4366
4367 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
4368 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
4369 break;
4370
4371 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
4372 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
4373 break;
4374
4375 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
4376 handle_app_attr_txt_response(pmeta_msg,
4377 &avrc_response.get_app_attr_txt);
4378 break;
4379
4380 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
4381 handle_app_attr_val_txt_response(pmeta_msg,
4382 &avrc_response.get_app_val_txt);
4383 break;
4384
4385 case AVRC_PDU_SET_PLAYER_APP_VALUE:
4386 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
4387 break;
4388
4389 case AVRC_PDU_GET_ELEMENT_ATTR:
4390 handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
4391 break;
4392
4393 case AVRC_PDU_GET_PLAY_STATUS:
4394 handle_get_playstatus_response(pmeta_msg,
4395 &avrc_response.get_play_status);
4396 break;
4397
4398 case AVRC_PDU_SET_ADDRESSED_PLAYER:
4399 handle_set_addressed_player_response(pmeta_msg, &avrc_response.rsp);
4400 break;
4401 }
4402 } else if (AVRC_OP_BROWSE == pmeta_msg->p_msg->hdr.opcode) {
4403 BTIF_TRACE_DEBUG("%s AVRC_OP_BROWSE pdu %d", __func__, avrc_response.pdu);
4404 /* check what kind of command it is for browsing */
4405 switch (avrc_response.pdu) {
4406 case AVRC_PDU_GET_FOLDER_ITEMS:
4407 handle_get_folder_items_response(pmeta_msg, &avrc_response.get_items);
4408 break;
4409 case AVRC_PDU_CHANGE_PATH:
4410 handle_change_path_response(pmeta_msg, &avrc_response.chg_path);
4411 break;
4412 case AVRC_PDU_SET_BROWSED_PLAYER:
4413 handle_set_browsed_player_response(pmeta_msg, &avrc_response.br_player);
4414 break;
4415 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
4416 handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
4417 break;
4418 default:
4419 BTIF_TRACE_ERROR("%s cannot handle browse pdu %d", __func__,
4420 pmeta_msg->p_msg->hdr.opcode);
4421 }
4422 } else {
4423 BTIF_TRACE_DEBUG(
4424 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.",
4425 __func__, pmeta_msg->code, pmeta_msg->len);
4426 return;
4427 }
4428 BTIF_TRACE_DEBUG("XX __func__ release transaction %d", pmeta_msg->label);
4429 release_transaction(pmeta_msg->label);
4430 }
4431
4432 /***************************************************************************
4433 *
4434 * Function handle_avk_rc_metamsg_cmd
4435 *
4436 * Description Handle RC metamessage response
4437 *
4438 * Returns void
4439 *
4440 **************************************************************************/
handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)4441 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
4442 tAVRC_COMMAND avrc_cmd = {0};
4443 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4444 btif_rc_device_cb_t* p_dev = NULL;
4445
4446 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d", __func__,
4447 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4448 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
4449 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) &&
4450 (pmeta_msg->code <= AVRC_CMD_GEN_INQ)) {
4451 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
4452 __func__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
4453
4454 if (status != AVRC_STS_NO_ERROR) {
4455 /* return error */
4456 BTIF_TRACE_WARNING(
4457 "%s: Error in parsing received metamsg command. status: 0x%02x",
4458 __func__, status);
4459 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu,
4460 status, pmeta_msg->p_msg->hdr.opcode);
4461 } else {
4462 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4463 if (p_dev == NULL) {
4464 BTIF_TRACE_ERROR("%s: avk rc meta msg cmd for Invalid rc handle",
4465 __func__);
4466 return;
4467 }
4468
4469 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
4470 uint8_t event_id = avrc_cmd.reg_notif.event_id;
4471 BTIF_TRACE_EVENT("%s: Register notification event_id: %s", __func__,
4472 dump_rc_notification_event_id(event_id));
4473 } else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) {
4474 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __func__);
4475 }
4476
4477 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label,
4478 p_dev);
4479 }
4480 } else {
4481 BTIF_TRACE_DEBUG(
4482 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.",
4483 __func__, pmeta_msg->code, pmeta_msg->len);
4484 return;
4485 }
4486 }
4487
4488 /***************************************************************************
4489 *
4490 * Function cleanup
4491 *
4492 * Description Closes the AVRC interface
4493 *
4494 * Returns void
4495 *
4496 **************************************************************************/
cleanup()4497 static void cleanup() {
4498 BTIF_TRACE_EVENT("%s: ", __func__);
4499 if (bt_rc_callbacks) {
4500 bt_rc_callbacks = NULL;
4501 }
4502
4503 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4504 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4505 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
4506 sizeof(btif_rc_cb.rc_multi_cb[idx]));
4507 }
4508
4509 BTIF_TRACE_EVENT("%s: completed", __func__);
4510 }
4511
4512 /***************************************************************************
4513 *
4514 * Function cleanup_ctrl
4515 *
4516 * Description Closes the AVRC Controller interface
4517 *
4518 * Returns void
4519 *
4520 **************************************************************************/
cleanup_ctrl()4521 static void cleanup_ctrl() {
4522 BTIF_TRACE_EVENT("%s: ", __func__);
4523
4524 if (bt_rc_ctrl_callbacks) {
4525 bt_rc_ctrl_callbacks = NULL;
4526 }
4527
4528 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4529 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4530 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
4531 sizeof(btif_rc_cb.rc_multi_cb[idx]));
4532 }
4533
4534 memset(&btif_rc_cb.rc_multi_cb, 0, sizeof(btif_rc_cb.rc_multi_cb));
4535 BTIF_TRACE_EVENT("%s: completed", __func__);
4536 }
4537
4538 /***************************************************************************
4539 *
4540 * Function getcapabilities_cmd
4541 *
4542 * Description GetCapabilties from Remote(Company_ID, Events_Supported)
4543 *
4544 * Returns void
4545 *
4546 **************************************************************************/
getcapabilities_cmd(uint8_t cap_id,btif_rc_device_cb_t * p_dev)4547 static bt_status_t getcapabilities_cmd(uint8_t cap_id,
4548 btif_rc_device_cb_t* p_dev) {
4549 BTIF_TRACE_DEBUG("%s: cap_id: %d", __func__, cap_id);
4550 CHECK_RC_CONNECTED(p_dev);
4551
4552 tAVRC_COMMAND avrc_cmd = {0};
4553 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
4554 avrc_cmd.get_caps.capability_id = cap_id;
4555 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
4556 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
4557
4558 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4559 }
4560
4561 /***************************************************************************
4562 *
4563 * Function list_player_app_setting_attrib_cmd
4564 *
4565 * Description Get supported List Player Attributes
4566 *
4567 * Returns void
4568 *
4569 **************************************************************************/
list_player_app_setting_attrib_cmd(btif_rc_device_cb_t * p_dev)4570 static bt_status_t list_player_app_setting_attrib_cmd(
4571 btif_rc_device_cb_t* p_dev) {
4572 BTIF_TRACE_DEBUG("%s", __func__);
4573 CHECK_RC_CONNECTED(p_dev);
4574
4575 tAVRC_COMMAND avrc_cmd = {0};
4576 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
4577 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
4578 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
4579
4580 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4581 }
4582
4583 /***************************************************************************
4584 *
4585 * Function list_player_app_setting_value_cmd
4586 *
4587 * Description Get values of supported Player Attributes
4588 *
4589 * Returns void
4590 *
4591 **************************************************************************/
list_player_app_setting_value_cmd(uint8_t attrib_id,btif_rc_device_cb_t * p_dev)4592 static bt_status_t list_player_app_setting_value_cmd(
4593 uint8_t attrib_id, btif_rc_device_cb_t* p_dev) {
4594 BTIF_TRACE_DEBUG("%s: attrib_id: %d", __func__, attrib_id);
4595 CHECK_RC_CONNECTED(p_dev);
4596
4597 tAVRC_COMMAND avrc_cmd = {0};
4598 avrc_cmd.list_app_values.attr_id = attrib_id;
4599 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
4600 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
4601 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
4602
4603 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4604 }
4605
4606 /***************************************************************************
4607 *
4608 * Function get_player_app_setting_cmd
4609 *
4610 * Description Get current values of Player Attributes
4611 *
4612 * Returns void
4613 *
4614 **************************************************************************/
get_player_app_setting_cmd(uint8_t num_attrib,uint8_t * attrib_ids,btif_rc_device_cb_t * p_dev)4615 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib,
4616 uint8_t* attrib_ids,
4617 btif_rc_device_cb_t* p_dev) {
4618 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib);
4619 CHECK_RC_CONNECTED(p_dev);
4620
4621 tAVRC_COMMAND avrc_cmd = {0};
4622 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
4623 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
4624 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
4625 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
4626
4627 for (int count = 0; count < num_attrib; count++) {
4628 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
4629 }
4630
4631 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4632 }
4633
4634 /***************************************************************************
4635 *
4636 * Function get_current_metadata_cmd
4637 *
4638 * Description Fetch the current track metadata for the device
4639 *
4640 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4641 * BT_STATUS_FAIL.
4642 *
4643 **************************************************************************/
get_current_metadata_cmd(const RawAddress & bd_addr)4644 static bt_status_t get_current_metadata_cmd(const RawAddress& bd_addr) {
4645 BTIF_TRACE_DEBUG("%s", __func__);
4646 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4647 if (p_dev == NULL) {
4648 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
4649 return BT_STATUS_FAIL;
4650 }
4651 const uint32_t* attr_list = get_requested_attributes_list(p_dev);
4652 const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
4653 return get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
4654 }
4655
4656 /***************************************************************************
4657 *
4658 * Function get_playback_state_cmd
4659 *
4660 * Description Fetch the current playback state for the device
4661 *
4662 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4663 * BT_STATUS_FAIL.
4664 *
4665 **************************************************************************/
get_playback_state_cmd(const RawAddress & bd_addr)4666 static bt_status_t get_playback_state_cmd(const RawAddress& bd_addr) {
4667 BTIF_TRACE_DEBUG("%s", __func__);
4668 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4669 return get_play_status_cmd(p_dev);
4670 }
4671
4672 /***************************************************************************
4673 *
4674 * Function get_now_playing_list_cmd
4675 *
4676 * Description Fetch the now playing list
4677 *
4678 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4679 * end_item: Last item to fetch (0xffffffff to fetch until end)
4680 *
4681 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4682 * BT_STATUS_FAIL.
4683 *
4684 **************************************************************************/
get_now_playing_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4685 static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr,
4686 uint32_t start_item,
4687 uint32_t end_item) {
4688 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
4689 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item,
4690 end_item);
4691 }
4692
4693 /***************************************************************************
4694 *
4695 * Function get_item_attribute_cmd
4696 *
4697 * Description Fetch the item attributes for a given uid.
4698 *
4699 * Parameters uid: Track UID you want attributes for
4700 * scope: Constant representing which scope you're querying
4701 * (i.e AVRC_SCOPE_FILE_SYSTEM)
4702 * p_dev: Device control block
4703 *
4704 * Returns BT_STATUS_SUCCESS if command is issued successfully
4705 * otherwise BT_STATUS_FAIL
4706 *
4707 **************************************************************************/
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)4708 static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope,
4709 uint8_t num_attribute,
4710 const uint32_t* p_attr_ids,
4711 btif_rc_device_cb_t* p_dev) {
4712 tAVRC_COMMAND avrc_cmd = {0};
4713 avrc_cmd.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
4714 avrc_cmd.get_attrs.scope = scope;
4715 memcpy(avrc_cmd.get_attrs.uid, &uid, 8);
4716 avrc_cmd.get_attrs.uid_counter = 0;
4717 avrc_cmd.get_attrs.attr_count = 0;
4718
4719 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4720 }
4721
4722 /***************************************************************************
4723 *
4724 * Function get_folder_list_cmd
4725 *
4726 * Description Fetch the currently selected folder list
4727 *
4728 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4729 * end_item: Last item to fetch (0xffffffff to fetch until end)
4730 *
4731 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4732 * BT_STATUS_FAIL.
4733 *
4734 **************************************************************************/
get_folder_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4735 static bt_status_t get_folder_list_cmd(const RawAddress& bd_addr,
4736 uint32_t start_item, uint32_t end_item) {
4737 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
4738 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item,
4739 end_item);
4740 }
4741
4742 /***************************************************************************
4743 *
4744 * Function get_player_list_cmd
4745 *
4746 * Description Fetch the player list
4747 *
4748 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4749 * end_item: Last item to fetch (0xffffffff to fetch until end)
4750 *
4751 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4752 * BT_STATUS_FAIL.
4753 *
4754 **************************************************************************/
get_player_list_cmd(const RawAddress & bd_addr,uint32_t start_item,uint32_t end_item)4755 static bt_status_t get_player_list_cmd(const RawAddress& bd_addr,
4756 uint32_t start_item, uint32_t end_item) {
4757 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
4758 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
4759 end_item);
4760 }
4761
4762 /***************************************************************************
4763 *
4764 * Function change_folder_path_cmd
4765 *
4766 * Description Change the folder.
4767 *
4768 * Paramters direction: Direction (Up/Down) to change folder
4769 * uid: The UID of folder to move to
4770 * start_item: First item to fetch (0 to fetch from beganning)
4771 * end_item: Last item to fetch (0xffffffff to fetch until end)
4772 *
4773 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4774 * BT_STATUS_FAIL.
4775 *
4776 **************************************************************************/
change_folder_path_cmd(const RawAddress & bd_addr,uint8_t direction,uint8_t * uid)4777 static bt_status_t change_folder_path_cmd(const RawAddress& bd_addr,
4778 uint8_t direction, uint8_t* uid) {
4779 BTIF_TRACE_DEBUG("%s: direction %d", __func__, direction);
4780 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4781 CHECK_RC_CONNECTED(p_dev);
4782 CHECK_BR_CONNECTED(p_dev);
4783
4784 tAVRC_COMMAND avrc_cmd = {0};
4785
4786 avrc_cmd.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
4787 avrc_cmd.chg_path.status = AVRC_STS_NO_ERROR;
4788 // TODO(sanketa): Improve for database aware clients.
4789 avrc_cmd.chg_path.uid_counter = 0;
4790 avrc_cmd.chg_path.direction = direction;
4791
4792 memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t));
4793 memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t));
4794
4795 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4796 }
4797
4798 /***************************************************************************
4799 *
4800 * Function set_browsed_player_cmd
4801 *
4802 * Description Change the browsed player.
4803 *
4804 * Paramters id: The UID of player to move to
4805 *
4806 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4807 * BT_STATUS_FAIL.
4808 *
4809 **************************************************************************/
set_browsed_player_cmd(const RawAddress & bd_addr,uint16_t id)4810 static bt_status_t set_browsed_player_cmd(const RawAddress& bd_addr,
4811 uint16_t id) {
4812 BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
4813 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4814 CHECK_RC_CONNECTED(p_dev);
4815 CHECK_BR_CONNECTED(p_dev);
4816
4817 tAVRC_COMMAND avrc_cmd = {0};
4818 avrc_cmd.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
4819 avrc_cmd.br_player.status = AVRC_STS_NO_ERROR;
4820 // TODO(sanketa): Improve for database aware clients.
4821 avrc_cmd.br_player.player_id = id;
4822
4823 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4824 }
4825
4826 /***************************************************************************
4827 **
4828 ** Function set_addressed_player_cmd
4829 **
4830 ** Description Change the addressed player.
4831 **
4832 ** Paramters id: The UID of player to move to
4833 **
4834 ** Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4835 ** BT_STATUS_FAIL.
4836 **
4837 ***************************************************************************/
set_addressed_player_cmd(const RawAddress & bd_addr,uint16_t id)4838 static bt_status_t set_addressed_player_cmd(const RawAddress& bd_addr,
4839 uint16_t id) {
4840 BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
4841
4842 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4843 CHECK_RC_CONNECTED(p_dev);
4844 CHECK_BR_CONNECTED(p_dev);
4845
4846 tAVRC_COMMAND avrc_cmd = {0};
4847 avrc_cmd.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
4848 avrc_cmd.addr_player.status = AVRC_STS_NO_ERROR;
4849 // TODO(sanketa): Improve for database aware clients.
4850 avrc_cmd.addr_player.player_id = id;
4851
4852 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4853 }
4854
4855 /***************************************************************************
4856 *
4857 * Function get_folder_items_cmd
4858 *
4859 * Description Helper function to browse the content hierarchy of the
4860 * TG device.
4861 *
4862 * Paramters scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable
4863 * content
4864 * start_item: First item to fetch (0 to fetch from beganning)
4865 * end_item: Last item to fetch (0xffff to fetch until end)
4866 *
4867 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4868 * BT_STATUS_FAIL.
4869 *
4870 **************************************************************************/
get_folder_items_cmd(const RawAddress & bd_addr,uint8_t scope,uint32_t start_item,uint32_t end_item)4871 static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr,
4872 uint8_t scope, uint32_t start_item,
4873 uint32_t end_item) {
4874 /* Check that both avrcp and browse channel are connected. */
4875 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4876 BTIF_TRACE_DEBUG("%s", __func__);
4877 CHECK_RC_CONNECTED(p_dev);
4878 CHECK_BR_CONNECTED(p_dev);
4879
4880 tAVRC_COMMAND avrc_cmd = {0};
4881
4882 /* Set the layer specific to point to browse although this should really
4883 * be done by lower layers and looking at the PDU
4884 */
4885 avrc_cmd.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
4886 avrc_cmd.get_items.status = AVRC_STS_NO_ERROR;
4887 avrc_cmd.get_items.scope = scope;
4888 avrc_cmd.get_items.start_item = start_item;
4889 avrc_cmd.get_items.end_item = end_item;
4890 avrc_cmd.get_items.attr_count = 0; /* p_attr_list does not matter hence */
4891
4892 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4893 }
4894
4895 /***************************************************************************
4896 *
4897 * Function change_player_app_setting
4898 *
4899 * Description Set current values of Player Attributes
4900 *
4901 * Returns void
4902 *
4903 **************************************************************************/
change_player_app_setting(const RawAddress & bd_addr,uint8_t num_attrib,uint8_t * attrib_ids,uint8_t * attrib_vals)4904 static bt_status_t change_player_app_setting(const RawAddress& bd_addr,
4905 uint8_t num_attrib,
4906 uint8_t* attrib_ids,
4907 uint8_t* attrib_vals) {
4908 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib);
4909 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4910 CHECK_RC_CONNECTED(p_dev);
4911
4912 tAVRC_COMMAND avrc_cmd = {0};
4913 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
4914 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
4915 avrc_cmd.set_app_val.num_val = num_attrib;
4916 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
4917 avrc_cmd.set_app_val.p_vals =
4918 (tAVRC_APP_SETTING*)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
4919 for (int count = 0; count < num_attrib; count++) {
4920 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
4921 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
4922 }
4923
4924 bt_status_t st = build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4925 osi_free_and_reset((void**)&avrc_cmd.set_app_val.p_vals);
4926 return st;
4927 }
4928
4929 /***************************************************************************
4930 *
4931 * Function play_item_cmd
4932 *
4933 * Description Play the item specified by UID & scope
4934 *
4935 * Returns void
4936 *
4937 **************************************************************************/
play_item_cmd(const RawAddress & bd_addr,uint8_t scope,uint8_t * uid,uint16_t uid_counter)4938 static bt_status_t play_item_cmd(const RawAddress& bd_addr, uint8_t scope,
4939 uint8_t* uid, uint16_t uid_counter) {
4940 BTIF_TRACE_DEBUG("%s: scope %d uid_counter %d", __func__, scope, uid_counter);
4941 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4942 CHECK_RC_CONNECTED(p_dev);
4943 CHECK_BR_CONNECTED(p_dev);
4944
4945 tAVRC_COMMAND avrc_cmd = {0};
4946 avrc_cmd.pdu = AVRC_PDU_PLAY_ITEM;
4947 avrc_cmd.play_item.opcode = AVRC_OP_VENDOR;
4948 avrc_cmd.play_item.status = AVRC_STS_NO_ERROR;
4949 avrc_cmd.play_item.scope = scope;
4950 memcpy(avrc_cmd.play_item.uid, uid, AVRC_UID_SIZE);
4951 avrc_cmd.play_item.uid_counter = uid_counter;
4952
4953 return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
4954 // return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4955 }
4956
4957 /***************************************************************************
4958 *
4959 * Function get_player_app_setting_attr_text_cmd
4960 *
4961 * Description Get text description for app attribute
4962 *
4963 * Returns void
4964 *
4965 **************************************************************************/
get_player_app_setting_attr_text_cmd(uint8_t * attrs,uint8_t num_attrs,btif_rc_device_cb_t * p_dev)4966 static bt_status_t get_player_app_setting_attr_text_cmd(
4967 uint8_t* attrs, uint8_t num_attrs, btif_rc_device_cb_t* p_dev) {
4968 BTIF_TRACE_DEBUG("%s: num attrs: %d", __func__, num_attrs);
4969 CHECK_RC_CONNECTED(p_dev);
4970
4971 tAVRC_COMMAND avrc_cmd = {0};
4972 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
4973 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
4974 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
4975
4976 for (int count = 0; count < num_attrs; count++) {
4977 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
4978 }
4979
4980 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4981 }
4982
4983 /***************************************************************************
4984 *
4985 * Function get_player_app_setting_val_text_cmd
4986 *
4987 * Description Get text description for app attribute values
4988 *
4989 * Returns void
4990 *
4991 **************************************************************************/
get_player_app_setting_value_text_cmd(uint8_t * vals,uint8_t num_vals,btif_rc_device_cb_t * p_dev)4992 static bt_status_t get_player_app_setting_value_text_cmd(
4993 uint8_t* vals, uint8_t num_vals, btif_rc_device_cb_t* p_dev) {
4994 BTIF_TRACE_DEBUG("%s: num_vals: %d", __func__, num_vals);
4995 CHECK_RC_CONNECTED(p_dev);
4996
4997 tAVRC_COMMAND avrc_cmd = {0};
4998 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
4999 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
5000 avrc_cmd.get_app_val_txt.num_val = num_vals;
5001
5002 for (int count = 0; count < num_vals; count++) {
5003 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
5004 }
5005
5006 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
5007 }
5008
5009 /***************************************************************************
5010 *
5011 * Function register_notification_cmd
5012 *
5013 * Description Send Command to register for a Notification ID
5014 *
5015 * Returns void
5016 *
5017 **************************************************************************/
register_notification_cmd(uint8_t label,uint8_t event_id,uint32_t event_value,btif_rc_device_cb_t * p_dev)5018 static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id,
5019 uint32_t event_value,
5020 btif_rc_device_cb_t* p_dev) {
5021 BTIF_TRACE_DEBUG("%s: event_id: %d event_value %d", __func__, event_id,
5022 event_value);
5023 CHECK_RC_CONNECTED(p_dev);
5024
5025 tAVRC_COMMAND avrc_cmd = {0};
5026 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
5027 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
5028 avrc_cmd.reg_notif.event_id = event_id;
5029 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
5030 avrc_cmd.reg_notif.param = event_value;
5031
5032 BT_HDR* p_msg = NULL;
5033 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
5034 if (status == AVRC_STS_NO_ERROR) {
5035 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
5036 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
5037 label);
5038 if (p_msg != NULL) {
5039 BTA_AvVendorCmd(p_dev->rc_handle, label, AVRC_CMD_NOTIF, data_start,
5040 p_msg->len);
5041 status = BT_STATUS_SUCCESS;
5042 }
5043 } else {
5044 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
5045 status);
5046 }
5047 osi_free(p_msg);
5048 return (bt_status_t)status;
5049 }
5050
5051 /***************************************************************************
5052 *
5053 * Function get_metadata_attribute_cmd
5054 *
5055 * Description Get metadata attributes for attributeIds. This function
5056 * will make the right determination of whether to use the
5057 * control or browsing channel for the request
5058 *
5059 * Returns BT_STATUS_SUCCESS if the command is successfully issued
5060 * otherwise BT_STATUS_FAIL
5061 *
5062 **************************************************************************/
get_metadata_attribute_cmd(uint8_t num_attribute,const uint32_t * p_attr_ids,btif_rc_device_cb_t * p_dev)5063 static bt_status_t get_metadata_attribute_cmd(uint8_t num_attribute,
5064 const uint32_t* p_attr_ids,
5065 btif_rc_device_cb_t* p_dev) {
5066 BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__,
5067 num_attribute, p_attr_ids[0]);
5068
5069 // If browsing is connected then send the command out that channel
5070 if (p_dev->br_connected) {
5071 return get_item_attribute_cmd(p_dev->rc_playing_uid,
5072 AVRC_SCOPE_NOW_PLAYING, num_attribute,
5073 p_attr_ids, p_dev);
5074 }
5075
5076 // Otherwise, default to the control channel
5077 return get_element_attribute_cmd(num_attribute, p_attr_ids, p_dev);
5078 }
5079
5080 /***************************************************************************
5081 *
5082 * Function get_element_attribute_cmd
5083 *
5084 * Description Get Element Attribute for attributeIds
5085 *
5086 * Returns void
5087 *
5088 **************************************************************************/
get_element_attribute_cmd(uint8_t num_attribute,const uint32_t * p_attr_ids,btif_rc_device_cb_t * p_dev)5089 static bt_status_t get_element_attribute_cmd(uint8_t num_attribute,
5090 const uint32_t* p_attr_ids,
5091 btif_rc_device_cb_t* p_dev) {
5092 BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__,
5093 num_attribute, p_attr_ids[0]);
5094 CHECK_RC_CONNECTED(p_dev);
5095 tAVRC_COMMAND avrc_cmd = {0};
5096 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
5097 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
5098 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
5099 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
5100 for (int count = 0; count < num_attribute; count++) {
5101 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
5102 }
5103
5104 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
5105 }
5106
5107 /***************************************************************************
5108 *
5109 * Function get_play_status_cmd
5110 *
5111 * Description Get Playing Status of a Device
5112 *
5113 * Returns bt_status_t
5114 *
5115 **************************************************************************/
get_play_status_cmd(btif_rc_device_cb_t * p_dev)5116 static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev) {
5117 BTIF_TRACE_DEBUG("%s", __func__);
5118 CHECK_RC_CONNECTED(p_dev);
5119
5120 tAVRC_COMMAND avrc_cmd = {0};
5121 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
5122 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
5123 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
5124
5125 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
5126 }
5127
5128 /***************************************************************************
5129 *
5130 * Function set_volume_rsp
5131 *
5132 * Description Rsp for SetAbsoluteVolume Command
5133 *
5134 * Returns void
5135 *
5136 **************************************************************************/
set_volume_rsp(const RawAddress & bd_addr,uint8_t abs_vol,uint8_t label)5137 static bt_status_t set_volume_rsp(const RawAddress& bd_addr, uint8_t abs_vol,
5138 uint8_t label) {
5139 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5140 tAVRC_RESPONSE avrc_rsp;
5141 BT_HDR* p_msg = NULL;
5142 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5143
5144 CHECK_RC_CONNECTED(p_dev);
5145
5146 BTIF_TRACE_DEBUG("%s: abs_vol: %d", __func__, abs_vol);
5147
5148 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
5149 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
5150 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
5151 avrc_rsp.volume.volume = abs_vol;
5152 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
5153 if (status == AVRC_STS_NO_ERROR) {
5154 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
5155 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
5156 p_dev->rc_vol_label);
5157 if (p_msg != NULL) {
5158 BTA_AvVendorRsp(p_dev->rc_handle, label, AVRC_RSP_ACCEPT, data_start,
5159 p_msg->len, 0);
5160 status = BT_STATUS_SUCCESS;
5161 }
5162 } else {
5163 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
5164 status);
5165 }
5166 osi_free(p_msg);
5167 return (bt_status_t)status;
5168 }
5169
5170 /***************************************************************************
5171 *
5172 * Function send_register_abs_vol_rsp
5173 *
5174 * Description Rsp for Notification of Absolute Volume
5175 *
5176 * Returns void
5177 *
5178 **************************************************************************/
volume_change_notification_rsp(const RawAddress & bd_addr,btrc_notification_type_t rsp_type,uint8_t abs_vol,uint8_t label)5179 static bt_status_t volume_change_notification_rsp(
5180 const RawAddress& bd_addr, btrc_notification_type_t rsp_type,
5181 uint8_t abs_vol, uint8_t label) {
5182 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5183 tAVRC_RESPONSE avrc_rsp;
5184 BT_HDR* p_msg = NULL;
5185 BTIF_TRACE_DEBUG("%s: rsp_type: %d abs_vol: %d", __func__, rsp_type, abs_vol);
5186
5187 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5188
5189 CHECK_RC_CONNECTED(p_dev);
5190
5191 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
5192 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
5193 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
5194 avrc_rsp.reg_notif.param.volume = abs_vol;
5195 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
5196
5197 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
5198 if (status == AVRC_STS_NO_ERROR) {
5199 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
5200 label);
5201 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
5202 BTA_AvVendorRsp(p_dev->rc_handle, label,
5203 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM)
5204 ? AVRC_RSP_INTERIM
5205 : AVRC_RSP_CHANGED,
5206 data_start, p_msg->len, 0);
5207 status = BT_STATUS_SUCCESS;
5208 } else {
5209 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
5210 status);
5211 }
5212 osi_free(p_msg);
5213
5214 return (bt_status_t)status;
5215 }
5216
5217 /***************************************************************************
5218 *
5219 * Function send_groupnavigation_cmd
5220 *
5221 * Description Send Pass-Through command
5222 *
5223 * Returns void
5224 *
5225 **************************************************************************/
send_groupnavigation_cmd(const RawAddress & bd_addr,uint8_t key_code,uint8_t key_state)5226 static bt_status_t send_groupnavigation_cmd(const RawAddress& bd_addr,
5227 uint8_t key_code,
5228 uint8_t key_state) {
5229 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5230 rc_transaction_t* p_transaction = NULL;
5231 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code,
5232 key_state);
5233 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5234
5235 CHECK_RC_CONNECTED(p_dev);
5236
5237 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
5238 bt_status_t tran_status = get_transaction(&p_transaction);
5239 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
5240 uint8_t buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
5241 uint8_t* start = buffer;
5242 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
5243 *(start)++ = 0;
5244 UINT8_TO_BE_STREAM(start, key_code);
5245 BTA_AvRemoteVendorUniqueCmd(p_dev->rc_handle, p_transaction->lbl,
5246 (tBTA_AV_STATE)key_state, buffer,
5247 AVRC_PASS_THRU_GROUP_LEN);
5248 status = BT_STATUS_SUCCESS;
5249 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
5250 __func__);
5251 } else {
5252 status = BT_STATUS_FAIL;
5253 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__);
5254 }
5255 } else {
5256 status = BT_STATUS_FAIL;
5257 BTIF_TRACE_DEBUG("%s: feature not supported", __func__);
5258 }
5259 return (bt_status_t)status;
5260 }
5261
5262 /***************************************************************************
5263 *
5264 * Function send_passthrough_cmd
5265 *
5266 * Description Send Pass-Through command
5267 *
5268 * Returns void
5269 *
5270 **************************************************************************/
send_passthrough_cmd(const RawAddress & bd_addr,uint8_t key_code,uint8_t key_state)5271 static bt_status_t send_passthrough_cmd(const RawAddress& bd_addr,
5272 uint8_t key_code, uint8_t key_state) {
5273 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5274 btif_rc_device_cb_t* p_dev = NULL;
5275 BTIF_TRACE_ERROR("%s: calling btif_rc_get_device_by_bda", __func__);
5276 p_dev = btif_rc_get_device_by_bda(bd_addr);
5277
5278 CHECK_RC_CONNECTED(p_dev);
5279
5280 rc_transaction_t* p_transaction = NULL;
5281 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code,
5282 key_state);
5283 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
5284 bt_status_t tran_status = get_transaction(&p_transaction);
5285 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) {
5286 BTA_AvRemoteCmd(p_dev->rc_handle, p_transaction->lbl,
5287 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
5288 status = BT_STATUS_SUCCESS;
5289 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA",
5290 __func__);
5291 } else {
5292 status = BT_STATUS_FAIL;
5293 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__);
5294 }
5295 } else {
5296 status = BT_STATUS_FAIL;
5297 BTIF_TRACE_DEBUG("%s: feature not supported", __func__);
5298 }
5299 return (bt_status_t)status;
5300 }
5301
5302 static const btrc_interface_t bt_rc_interface = {
5303 sizeof(bt_rc_interface),
5304 init,
5305 get_play_status_rsp,
5306 NULL, /* list_player_app_attr_rsp */
5307 NULL, /* list_player_app_value_rsp */
5308 NULL, /* get_player_app_value_rsp */
5309 NULL, /* get_player_app_attr_text_rsp */
5310 NULL, /* get_player_app_value_text_rsp */
5311 get_element_attr_rsp,
5312 NULL, /* set_player_app_value_rsp */
5313 register_notification_rsp,
5314 set_volume,
5315 set_addressed_player_rsp,
5316 set_browsed_player_rsp,
5317 get_folder_items_list_rsp,
5318 change_path_rsp,
5319 get_item_attr_rsp,
5320 play_item_rsp,
5321 get_total_num_of_items_rsp,
5322 search_rsp,
5323 add_to_now_playing_rsp,
5324 cleanup,
5325 };
5326
5327 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
5328 sizeof(bt_rc_ctrl_interface),
5329 init_ctrl,
5330 send_passthrough_cmd,
5331 send_groupnavigation_cmd,
5332 change_player_app_setting,
5333 play_item_cmd,
5334 get_current_metadata_cmd,
5335 get_playback_state_cmd,
5336 get_now_playing_list_cmd,
5337 get_folder_list_cmd,
5338 get_player_list_cmd,
5339 change_folder_path_cmd,
5340 set_browsed_player_cmd,
5341 set_addressed_player_cmd,
5342 set_volume_rsp,
5343 volume_change_notification_rsp,
5344 cleanup_ctrl,
5345 };
5346
5347 /*******************************************************************************
5348 *
5349 * Function btif_rc_get_interface
5350 *
5351 * Description Get the AVRCP Target callback interface
5352 *
5353 * Returns btrc_interface_t
5354 *
5355 ******************************************************************************/
btif_rc_get_interface(void)5356 const btrc_interface_t* btif_rc_get_interface(void) {
5357 BTIF_TRACE_EVENT("%s: ", __func__);
5358 return &bt_rc_interface;
5359 }
5360
5361 /*******************************************************************************
5362 *
5363 * Function btif_rc_ctrl_get_interface
5364 *
5365 * Description Get the AVRCP Controller callback interface
5366 *
5367 * Returns btrc_ctrl_interface_t
5368 *
5369 ******************************************************************************/
btif_rc_ctrl_get_interface(void)5370 const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) {
5371 BTIF_TRACE_EVENT("%s: ", __func__);
5372 return &bt_rc_ctrl_interface;
5373 }
5374
5375 /*******************************************************************************
5376 * Function initialize_transaction
5377 *
5378 * Description Initializes fields of the transaction structure
5379 *
5380 * Returns void
5381 ******************************************************************************/
initialize_transaction(int lbl)5382 static void initialize_transaction(int lbl) {
5383 std::unique_lock<std::recursive_mutex> lock(device.lbllock);
5384 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5385 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
5386 clear_cmd_timeout(lbl);
5387 }
5388 device.transaction[lbl].lbl = lbl;
5389 device.transaction[lbl].in_use = false;
5390 device.transaction[lbl].handle = 0;
5391 }
5392 }
5393
5394 /*******************************************************************************
5395 * Function lbl_init
5396 *
5397 * Description Initializes label structures and mutexes.
5398 *
5399 * Returns void
5400 ******************************************************************************/
lbl_init()5401 void lbl_init() {
5402 memset(&device.transaction, 0, sizeof(device.transaction));
5403 init_all_transactions();
5404 }
5405
5406 /*******************************************************************************
5407 *
5408 * Function init_all_transactions
5409 *
5410 * Description Initializes all transactions
5411 *
5412 * Returns void
5413 ******************************************************************************/
init_all_transactions()5414 void init_all_transactions() {
5415 uint8_t txn_indx = 0;
5416 for (txn_indx = 0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++) {
5417 initialize_transaction(txn_indx);
5418 }
5419 }
5420
5421 /*******************************************************************************
5422 *
5423 * Function get_transaction_by_lbl
5424 *
5425 * Description Will return a transaction based on the label. If not inuse
5426 * will return an error.
5427 *
5428 * Returns bt_status_t
5429 ******************************************************************************/
get_transaction_by_lbl(uint8_t lbl)5430 rc_transaction_t* get_transaction_by_lbl(uint8_t lbl) {
5431 rc_transaction_t* transaction = NULL;
5432 std::unique_lock<std::recursive_mutex> lock(device.lbllock);
5433
5434 /* Determine if this is a valid label */
5435 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5436 if (!device.transaction[lbl].in_use) {
5437 transaction = NULL;
5438 } else {
5439 transaction = &(device.transaction[lbl]);
5440 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__, lbl);
5441 }
5442 }
5443
5444 return transaction;
5445 }
5446
5447 /*******************************************************************************
5448 *
5449 * Function get_transaction
5450 *
5451 * Description Obtains the transaction details.
5452 *
5453 * Returns bt_status_t
5454 ******************************************************************************/
5455
get_transaction(rc_transaction_t ** ptransaction)5456 static bt_status_t get_transaction(rc_transaction_t** ptransaction) {
5457 std::unique_lock<std::recursive_mutex> lock(device.lbllock);
5458
5459 // Check for unused transactions
5460 for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; i++) {
5461 if (!device.transaction[i].in_use) {
5462 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__,
5463 device.transaction[i].lbl);
5464 device.transaction[i].in_use = true;
5465 *ptransaction = &(device.transaction[i]);
5466 return BT_STATUS_SUCCESS;
5467 }
5468 }
5469 return BT_STATUS_NOMEM;
5470 }
5471
5472 /*******************************************************************************
5473 *
5474 * Function release_transaction
5475 *
5476 * Description Will release a transaction for reuse
5477 *
5478 * Returns bt_status_t
5479 ******************************************************************************/
release_transaction(uint8_t lbl)5480 void release_transaction(uint8_t lbl) {
5481 BTIF_TRACE_DEBUG("%s %d", __func__, lbl);
5482 rc_transaction_t* transaction = get_transaction_by_lbl(lbl);
5483
5484 /* If the transaction is in use... */
5485 if (transaction != NULL) {
5486 BTIF_TRACE_DEBUG("%s: lbl: %d", __func__, lbl);
5487 initialize_transaction(lbl);
5488 }
5489 }
5490
5491 /*******************************************************************************
5492 * Function sleep_ms
5493 *
5494 * Description Sleep the calling thread unconditionally for
5495 * |timeout_ms| milliseconds.
5496 *
5497 * Returns void
5498 ******************************************************************************/
sleep_ms(uint64_t timeout_ms)5499 static void sleep_ms(uint64_t timeout_ms) {
5500 struct timespec delay;
5501 delay.tv_sec = timeout_ms / 1000;
5502 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
5503
5504 OSI_NO_INTR(nanosleep(&delay, &delay));
5505 }
5506
absolute_volume_disabled()5507 static bool absolute_volume_disabled() {
5508 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
5509 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
5510 if (strncmp(volume_disabled, "true", 4) == 0) {
5511 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);
5512 return true;
5513 }
5514 return false;
5515 }
5516