Merge branch android10-qpr3-release

Change-Id: I691b239eb1f526001707ee968c295a05853a6a4c
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 5f6e378..8b05056 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -76,6 +76,10 @@
     {
       "name" : "net_test_types",
       "host" : true
+    },
+    {
+      "name" : "net_test_btif_rc",
+      "host" : true
     }
   ]
 }
diff --git a/binder/android/bluetooth/IBluetoothManager.aidl b/binder/android/bluetooth/IBluetoothManager.aidl
index 2e12700..8a80d49 100644
--- a/binder/android/bluetooth/IBluetoothManager.aidl
+++ b/binder/android/bluetooth/IBluetoothManager.aidl
@@ -46,6 +46,8 @@
     String getAddress();
     String getName();
 
+    boolean onFactoryReset();
+
     boolean isBleScanAlwaysAvailable();
     int updateBleAppCount(IBinder b, boolean enable, String packageName);
     boolean isBleAppPresent();
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index b022b43..7cd7056 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -1246,7 +1246,6 @@
     open.chnl = p_scb->chnl;
     open.hndl = p_scb->hndl;
     open.status = BTA_AV_SUCCESS;
-    open.starting = bta_av_chk_start(p_scb);
     open.edr = 0;
     p = BTM_ReadRemoteFeatures(p_scb->PeerAddress());
     if (p != NULL) {
@@ -1262,8 +1261,10 @@
     bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr, p_scb->hdi);
 #endif
     if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) {
+      open.starting = false;
       open.sep = AVDT_TSEP_SNK;
     } else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK) {
+      open.starting = bta_av_chk_start(p_scb);
       open.sep = AVDT_TSEP_SRC;
     }
 
diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc
index a1a94b0..80effa3 100644
--- a/bta/av/bta_av_ssm.cc
+++ b/bta/av/bta_av_ssm.cc
@@ -329,7 +329,7 @@
     /* STR_RECONFIG_CFM_EVT */
     {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
     /* AVRC_TIMER_EVT */
-    {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START, BTA_AV_OPEN_SST},
+    {BTA_AV_OPEN_RC, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
     /* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
     /* AVDT_DISCONNECT_EVT */
     {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
diff --git a/bta/hf_client/bta_hf_client_rfc.cc b/bta/hf_client/bta_hf_client_rfc.cc
index f3e0947..535371f 100644
--- a/bta/hf_client/bta_hf_client_rfc.cc
+++ b/bta/hf_client/bta_hf_client_rfc.cc
@@ -127,6 +127,7 @@
     } else {
       APPL_TRACE_ERROR("%s: PORT_SUCCESS, ignoring handle = %d", __func__,
                        port_handle);
+      osi_free(p_buf);
       return;
     }
   } else if (client_cb != NULL &&
@@ -136,6 +137,10 @@
 
     RFCOMM_RemoveServer(port_handle);
     p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
+  } else if (client_cb == NULL) {
+    // client_cb is already cleaned due to hfp client disabled.
+    // Assigned a valid event value to header and send this message anyway.
+    p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
   }
 
   p_buf->hdr.layer_specific = client_cb != NULL ? client_cb->handle : 0;
diff --git a/btif/Android.bp b/btif/Android.bp
index f33d174..0ecf207 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -208,3 +208,36 @@
     ],
     cflags: ["-DBUILDCFG"],
 }
+
+// btif rc unit tests for target
+// ========================================================
+cc_test {
+    name: "net_test_btif_rc",
+    defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
+    host_supported: true,
+    include_dirs: btifCommonIncludes,
+    srcs: [
+        "test/btif_rc_test.cc",
+    ],
+    header_libs: ["libbluetooth_headers"],
+    shared_libs: [
+        "libcrypto",
+        "libcutils",
+        "liblog",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "libbluetooth-types",
+        "libbt-common",
+        "libbt-protos-lite",
+        "libosi",
+        "libosi-AllocationTestHarness",
+    ],
+    cflags: ["-DBUILDCFG"],
+    sanitize: {
+        address: true,
+        cfi: true,
+        misc_undefined: ["bounds"],
+    },
+}
diff --git a/btif/src/btif_a2dp_sink.cc b/btif/src/btif_a2dp_sink.cc
index bb1bc49..aa75d21 100644
--- a/btif/src/btif_a2dp_sink.cc
+++ b/btif/src/btif_a2dp_sink.cc
@@ -667,7 +667,6 @@
   LOG_INFO(LOG_TAG, "%s: state=%d", __func__, state);
   LockGuard lock(g_mutex);
 
