From 42522c2417a87acf7e335b557662ef6ca95805d9 Mon Sep 17 00:00:00 2001
From: Joseph Pirozzo <pirozzoj@google.com>
Date: Wed, 11 Apr 2018 12:40:20 -0700
Subject: [PATCH] AVRCP controller browsing deep copy and get folder range

AVRCP browsing was unstable on the sink side due to bytes
being used instead of integers for get_folder_items_cmd
and a lack of deep copy in the data buffers.  This patch
allows both browse and vendor commands to work correctly.

Bug: 72496280
Test: stream music and browse at the same time.
Change-Id: Id4d34101c918947450923b68e087e6851ce99130
---
 system/btif/src/btif_av.cc      | 10 +++++++++
 system/btif/src/btif_rc.cc      | 39 +++++++++++++++++----------------
 system/include/hardware/bt_rc.h | 18 +++++++--------
 3 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index 0f59a989646..65b42ce7d09 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -774,6 +774,13 @@ void BtifAvEvent::DeepCopy(uint32_t event, const void* p_data,
           memcpy(p_msg_dest->vendor.p_vendor_data,
                  p_msg_src->vendor.p_vendor_data, p_msg_src->vendor.vendor_len);
         }
+        if ((p_msg_src->hdr.opcode == AVRC_OP_BROWSE) &&
+            p_msg_src->browse.p_browse_data && p_msg_src->browse.browse_len) {
+          p_msg_dest->browse.p_browse_data =
+              (uint8_t*)osi_calloc(p_msg_src->browse.browse_len);
+          memcpy(p_msg_dest->browse.p_browse_data,
+                 p_msg_src->browse.p_browse_data, p_msg_src->browse.browse_len);
+        }
       }
     } break;
 
@@ -792,6 +799,9 @@ void BtifAvEvent::DeepFree() {
         if (av->meta_msg.p_msg->hdr.opcode == AVRC_OP_VENDOR) {
           osi_free(av->meta_msg.p_msg->vendor.p_vendor_data);
         }
+        if (av->meta_msg.p_msg->hdr.opcode == AVRC_OP_BROWSE) {
+          osi_free(av->meta_msg.p_msg->browse.p_browse_data);
+        }
         osi_free_and_reset((void**)&av->meta_msg.p_msg);
       }
     } break;
diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc
index 72c82e56e16..861b1c2d156 100644
--- a/system/btif/src/btif_rc.cc
+++ b/system/btif/src/btif_rc.cc
@@ -321,7 +321,7 @@ void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
 void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
                                  btrc_folder_items_t* btrc_item);
 static bt_status_t get_folder_items_cmd(RawAddress* bd_addr, uint8_t scope,
-                                        uint8_t start_item, uint8_t num_items);
+                                        uint32_t start_item, uint32_t end_item);
 
 static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* p_param,
                                   uint8_t ctype, uint8_t label,
@@ -4500,18 +4500,18 @@ static bt_status_t get_playback_state_cmd(RawAddress* bd_addr) {
  * Description      Fetch the now playing list
  *
  * Paramters        start_item: First item to fetch (0 to fetch from beganning)
- *                  end_item: Last item to fetch (0xff to fetch until end)
+ *                  end_item: Last item to fetch (0xffffffff to fetch until end)
  *
  * Returns          BT_STATUS_SUCCESS if command issued successfully otherwise
  *                  BT_STATUS_FAIL.
  *
  **************************************************************************/
 static bt_status_t get_now_playing_list_cmd(RawAddress* bd_addr,
-                                            uint8_t start_item,
-                                            uint8_t num_items) {
-  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+                                            uint32_t start_item,
+                                            uint32_t end_item) {
+  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
   return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item,
-                              num_items);
+                              end_item);
 }
 
 /***************************************************************************
@@ -4521,17 +4521,17 @@ static bt_status_t get_now_playing_list_cmd(RawAddress* bd_addr,
  * Description      Fetch the currently selected folder list
  *
  * Paramters        start_item: First item to fetch (0 to fetch from beganning)
- *                  end_item: Last item to fetch (0xff to fetch until end)
+ *                  end_item: Last item to fetch (0xffffffff to fetch until end)
  *
  * Returns          BT_STATUS_SUCCESS if command issued successfully otherwise
  *                  BT_STATUS_FAIL.
  *
  **************************************************************************/
