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