-  if (!btif_av_is_connected()) return;
   APPL_TRACE_DEBUG("%s: setting focus state to %d", __func__, state);
   btif_a2dp_sink_cb.rx_focus_state = state;
   if (btif_a2dp_sink_cb.rx_focus_state == BTIF_A2DP_SINK_FOCUS_NOT_GRANTED) {
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index 9919a7b..575d83e 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -1836,6 +1836,12 @@
   BTIF_TRACE_DEBUG("%s", __func__);
   CHECK_RC_CONNECTED(p_dev);
 
+  if (num_attr > BTRC_MAX_ELEM_ATTR_SIZE) {
+    LOG(WARNING) << __func__
+                 << " Exceeded number attributes:" << static_cast<int>(num_attr)
+                 << " max:" << BTRC_MAX_ELEM_ATTR_SIZE;
+    num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
+  }
   memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
 
   if (num_attr == 0) {
@@ -1844,7 +1850,8 @@
     for (i = 0; i < num_attr; i++) {
       element_attrs[i].attr_id = p_attrs[i].attr_id;
       element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
-      element_attrs[i].name.str_len = (uint16_t)strlen((char*)p_attrs[i].text);
+      element_attrs[i].name.str_len =
+          (uint16_t)strnlen((char*)p_attrs[i].text, BTRC_MAX_ATTR_STR_LEN);
       element_attrs[i].name.p_str = p_attrs[i].text;
       BTIF_TRACE_DEBUG(
           "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__,
@@ -2939,11 +2946,12 @@
     return;
   }
   // interval is only valid for AVRC_EVT_PLAY_POS_CHANGED
-  uint32_t interval = 0;
+  uint32_t interval_in_seconds = 0;
   if (p_event->event_id == AVRC_EVT_PLAY_POS_CHANGED) {
-    interval = 2000;
+    interval_in_seconds = 2;
   }
-  status = register_notification_cmd(p_transaction->lbl, p_event->event_id, interval, p_dev);
+  status = register_notification_cmd(p_transaction->lbl, p_event->event_id,
+                                     interval_in_seconds, p_dev);
   if (status != BT_STATUS_SUCCESS) {
     BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__,
                      status);
@@ -3152,11 +3160,10 @@
           break;
         } else {
           uint8_t* p_data = p_rsp->param.track;
-          /* Update the UID for current track
-           * Attributes will be fetched after the AVRCP procedure
-           */
           BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
           get_play_status_cmd(p_dev);
+          get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list,
+                                    p_dev);
         }
         break;
 
@@ -3336,6 +3343,8 @@
     rc_ctrl_procedure_complete(p_dev);
     return;
   }
+  p_dev->rc_app_settings.num_attrs = 0;
+  p_dev->rc_app_settings.num_ext_attrs = 0;
 
   for (xx = 0; xx < p_rsp->num_attr; xx++) {
     uint8_t st_index;
@@ -3809,6 +3818,10 @@
   if (p_rsp->status == AVRC_STS_NO_ERROR) {
     do_in_jni_thread(
         FROM_HERE,
+        base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb, p_dev->rc_addr,
+                   (btrc_play_status_t)p_rsp->play_status));
+    do_in_jni_thread(
+        FROM_HERE,
         base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb,
                    p_dev->rc_addr, p_rsp->song_len, p_rsp->song_pos));
   } else {
@@ -3907,6 +3920,12 @@
                    /* We want to make the ownership explicit in native */
                    btrc_items, item_count));
 
+    if (item_count > 0) {
+      if (btrc_items[0].item_type == AVRC_ITEM_PLAYER &&
+          (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING)) {
+        list_player_app_setting_attrib_cmd(p_dev);
+      }
+    }
     /* Release the memory block for items and attributes allocated here.
      * Since the executor for do_in_jni_thread is a Single Thread Task Runner it
      * is okay to queue up the cleanup of btrc_items */
diff --git a/btif/test/btif_rc_test.cc b/btif/test/btif_rc_test.cc
new file mode 100644
index 0000000..6271881
--- /dev/null
+++ b/btif/test/btif_rc_test.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <cstdint>
+
+#include "bta/include/bta_av_api.h"
+#include "btif/include/btif_common.h"
+#include "device/include/interop.h"
+#include "include/hardware/bt_rc.h"
+#include "osi/test/AllocationTestHarness.h"
+#include "stack/include/btm_api_types.h"
+#include "types/raw_address.h"
+#undef LOG_TAG
+#include "btif/src/btif_rc.cc"
+
+extern void allocation_tracker_uninit(void);
+
+namespace {
+int AVRC_BldResponse_ = 0;
+}  // namespace
+
+uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING;
+uint8_t btif_trace_level = BT_TRACE_LEVEL_WARNING;
+
+tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) { return 0; }
+tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp,
+                           BT_HDR** pp_pkt) {
+  AVRC_BldResponse_++;
+  return 0;
+}
+tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) {
+  return 0;
+}
+tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
+                                 uint8_t* p_buf, uint16_t* buf_len) {
+  return 0;
+}
+tAVRC_STS AVRC_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result,
+                           uint8_t* p_buf, uint16_t buf_len) {
+  return 0;
+}
+tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
+                            UNUSED_ATTR uint8_t* p_buf,
+                            UNUSED_ATTR uint16_t buf_len) {
+  return 0;
+}
+void BTA_AvCloseRc(uint8_t rc_handle) {}
+void BTA_AvMetaCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CMD cmd_code,
+                   BT_HDR* p_pkt) {}
+void BTA_AvMetaRsp(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE rsp_code,
+                   BT_HDR* p_pkt) {}
+void BTA_AvRemoteCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_RC rc_id,
+                     tBTA_AV_STATE key_state) {}
+void BTA_AvRemoteVendorUniqueCmd(uint8_t rc_handle, uint8_t label,
+                                 tBTA_AV_STATE key_state, uint8_t* p_msg,
+                                 uint8_t buf_len) {}
+void BTA_AvVendorCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE cmd_code,
+                     uint8_t* p_data, uint16_t len) {}
+void BTA_AvVendorRsp(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE rsp_code,
+                     uint8_t* p_data, uint16_t len, uint32_t company_id) {}
+void btif_av_clear_remote_suspend_flag(void) {}
+bool btif_av_is_connected(void) { return false; }
+bool btif_av_is_sink_enabled(void) { return false; }
+RawAddress btif_av_sink_active_peer(void) { return RawAddress(); }
+RawAddress btif_av_source_active_peer(void) { return RawAddress(); }
+bool btif_av_stream_started_ready(void) { return false; }
+bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
+                                  char* p_params, int param_len,
+                                  tBTIF_COPY_CBACK* p_copy_cback) {
+  return BT_STATUS_SUCCESS;
+}
+const char* dump_rc_event(uint8_t event) { return nullptr; }
+const char* dump_rc_notification_event_id(uint8_t event_id) { return nullptr; }
+const char* dump_rc_pdu(uint8_t pdu) { return nullptr; }
+bt_status_t do_in_jni_thread(const base::Location& from_here,
+                             base::OnceClosure task) {
+  return BT_STATUS_SUCCESS;
+}
+base::MessageLoop* get_main_message_loop() { return nullptr; }
+bool interop_match_addr(const interop_feature_t feature,
+                        const RawAddress* addr) {
+  return false;
+}
+void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {}
+
+/**
+ * Test class to test selected functionality in hci/src/hci_layer.cc
+ */
+class BtifRcTest : public AllocationTestHarness {
+ protected:
+  void SetUp() override {
+    AllocationTestHarness::SetUp();
+    // Disable our allocation tracker to allow ASAN full range
+    allocation_tracker_uninit();
+  }
+
+  void TearDown() override { AllocationTestHarness::TearDown(); }
+};
+
+TEST_F(BtifRcTest, get_element_attr_rsp) {
+  RawAddress bd_addr;
+
+  btif_rc_cb.rc_multi_cb[0].rc_addr = bd_addr;
+  btif_rc_cb.rc_multi_cb[0].rc_connected = true;
+  btif_rc_cb.rc_multi_cb[0]
+      .rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP]
+      .is_rsp_pending = true;
+  btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
+
+  btrc_element_attr_val_t p_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+  uint8_t num_attr = BTRC_MAX_ELEM_ATTR_SIZE + 1;
+
+  CHECK(get_element_attr_rsp(bd_addr, num_attr, p_attrs) == BT_STATUS_SUCCESS);
+  CHECK(AVRC_BldResponse_ == 1);
+}
diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h
index 67a67c5..d122234 100644
--- a/internal_include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef BTA_DM_SDP_DB_SIZE
-#define BTA_DM_SDP_DB_SIZE 8000
+#define BTA_DM_SDP_DB_SIZE 20000
 #endif
 
 #ifndef HL_INCLUDED
diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc
index 4ca624b..264eaf0 100644
--- a/profile/avrcp/device.cc
+++ b/profile/avrcp/device.cc
@@ -98,6 +98,19 @@
       case CommandPdu::REGISTER_NOTIFICATION: {
         auto register_notification =
             Packet::Specialize<RegisterNotificationResponse>(pkt);
+
+        if (!register_notification->IsValid()) {
+          DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+          auto response =
+              RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
+                                         Status::INVALID_PARAMETER);
+          send_message(label, false, std::move(response));
+          active_labels_.erase(label);
+          volume_interface_ = nullptr;
+          volume_ = VOL_REGISTRATION_FAILED;
+          return;
+        }
+
         if (register_notification->GetEvent() != Event::VOLUME_CHANGED) {
           DEVICE_LOG(WARNING)
               << __func__ << ": Unhandled register notification received: "
@@ -336,16 +349,6 @@
     uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) {
   DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
 
-  if (!pkt->IsValid()) {
-    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
-    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
-    send_message(label, false, std::move(response));
-    active_labels_.erase(label);
-    volume_interface_ = nullptr;
-    volume_ = VOL_REGISTRATION_FAILED;
-    return;
-  }
-
   if (volume_interface_ == nullptr) return;
 
   if (pkt->GetCType() == CType::REJECTED) {
diff --git a/service/gatt_server.cc b/service/gatt_server.cc
index 52fd1ed..f46927d 100644
--- a/service/gatt_server.cc
+++ b/service/gatt_server.cc
@@ -18,6 +18,7 @@
 
 #include <base/logging.h>
 
+#include "osi/include/log.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 
@@ -116,6 +117,12 @@
     return false;
   }
 
+  if (offset < 0) {
+    android_errorWriteLog(0x534e4554, "143231677");
+    LOG(ERROR) << "Offset is less than 0 offset: " << offset;
+    return false;
+  }
+
   if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
     LOG(ERROR) << "Value is too large";
     return false;
diff --git a/stack/Android.bp b/stack/Android.bp
index f7f5a45..f9d11e2 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -200,6 +200,7 @@
     ],
     srcs: [
         "test/stack_a2dp_test.cc",
+        "test/stack_avrcp_test.cc",
     ],
     shared_libs: [
         "libcrypto",
diff --git a/stack/BUILD.gn b/stack/BUILD.gn
index 00680c8..87dc726 100644
--- a/stack/BUILD.gn
+++ b/stack/BUILD.gn
@@ -202,6 +202,7 @@
   testonly = true
   sources = [
     "test/stack_a2dp_test.cc",
+    "test/stack_avrcp_test.cc",
   ]
 
   include_dirs = [
diff --git a/stack/a2dp/a2dp_aac_decoder.cc b/stack/a2dp/a2dp_aac_decoder.cc
index d9cd85d..d998d7d 100644
--- a/stack/a2dp/a2dp_aac_decoder.cc
+++ b/stack/a2dp/a2dp_aac_decoder.cc
@@ -30,7 +30,7 @@
 typedef struct {
   HANDLE_AACDECODER aac_handle;
   bool has_aac_handle;  // True if aac_handle is valid
-  INT_PCM* decode_buf;
+  INT_PCM* decode_buf = nullptr;
   decoded_data_callback_t decode_callback;
 } tA2DP_AAC_DECODER_CB;
 
@@ -58,7 +58,7 @@
 void a2dp_aac_decoder_cleanup(void) {
   if (a2dp_aac_decoder_cb.has_aac_handle)
     aacDecoder_Close(a2dp_aac_decoder_cb.aac_handle);
-  free(a2dp_aac_decoder_cb.decode_buf);
+  osi_free(a2dp_aac_decoder_cb.decode_buf);
   memset(&a2dp_aac_decoder_cb, 0, sizeof(a2dp_aac_decoder_cb));
 }
 
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index 853f369..33fbfa7 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -985,18 +985,30 @@
  * Returns          Error code or zero if no error.
  *
  ******************************************************************************/
-static uint8_t avdt_msg_prs_rej(tAVDT_MSG* p_msg, uint8_t* p, uint8_t sig) {
-  if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG)) {
-    p_msg->hdr.err_param = *p++;
-    p_msg->hdr.err_code = *p;
-  } else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND)) {
-    AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param);
-    p_msg->hdr.err_code = *p;
+static uint8_t avdt_msg_prs_rej(tAVDT_MSG* p_msg, uint8_t* p, uint16_t len,
+                                uint8_t sig) {
+  uint8_t error = 0;
+
+  if (len > 0) {
+    if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG)) {
+      p_msg->hdr.err_param = *p++;
+      len--;
+    } else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND)) {
+      AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param);
+      len--;
+    }
+  }
+
+  if (len < 1) {
+    char error_info[] = "AVDT rejected response length mismatch";
+    android_errorWriteWithInfoLog(0x534e4554, "79702484", -1, error_info,
+                                  strlen(error_info));
+    error = AVDT_ERR_LENGTH;
   } else {
     p_msg->hdr.err_code = *p;
   }
 