-static bt_status_t get_folder_list_cmd(RawAddress* bd_addr, uint8_t start_item,
-                                       uint8_t num_items) {
-  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+static bt_status_t get_folder_list_cmd(RawAddress* bd_addr, uint32_t start_item,
+                                       uint32_t end_item) {
+  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
   return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item,
-                              num_items);
+                              end_item);
 }
 
 /***************************************************************************
@@ -4541,17 +4541,17 @@ static bt_status_t get_folder_list_cmd(RawAddress* bd_addr, uint8_t start_item,
  * Description      Fetch the player list
  *
  * Paramters        start_item: First item to fetch (0 to fetch from beganning)
- *                  end_item: Last item to fetch (0xff to fetch until end)
+ *                  end_item: Last item to fetch (0xffffffff to fetch until end)
  *
  * Returns          BT_STATUS_SUCCESS if command issued successfully otherwise
  *                  BT_STATUS_FAIL.
  *
  **************************************************************************/
-static bt_status_t get_player_list_cmd(RawAddress* bd_addr, uint8_t start_item,
-                                       uint8_t num_items) {
-  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+static bt_status_t get_player_list_cmd(RawAddress* bd_addr, uint32_t start_item,
+                                       uint32_t end_item) {
+  BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
   return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
-                              num_items);
+                              end_item);
 }
 
 /***************************************************************************
@@ -4563,7 +4563,7 @@ static bt_status_t get_player_list_cmd(RawAddress* bd_addr, uint8_t start_item,
  * Paramters        direction: Direction (Up/Down) to change folder
  *                  uid: The UID of folder to move to
  *                  start_item: First item to fetch (0 to fetch from beganning)
- *                  end_item: Last item to fetch (0xff to fetch until end)
+ *                  end_item: Last item to fetch (0xffffffff to fetch until end)
  *
  * Returns          BT_STATUS_SUCCESS if command issued successfully otherwise
  *                  BT_STATUS_FAIL.
@@ -4715,14 +4715,15 @@ static bt_status_t set_addressed_player_cmd(RawAddress* bd_addr, uint16_t id) {
  * Paramters        scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable
  *                  content
  *                  start_item: First item to fetch (0 to fetch from beganning)
- *                  end_item: Last item to fetch (0xff to fetch until end)
+ *                  end_item: Last item to fetch (0xffff to fetch until end)
  *
  * Returns          BT_STATUS_SUCCESS if command issued successfully otherwise
  *                  BT_STATUS_FAIL.
  *
  **************************************************************************/
 static bt_status_t get_folder_items_cmd(RawAddress* bd_addr, uint8_t scope,
-                                        uint8_t start_item, uint8_t end_item) {
+                                        uint32_t start_item,
+                                        uint32_t end_item) {
   /* Check that both avrcp and browse channel are connected. */
   btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
   BTIF_TRACE_DEBUG("%s", __func__);
diff --git a/system/include/hardware/bt_rc.h b/system/include/hardware/bt_rc.h
index 3a8755721e8..4b54c8a82ac 100644
--- a/system/include/hardware/bt_rc.h
+++ b/system/include/hardware/bt_rc.h
@@ -600,7 +600,7 @@ typedef void (*btrc_ctrl_get_folder_items_callback)(
     const btrc_folder_items_t* folder_items, uint8_t count);
 
 typedef void (*btrc_ctrl_change_path_callback)(RawAddress* bd_addr,
-                                               uint8_t count);
+                                               uint32_t count);
 
 typedef void (*btrc_ctrl_set_browsed_player_callback)(RawAddress* bd_addr,
                                                       uint8_t num_items,
@@ -662,18 +662,18 @@ typedef struct {
   bt_status_t (*get_playback_state_cmd)(RawAddress* bd_addr);
 
   /** get the now playing list */
-  bt_status_t (*get_now_playing_list_cmd)(RawAddress* bd_addr, uint8_t start,
-                                          uint8_t items);
+  bt_status_t (*get_now_playing_list_cmd)(RawAddress* bd_addr, uint32_t start,
+                                          uint32_t end);
 
   /** get the folder list */
-  bt_status_t (*get_folder_list_cmd)(RawAddress* bd_addr, uint8_t start,
-                                     uint8_t items);
+  bt_status_t (*get_folder_list_cmd)(RawAddress* bd_addr, uint32_t start,
+                                     uint32_t end);
 
-  /** get the folder list */
-  bt_status_t (*get_player_list_cmd)(RawAddress* bd_addr, uint8_t start,
-                                     uint8_t items);
+  /** get the player list */
+  bt_status_t (*get_player_list_cmd)(RawAddress* bd_addr, uint32_t start,
+                                     uint32_t end);
 
-  /** get the folder list */
+  /** change the folder path */
   bt_status_t (*change_folder_path_cmd)(RawAddress* bd_addr, uint8_t direction,
                                         uint8_t* uid);
 
-- 
GitLab