DO NOT MERGE AVRCP: Proper handling of Fragmented AVCTP packet

- AVCTP : Allocate bigger buffer for reassembly
- AVRCP : Handle getelimentattr to eliminate duplicates
          and invalid attributes, this also fixes BOF.

Bug: 17669579
CRs-Fixed: 576831
Change-Id: I778c3df1386339ff8a00a755ffc9f24881b5167d
diff --git a/system/btif/src/btif_rc.c b/system/btif/src/btif_rc.c
index b2cd335..068d096 100755
--- a/system/btif/src/btif_rc.c
+++ b/system/btif/src/btif_rc.c
@@ -1008,9 +1008,33 @@
             }
             else
             {
-                num_attr = pavrc_cmd->get_elem_attrs.num_attr;
-                memcpy(element_attrs, pavrc_cmd->get_elem_attrs.attrs, sizeof(UINT32)
-                    *pavrc_cmd->get_elem_attrs.num_attr);
+                int attr_cnt, filled_attr_count;
+
+                num_attr = 0;
+                /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
+                 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
+                 * Fill only valid entries.
+                 */
+                for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
+                    (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
+                {
+                    if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
+                        (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
+                    {
+                        /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
+                         */
+                        for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
+                        {
+                            if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
+                                break;
+                        }
+                        if (filled_attr_count == num_attr)
+                        {
+                            element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
+                            num_attr++;
+                        }
+                    }
+                }
             }
             FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
             HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
diff --git a/system/stack/avct/avct_lcb_act.c b/system/stack/avct/avct_lcb_act.c
index 2fc9217..23ad332 100644
--- a/system/stack/avct/avct_lcb_act.c
+++ b/system/stack/avct/avct_lcb_act.c
@@ -89,17 +89,35 @@
             GKI_freebuf(p_lcb->p_rx_msg);
             AVCT_TRACE_WARNING0("Got start during reassembly");
         }
-        p_lcb->p_rx_msg = p_buf;
+        /* Allocate bigger buffer for reassembly. As lower layers are
+         * not aware of possible packet size after reassembly they
+         * would have allocated smaller buffer.
+         */
+        p_lcb->p_rx_msg = (BT_HDR*)GKI_getbuf(GKI_MAX_BUF_SIZE);
+        if (p_lcb->p_rx_msg == NULL)
+        {
+            AVCT_TRACE_ERROR0 ("Cannot alloc buffer for reassembly !!");
+            GKI_freebuf(p_buf);
+        }
+        else
+        {
+            memcpy (p_lcb->p_rx_msg, p_buf,
+                sizeof(BT_HDR) + p_buf->offset + p_buf->len);
+            /* Free original buffer */
+            GKI_freebuf(p_buf);
 
-        /* copy first header byte over nosp */
-        *(p + 1) = *p;
+            /* update p to point to new buffer */
+            p = (UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
 
-        /* set offset to point to where to copy next */
-        p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
+            /* copy first header byte over nosp */
+            *(p + 1) = *p;
 
-        /* adjust length for packet header */
-        p_lcb->p_rx_msg->len -= 1;
+            /* set offset to point to where to copy next */
+            p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
 
+            /* adjust length for packet header */
+            p_lcb->p_rx_msg->len -= 1;
+        }
         p_ret = NULL;
     }
     /* continue or end */