-  return 0;
+  return error;
 }
 
 /*******************************************************************************
@@ -1604,7 +1616,7 @@
       evt = avdt_msg_rsp_2_evt[sig - 1];
     } else /* msg_type == AVDT_MSG_TYPE_REJ */
     {
-      err = avdt_msg_prs_rej(&msg, p, sig);
+      err = avdt_msg_prs_rej(&msg, p, p_buf->len, sig);
       evt = avdt_msg_rej_2_evt[sig - 1];
     }
 
diff --git a/stack/avrc/avrc_pars_ct.cc b/stack/avrc/avrc_pars_ct.cc
index 80dc882..39ed921 100644
--- a/stack/avrc/avrc_pars_ct.cc
+++ b/stack/avrc/avrc_pars_ct.cc
@@ -806,7 +806,7 @@
       if (len < min_len) goto length_error;
       BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
       BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
-      BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
+      BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p);
       break;
 
     case AVRC_PDU_SET_ADDRESSED_PLAYER:
diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc
index 22471bd..fe1db3d 100644
--- a/stack/avrc/avrc_pars_tg.cc
+++ b/stack/avrc/avrc_pars_tg.cc
@@ -363,7 +363,7 @@
  *
  * Description      This function is used to parse cmds received for CTRL
  *                  Currently it is for SetAbsVolume and Volume Change
- *                  Notification..
+ *                  Notification.
  *
  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
  *                  successfully.
@@ -390,6 +390,12 @@
   return status;
 }
 
+#define RETURN_STATUS_IF_FALSE(_status_, _b_, _msg_, ...) \
+  if (!(_b_)) {                                           \
+    AVRC_TRACE_DEBUG(_msg_, ##__VA_ARGS__);               \
+    return _status_;                                      \
+  }
+
 /*******************************************************************************
  *
  * Function         avrc_pars_browsing_cmd
@@ -409,6 +415,10 @@
   uint8_t* p = p_msg->p_browse_data;
   int count;
 
+  uint16_t min_len = 3;
+  RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                         "msg too short");
+
   p_result->pdu = *p++;
   AVRC_TRACE_DEBUG("avrc_pars_browsing_cmd() pdu:0x%x", p_result->pdu);
   /* skip over len */
@@ -416,11 +426,20 @@
 
   switch (p_result->pdu) {
     case AVRC_PDU_SET_BROWSED_PLAYER: /* 0x70 */
+      min_len += 2;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       // For current implementation all players are browsable.
       BE_STREAM_TO_UINT16(p_result->br_player.player_id, p);
       break;
 
     case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
+
+      min_len += 10;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       STREAM_TO_UINT8(p_result->get_items.scope, p);
       // To be modified later here (Scope) when all browsing commands are
       // supported
@@ -441,12 +460,21 @@
         if (buf_len < (count << 2))
           p_result->get_items.attr_count = count = (buf_len >> 2);
         for (int idx = 0; idx < count; idx++) {
+          min_len += 4;
+          RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
+                                 (p_msg->browse_len >= min_len),
+                                 "msg too short");
+
           BE_STREAM_TO_UINT32(p_result->get_items.p_attr_list[idx], p);
         }
       }
       break;
 
     case AVRC_PDU_CHANGE_PATH: /* 0x72 */
+      min_len += 11;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       BE_STREAM_TO_UINT16(p_result->chg_path.uid_counter, p);
       BE_STREAM_TO_UINT8(p_result->chg_path.direction, p);
       if (p_result->chg_path.direction != AVRC_DIR_UP &&
@@ -457,7 +485,12 @@
       break;
 
     case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */
+      min_len += 12;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       BE_STREAM_TO_UINT8(p_result->get_attrs.scope, p);
+
       if (p_result->get_attrs.scope > AVRC_SCOPE_NOW_PLAYING) {
         status = AVRC_STS_BAD_SCOPE;
         break;
@@ -473,6 +506,11 @@
           p_result->get_attrs.attr_count = count = (buf_len >> 2);
         for (int idx = 0, count = 0; idx < p_result->get_attrs.attr_count;
              idx++) {
+          min_len += 4;
+          RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
+                                 (p_msg->browse_len >= min_len),
+                                 "msg too short");
+
           BE_STREAM_TO_UINT32(p_result->get_attrs.p_attr_list[count], p);
           if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(
                   p_result->get_attrs.p_attr_list[count])) {
@@ -488,6 +526,10 @@
       break;
 
     case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: /* 0x75 */
+      ++min_len;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       BE_STREAM_TO_UINT8(p_result->get_num_of_items.scope, p);
       if (p_result->get_num_of_items.scope > AVRC_SCOPE_NOW_PLAYING) {
         status = AVRC_STS_BAD_SCOPE;
@@ -495,6 +537,10 @@
       break;
 
     case AVRC_PDU_SEARCH: /* 0x80 */
+      min_len += 4;
+      RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                             "msg too short");
+
       BE_STREAM_TO_UINT16(p_result->search.string.charset_id, p);
       BE_STREAM_TO_UINT16(p_result->search.string.str_len, p);
       p_result->search.string.p_str = p_buf;
@@ -504,6 +550,10 @@
         } else {
           android_errorWriteLog(0x534e4554, "63146237");
         }
+        min_len += p_result->search.string.str_len;
+        RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
+                               "msg too short");
+
         BE_STREAM_TO_ARRAY(p, p_buf, p_result->search.string.str_len);
       } else {
         status = AVRC_STS_INTERNAL_ERR;
diff --git a/stack/btm/btm_ble_multi_adv.cc b/stack/btm/btm_ble_multi_adv.cc
index 22d2e17..b425c09 100644
--- a/stack/btm/btm_ble_multi_adv.cc
+++ b/stack/btm/btm_ble_multi_adv.cc
@@ -728,16 +728,13 @@
       data.insert(data.begin(), flags.begin(), flags.end());
     }
 
-    // Find and fill TX Power with the correct value
-    if (data.size()) {
-      size_t i = 0;
-      while (i < data.size()) {
-        uint8_t type = data[i + 1];
-        if (type == HCI_EIR_TX_POWER_LEVEL_TYPE) {
-          data[i + 2] = adv_inst[inst_id].tx_power;
-        }
-        i += data[i] + 1;
+    // Find and fill TX Power with the correct value.
+    // The TX Power section is a 3 byte section.
+    for (size_t i = 0; (i + 2) < data.size();) {
+      if (data[i + 1] == HCI_EIR_TX_POWER_LEVEL_TYPE) {
+        data[i + 2] = adv_inst[inst_id].tx_power;
       }
+      i += data[i] + 1;
     }
 
     VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
diff --git a/stack/btm/btm_inq.cc b/stack/btm/btm_inq.cc
index ef16359..f56369b 100644
--- a/stack/btm/btm_inq.cc
+++ b/stack/btm/btm_inq.cc
@@ -915,10 +915,9 @@
   /* Make sure there is not already one in progress */
   if (p_inq->remname_active) {
     if (BTM_UseLeLink(p_inq->remname_bda)) {
-      if (btm_ble_cancel_remote_name(p_inq->remname_bda))
-        return (BTM_CMD_STARTED);
-      else
-        return (BTM_UNKNOWN_ADDR);
+      /* Cancel remote name request for LE device, and process remote name
+       * callback. */
+      btm_inq_rmt_name_failed_cancelled();
     } else
       btsnd_hcic_rmt_name_req_cancel(p_inq->remname_bda);
     return (BTM_CMD_STARTED);
@@ -2091,22 +2090,22 @@
 }
 
 void btm_inq_remote_name_timer_timeout(UNUSED_ATTR void* data) {
-  btm_inq_rmt_name_failed();
+  btm_inq_rmt_name_failed_cancelled();
 }
 
 /*******************************************************************************
  *
- * Function         btm_inq_rmt_name_failed
+ * Function         btm_inq_rmt_name_failed_cancelled
  *
- * Description      This function is if timeout expires while getting remote
- *                  name.  This is done for devices that incorrectly do not
- *                  report operation failure
+ * Description      This function is if timeout expires or request is cancelled
+ *                  while getting remote name.  This is done for devices that
+ *                  incorrectly do not report operation failure
  *
  * Returns          void
  *
  ******************************************************************************/
-void btm_inq_rmt_name_failed(void) {
-  BTM_TRACE_ERROR("btm_inq_rmt_name_failed()  remname_active=%d",
+void btm_inq_rmt_name_failed_cancelled(void) {
+  BTM_TRACE_ERROR("btm_inq_rmt_name_failed_cancelled()  remname_active=%d",
                   btm_cb.btm_inq_vars.remname_active);
 
   if (btm_cb.btm_inq_vars.remname_active)
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 88cb724..05180db 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -59,7 +59,7 @@
 
 extern void btm_process_remote_name(const RawAddress* bda, BD_NAME name,
                                     uint16_t evt_len, uint8_t hci_status);
-extern void btm_inq_rmt_name_failed(void);
+extern void btm_inq_rmt_name_failed_cancelled(void);
 extern void btm_inq_remote_name_timer_timeout(void* data);
 
 /* Inquiry related functions */
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index 245c537..52d5d60 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -48,6 +48,7 @@
 #include "btu.h"
 #include "common/metrics.h"
 #include "device/include/controller.h"
+#include "hci_evt_length.h"
 #include "hci_layer.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
@@ -257,6 +258,13 @@
   STREAM_TO_UINT8(hci_evt_code, p);
   STREAM_TO_UINT8(hci_evt_len, p);
 
+  // validate event size
+  if (hci_evt_len < hci_event_parameters_minimum_length[hci_evt_code]) {
+    HCI_TRACE_WARNING("%s: evt:0x%2X, malformed event of size %hhd", __func__,
+                      hci_evt_code, hci_evt_len);
+    return;
+  }
+
   btu_hcif_log_event_metrics(hci_evt_code, p);
 
   switch (hci_evt_code) {
diff --git a/stack/crypto_toolbox/aes_cmac.cc b/stack/crypto_toolbox/aes_cmac.cc
index 8b8246e..c90b80c 100644
--- a/stack/crypto_toolbox/aes_cmac.cc
+++ b/stack/crypto_toolbox/aes_cmac.cc
@@ -180,7 +180,8 @@
  *  length - length of the input in byte.
  */
 Octet16 aes_cmac(const Octet16& key, const uint8_t* input, uint16_t length) {
-  uint16_t len, diff;
+  uint32_t len;
+  uint16_t diff;
   /* n is number of rounds */
   uint16_t n = (length + OCTET16_LEN - 1) / OCTET16_LEN;
 
diff --git a/stack/include/hci_evt_length.h b/stack/include/hci_evt_length.h
new file mode 100644
index 0000000..ea8dfdf
--- /dev/null
+++ b/stack/include/hci_evt_length.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *  Definitions for HCI Event Parameter Minimum Length
+ */
+static const uint8_t hci_event_parameters_minimum_length[] = {
+    0,    //  0x00 - N/A
+    1,    //  0x01 - HCI_Inquiry_Complete Event
+    15,   //  0x02 - HCI_Inquiry_Result Event (Num_Responses = 1)
+    11,   //  0x03 - HCI_Connection_Complete Event
+    10,   //  0x04 - HCI_Connection_Request Event
+    4,    //  0x05 - HCI_Disconnection_Complete Event
+    3,    //  0x06 - HCI_Authentication_Complete Event
+    255,  //  0x07 - HCI_Remote_Name_Request_Complete Event
+    4,    //  0x08 - HCI_Encryption_Change Event
+    3,    //  0x09 - HCI_Change_Connection_Link_Key_Complete Event
+    4,    //  0x0A - HCI_Master_Link_Key_Complete Event
+    11,   //  0x0B - HCI_Read_Remote_Supported_Features_Complete Event
+    8,    //  0x0C - HCI_Read_Remote_Version_Information_Complete Event
+    21,   //  0x0D - HCI_QoS_Setup_Complete Event
+    3,    //  0x0E - HCI_Command_Complete Event (Depends on command)
+    4,    //  0x0F - HCI_Command_Status Event
+    1,    //  0x10 - HCI_Hardware_Error Event
+    2,    //  0x11 - HCI_Flush_Occurred Event
+    8,    //  0x12 - HCI_Role_Change Event
+    5,    //  0x13 - HCI_Number_Of_Completed_Packets Event (Num_Handles = 1)
+    6,    //  0x14 - HCI_Mode_Change Event
+    23,   //  0x15 - HCI_Return_Link_Keys Event (Num_Keys = 1)
+    6,    //  0x16 - HCI_PIN_Code_Request Event
+    6,    //  0x17 - HCI_Link_Key_Request Event
+    23,   //  0x18 - HCI_Link_Key_Notification Event
+    3,    //  0x19 - HCI_Loopback_Command Event (Depends on command)
+    1,    //  0x1A - HCI_Data_Buffer_Overflow Event
+    3,    //  0x1B - HCI_Max_Slots_Change Event
+    5,    //  0x1C - HCI_Read_Clock_Offset_Complete Event
+    5,    //  0x1D - HCI_Connection_Packet_Type_Changed Event
+    2,    //  0x1E - HCI_QoS_Violation Event
+    7,    //  0x1F - HCI_Page_Scan_Mode_Change Event (Deprecated)
+    7,    //  0x20 - HCI_Page_Scan_Repetition_Mode_Change Event
+    22,   //  0x21 - HCI_Flow_Specification_Complet Event
+    15,   //  0x22 - HCI_Inquiry_Result_with_RSSI Event (Num_Responses = 1)
+    13,   //  0x23 - HCI_Read_Remote_Extended_Features_Complete Event
+    0,    //  0x24 - N/A
+    0,    //  0x25 - N/A
+    0,    //  0x26 - N/A
+    0,    //  0x27 - N/A
+    0,    //  0x28 - N/A
+    0,    //  0x29 - N/A
+    0,    //  0x2A - N/A
+    0,    //  0x2B - N/A
+    17,   //  0x2C - HCI_Synchronous_Connection_Complete Event
+    9,    //  0x2D - HCI_Synchronous_Connection_Changed Event
+    11,   //  0x2E - HCI_Sniff_Subrating Event
+    255,  //  0x2F - HCI_Extended_Inquiry_Result Event
+    3,    //  0x30 - HCI_Encryption_Key_Refresh_Complete Event
+    6,    //  0x31 - HCI_IO_Capability_Request Event
+    9,    //  0x32 - HCI_IO_Capability_Response Event
+    10,   //  0x33 - HCI_User_Confirmation_Request Event
+    6,    //  0x34 - HCI_User_Passkey_Request Event
+    6,    //  0x35 - HCI_Remote_OOB_Data_Request Event
+    7,    //  0x36 - HCI_Simple_Pairing_Complete Event
+    0,    //  0x37 - N/A
+    4,    //  0x38 - HCI_Link_Supervision_Timeout_Changed Event
+    2,    //  0x39 - HCI_Enhanced_Flush_Complete Event
+    0,    //  0x3A - N/A
+    10,   //  0x3B - HCI_User_Passkey_Notification Event
+    7,    //  0x3C - HCI_Keypress_Notification Event
+    14,   //  0x3D - HCI_Remote_Host_Supported_Features_Notification Event
+    0,    //  0x3E - LE Meta event
+    0,    //  0x3F - N/A
+    2,    //  0x40 - HCI_Physical_Link_Complete Event
+    1,    //  0x41 - HCI_Channel_Selected Event
+    3,    //  0x42 - HCI_Disconnection_Physical_Link_Complete Event
+    2,    //  0x43 - HCI_Physical_Link_Loss_Early_Warning Event
+    1,    //  0x44 - HCI_Physical_Link_Recovery Event
+    5,    //  0x45 - HCI_Logical_Link_Complete Event
+    4,    //  0x46 - HCI_Disconnection_Logical_Link_Complete Event
+    3,    //  0x47 - HCI_Flow_Spec_Modify_Complete Event
+    9,    //  0x48 - HCI_Number_Of_Completed_Data_Blocks Event (Num_Handles = 1)
+    2,    //  0x49 - HCI_AMP_Start_Test Event
+    2,    //  0x4A - HCI_AMP_Test_End Event
+    18,   //  0x4B - HCI_AMP_Receiver_Report Event
+    3,    //  0x4C - HCI_Short_Range_Mode_Change_Complete Event
+    2,    //  0x4D - HCI_AMP_Status_Change Event
+    9,    //  0x4E - HCI_Triggered_Clock_Capture Event
+    1,    //  0x4F - HCI_Synchronization_Train_Complete Event
+    29,   //  0x50 - HCI_Synchronization_Train_Received Event
+    18,   //  0x51 - HCI_Connectionless_Slave_Broadcast_Receive Event
+          //  (Data_Length = 0)
+    7,    //  0x52 - HCI_Connectionless_Slave_Broadcast_Timeout Event
+    7,    //  0x53 - HCI_Truncated_Page_Complete Event
+    0,    //  0x54 - HCI_Slave_Page_Response_Timeout Event
+    10,   //  0x55 - HCI_Connectionless_Slave_Broadcast_Channel_Map_Change Event
+    4,    //  0x56 - HCI_Inquiry_Response_Notification Event
+    2,    //  0x57 - HCI_Authenticated_Payload_Timeout_Expired Event
+    8,    //  0x58 - HCI_SAM_Status_Change Event
+    0,    //  0x59 - N/A
+    0,    //  0x5A - N/A
+    0,    //  0x5B - N/A
+    0,    //  0x5C - N/A
+    0,    //  0x5D - N/A
+    0,    //  0x5E - N/A
+    0,    //  0x5F - N/A
+    0,    //  0x60 - N/A
+    0,    //  0x61 - N/A
+    0,    //  0x62 - N/A
+    0,    //  0x63 - N/A
+    0,    //  0x64 - N/A
+    0,    //  0x65 - N/A
+    0,    //  0x66 - N/A
+    0,    //  0x67 - N/A
+    0,    //  0x68 - N/A
+    0,    //  0x69 - N/A
+    0,    //  0x6A - N/A
+    0,    //  0x6B - N/A
+    0,    //  0x6C - N/A
+    0,    //  0x6D - N/A
+    0,    //  0x6E - N/A
+    0,    //  0x6F - N/A
+    0,    //  0x70 - N/A
+    0,    //  0x71 - N/A
+    0,    //  0x72 - N/A
+    0,    //  0x73 - N/A
+    0,    //  0x74 - N/A
+    0,    //  0x75 - N/A
+    0,    //  0x76 - N/A
+    0,    //  0x77 - N/A
+    0,    //  0x78 - N/A
+    0,    //  0x79 - N/A
+    0,    //  0x7A - N/A
+    0,    //  0x7B - N/A
+    0,    //  0x7C - N/A
+    0,    //  0x7D - N/A
+    0,    //  0x7E - N/A
+    0,    //  0x7F - N/A
+    0,    //  0x80 - N/A
+    0,    //  0x81 - N/A
+    0,    //  0x82 - N/A
+    0,    //  0x83 - N/A
+    0,    //  0x84 - N/A
+    0,    //  0x85 - N/A
+    0,    //  0x86 - N/A
+    0,    //  0x87 - N/A
+    0,    //  0x88 - N/A
+    0,    //  0x89 - N/A
+    0,    //  0x8A - N/A
+    0,    //  0x8B - N/A
+    0,    //  0x8C - N/A
+    0,    //  0x8D - N/A
+    0,    //  0x8E - N/A
+    0,    //  0x8F - N/A
+    0,    //  0x90 - N/A
+    0,    //  0x91 - N/A
+    0,    //  0x92 - N/A
+    0,    //  0x93 - N/A
+    0,    //  0x94 - N/A
+    0,    //  0x95 - N/A
+    0,    //  0x96 - N/A
+    0,    //  0x97 - N/A
+    0,    //  0x98 - N/A
+    0,    //  0x99 - N/A
+    0,    //  0x9A - N/A
+    0,    //  0x9B - N/A
+    0,    //  0x9C - N/A
+    0,    //  0x9D - N/A
+    0,    //  0x9E - N/A
+    0,    //  0x9F - N/A
+    0,    //  0xA0 - N/A
+    0,    //  0xA1 - N/A
+    0,    //  0xA2 - N/A
+    0,    //  0xA3 - N/A
+    0,    //  0xA4 - N/A
+    0,    //  0xA5 - N/A
+    0,    //  0xA6 - N/A
+    0,    //  0xA7 - N/A
+    0,    //  0xA8 - N/A
+    0,    //  0xA9 - N/A
+    0,    //  0xAA - N/A
+    0,    //  0xAB - N/A
+    0,    //  0xAC - N/A
+    0,    //  0xAD - N/A
+    0,    //  0xAE - N/A
+    0,    //  0xAF - N/A
+    0,    //  0xB0 - N/A
+    0,    //  0xB1 - N/A
+    0,    //  0xB2 - N/A
+    0,    //  0xB3 - N/A
+    0,    //  0xB4 - N/A
+    0,    //  0xB5 - N/A
+    0,    //  0xB6 - N/A
+    0,    //  0xB7 - N/A
+    0,    //  0xB8 - N/A
+    0,    //  0xB9 - N/A
+    0,    //  0xBA - N/A
+    0,    //  0xBB - N/A
+    0,    //  0xBC - N/A
+    0,    //  0xBD - N/A
+    0,    //  0xBE - N/A
+    0,    //  0xBF - N/A
+    0,    //  0xC0 - N/A
+    0,    //  0xC1 - N/A
+    0,    //  0xC2 - N/A
+    0,    //  0xC3 - N/A
+    0,    //  0xC4 - N/A
+    0,    //  0xC5 - N/A
+    0,    //  0xC6 - N/A
+    0,    //  0xC7 - N/A
+    0,    //  0xC8 - N/A
+    0,    //  0xC9 - N/A
+    0,    //  0xCA - N/A
+    0,    //  0xCB - N/A
+    0,    //  0xCC - N/A
+    0,    //  0xCD - N/A
+    0,    //  0xCE - N/A
+    0,    //  0xCF - N/A
+    0,    //  0xD0 - N/A
+    0,    //  0xD1 - N/A
+    0,    //  0xD2 - N/A
+    0,    //  0xD3 - N/A
+    0,    //  0xD4 - N/A
+    0,    //  0xD5 - N/A
+    0,    //  0xD6 - N/A
+    0,    //  0xD7 - N/A
+    0,    //  0xD8 - N/A
+    0,    //  0xD9 - N/A
+    0,    //  0xDA - N/A
+    0,    //  0xDB - N/A
+    0,    //  0xDC - N/A
+    0,    //  0xDD - N/A
+    0,    //  0xDE - N/A
+    0,    //  0xDF - N/A
+    0,    //  0xE0 - N/A
+    0,    //  0xE1 - N/A
+    0,    //  0xE2 - N/A
+    0,    //  0xE3 - N/A
+    0,    //  0xE4 - N/A
+    0,    //  0xE5 - N/A
+    0,    //  0xE6 - N/A
+    0,    //  0xE7 - N/A
+    0,    //  0xE8 - N/A
+    0,    //  0xE9 - N/A
+    0,    //  0xEA - N/A
+    0,    //  0xEB - N/A
+    0,    //  0xEC - N/A
+    0,    //  0xED - N/A
+    0,    //  0xEE - N/A
+    0,    //  0xEF - N/A
+    0,    //  0xF0 - N/A
+    0,    //  0xF1 - N/A
+    0,    //  0xF2 - N/A
+    0,    //  0xF3 - N/A
+    0,    //  0xF4 - N/A
+    0,    //  0xF5 - N/A
+    0,    //  0xF6 - N/A
+    0,    //  0xF7 - N/A
+    0,    //  0xF8 - N/A
+    0,    //  0xF9 - N/A
+    0,    //  0xFA - N/A
+    0,    //  0xFB - N/A
+    0,    //  0xFC - N/A
+    0,    //  0xFD - N/A
+    0,    //  0xFE - N/A
+    0,    //  0xFF - HCI_Vendor_Specific Event
+};
diff --git a/stack/test/stack_avrcp_test.cc b/stack/test/stack_avrcp_test.cc
new file mode 100644
index 0000000..ad1cc9e
--- /dev/null
+++ b/stack/test/stack_avrcp_test.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include <gtest/gtest.h>
+
+#include "stack/include/avrc_api.h"
+
+class StackAvrcpTest : public ::testing::Test {
+ protected:
+  StackAvrcpTest() = default;
+
+  virtual ~StackAvrcpTest() = default;
+};
+
+TEST_F(StackAvrcpTest, test_avrcp_parse_browse_cmd) {
+  uint8_t scratch_buf[512]{};
+  tAVRC_MSG msg{};
+  tAVRC_COMMAND result{};
+  uint8_t browse_cmd_buf[512]{};
+
+  msg.hdr.opcode = AVRC_OP_BROWSE;
+  msg.browse.p_browse_data = browse_cmd_buf;
+  msg.browse.browse_len = 2;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_SET_BROWSED_PLAYER;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  msg.browse.browse_len = 5;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_GET_FOLDER_ITEMS;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  msg.browse.browse_len = 13;
+  uint8_t* p = &browse_cmd_buf[3];
+  UINT8_TO_STREAM(p, AVRC_SCOPE_NOW_PLAYING);  // scope
+  UINT32_TO_STREAM(p, 0x00000001);             // start_item
+  UINT32_TO_STREAM(p, 0x00000002);             // end_item
+  browse_cmd_buf[12] = 0;                      // attr_count
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_CHANGE_PATH;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  msg.browse.browse_len = 14;
+  p = &browse_cmd_buf[3];
+  UINT16_TO_STREAM(p, 0x1234);      // uid_counter
+  UINT8_TO_STREAM(p, AVRC_DIR_UP);  // direction
+  UINT8_TO_STREAM(p, 0);            // attr_count
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_GET_ITEM_ATTRIBUTES;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  msg.browse.browse_len = 15;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  msg.browse.browse_len = 4;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+
+  memset(browse_cmd_buf, 0, sizeof(browse_cmd_buf));
+  browse_cmd_buf[0] = AVRC_PDU_SEARCH;
+  msg.browse.browse_len = 3;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_BAD_CMD);
+
+  p = &browse_cmd_buf[3];
+  UINT16_TO_STREAM(p, 0x0000);  // charset_id
+  UINT16_TO_STREAM(p, 0x0000);  // str_len
+  msg.browse.browse_len = 7;
+  EXPECT_EQ(AVRC_ParsCommand(&msg, &result, scratch_buf, sizeof(scratch_buf)),
+            AVRC_STS_NO_ERROR);
+}