Merge "Handle unbonding in Hearing Aid profile"
diff --git a/audio_a2dp_hw/src/audio_a2dp_hw.cc b/audio_a2dp_hw/src/audio_a2dp_hw.cc
index 837e124..3622298 100644
--- a/audio_a2dp_hw/src/audio_a2dp_hw.cc
+++ b/audio_a2dp_hw/src/audio_a2dp_hw.cc
@@ -748,7 +748,8 @@
 static int a2dp_get_presentation_position_cmd(struct a2dp_stream_common* common,
                                               uint64_t* bytes, uint16_t* delay,
                                               struct timespec* timestamp) {
-  if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {  // Already disconnected
+  if ((common->ctrl_fd == AUDIO_SKT_DISCONNECTED) ||
+      (common->state != AUDIO_A2DP_STATE_STARTED)) {  // Audio is not streaming
     return -1;
   }
 
diff --git a/binder/android/bluetooth/IBluetoothHeadset.aidl b/binder/android/bluetooth/IBluetoothHeadset.aidl
index 60a92d2..f8dfb65 100644
--- a/binder/android/bluetooth/IBluetoothHeadset.aidl
+++ b/binder/android/bluetooth/IBluetoothHeadset.aidl
@@ -51,8 +51,8 @@
     void setAudioRouteAllowed(boolean allowed);
     boolean getAudioRouteAllowed();
     void setForceScoAudio(boolean forced);
-    boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device);
-    boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device);
+    boolean startScoUsingVirtualVoiceCall();
+    boolean stopScoUsingVirtualVoiceCall();
     oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
     void clccResponse(int index, int direction, int status, int mode, boolean mpty,
                       String number, int type);
diff --git a/btif/avrcp/avrcp_service.cc b/btif/avrcp/avrcp_service.cc
index 2508354..4338722 100644
--- a/btif/avrcp/avrcp_service.cc
+++ b/btif/avrcp/avrcp_service.cc
@@ -115,9 +115,9 @@
  public:
   MediaInterfaceWrapper(MediaInterface* cb) : wrapped_(cb){};
 
-  void SendKeyEvent(uint8_t key, uint8_t status) override {
+  void SendKeyEvent(uint8_t key, KeyState state) override {
     do_in_jni_thread(base::Bind(&MediaInterface::SendKeyEvent,
-                                base::Unretained(wrapped_), key, status));
+                                base::Unretained(wrapped_), key, state));
   }
 
   void GetSongInfo(SongInfoCallback info_cb) override {
diff --git a/include/hardware/avrcp/avrcp.h b/include/hardware/avrcp/avrcp.h
index dbd0ad9..8adba47 100644
--- a/include/hardware/avrcp/avrcp.h
+++ b/include/hardware/avrcp/avrcp.h
@@ -101,7 +101,7 @@
 // behavior in case the threading model changes on either side.
 class MediaInterface {
  public:
-  virtual void SendKeyEvent(uint8_t key, uint8_t status) = 0;
+  virtual void SendKeyEvent(uint8_t key, KeyState state) = 0;
 
   using SongInfoCallback = base::Callback<void(SongInfo)>;
   virtual void GetSongInfo(SongInfoCallback info_cb) = 0;
diff --git a/include/hardware/avrcp/avrcp_common.h b/include/hardware/avrcp/avrcp_common.h
index c805aa5..685eb1a 100644
--- a/include/hardware/avrcp/avrcp_common.h
+++ b/include/hardware/avrcp/avrcp_common.h
@@ -137,6 +137,11 @@
   DOWN = 0x01,
 };
 
+enum class KeyState : uint8_t {
+  PUSHED = 0x00,
+  RELEASED = 0x01,
+};
+
 class AttributeEntry {
  public:
   AttributeEntry(const Attribute& attribute, const std::string& value)
diff --git a/include/hardware/avrcp/avrcp_logging_helper.h b/include/hardware/avrcp/avrcp_logging_helper.h
index ce4951b..ce95337 100644
--- a/include/hardware/avrcp/avrcp_logging_helper.h
+++ b/include/hardware/avrcp/avrcp_logging_helper.h
@@ -226,5 +226,18 @@
   return os << DirectionText(dir);
 }
 
+inline std::string KeyStateText(const KeyState& state) {
+  switch (state) {
+    CASE_RETURN_TEXT(KeyState::PUSHED);
+    CASE_RETURN_TEXT(KeyState::RELEASED);
+    default:
+      return "Unknown KeyState: " + loghex((uint8_t)state);
+  }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const KeyState& dir) {
+  return os << KeyStateText(dir);
+}
+
 }  // namespace avrcp
 }  // namespace bluetooth
diff --git a/packet/avrcp/pass_through_packet.cc b/packet/avrcp/pass_through_packet.cc
index a384cc0..67b8d16 100644
--- a/packet/avrcp/pass_through_packet.cc
+++ b/packet/avrcp/pass_through_packet.cc
@@ -46,8 +46,9 @@
   return true;
 }
 
-bool PassThroughPacket::GetPushed() const {
-  return (*(begin() + Packet::kMinSize()) & 0b10000000) == 0;
+KeyState PassThroughPacket::GetKeyState() const {
+  auto it = begin() + Packet::kMinSize();
+  return static_cast<KeyState>(((*it) & 0b10000000) >> 7);
 }
 
 uint8_t PassThroughPacket::GetOperationId() const {
@@ -63,7 +64,7 @@
   ss << "  └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
   ss << "  └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
   ss << "  └ OpCode = " << GetOpcode() << std::endl;
-  ss << "  └ Pushed = " << GetPushed() << std::endl;
+  ss << "  └ Pushed = " << GetKeyState() << std::endl;
   ss << "  └ Opperation ID = " << loghex(GetOperationId()) << std::endl;
 
   return ss.str();
diff --git a/packet/avrcp/pass_through_packet.h b/packet/avrcp/pass_through_packet.h
index f2cf1d7..903b3d8 100644
--- a/packet/avrcp/pass_through_packet.h
+++ b/packet/avrcp/pass_through_packet.h
@@ -62,7 +62,7 @@
   static constexpr size_t kMinSize() { return Packet::kMinSize() + 2; }
 
   // Getter Functions
-  bool GetPushed() const;
+  KeyState GetKeyState() const;
   uint8_t GetOperationId() const;
 
   // Overloaded Functions
diff --git a/packet/tests/avrcp/pass_through_packet_test.cc b/packet/tests/avrcp/pass_through_packet_test.cc
index 0ef2879..5ea749f 100644
--- a/packet/tests/avrcp/pass_through_packet_test.cc
+++ b/packet/tests/avrcp/pass_through_packet_test.cc
@@ -42,11 +42,11 @@
 TEST(PassThroughPacketTest, getterTest) {
   auto test_packet =
       TestPassThroughPacket::Make(pass_through_command_play_pushed);
-  ASSERT_TRUE(test_packet->GetPushed());
+  ASSERT_EQ(test_packet->GetKeyState(), KeyState::PUSHED);
   ASSERT_EQ(test_packet->GetOperationId(), 0x44);
 
   test_packet = TestPassThroughPacket::Make(pass_through_command_play_released);
-  ASSERT_FALSE(test_packet->GetPushed());
+  ASSERT_EQ(test_packet->GetKeyState(), KeyState::RELEASED);
   ASSERT_EQ(test_packet->GetOperationId(), 0x44);
 }
 
diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc
index 6c442d4..aa5cc9c 100644
--- a/profile/avrcp/device.cc
+++ b/profile/avrcp/device.cc
@@ -491,14 +491,13 @@
     case Opcode::PASS_THROUGH: {
       auto pass_through_packet = Packet::Specialize<PassThroughPacket>(pkt);
       auto response = PassThroughPacketBuilder::MakeBuilder(
-          true, pass_through_packet->GetPushed(),
+          true, pass_through_packet->GetKeyState() == KeyState::PUSHED,
           pass_through_packet->GetOperationId());
       send_message(label, false, std::move(response));
 
-      // TODO (apanicke): Use an enum for media key ID's also handle
-      // other keys like forward and back for device switching.
+      // TODO (apanicke): Use an enum for media key ID's
       if (pass_through_packet->GetOperationId() == 0x44 &&
-          !pass_through_packet->GetPushed()) {
+          pass_through_packet->GetKeyState() == KeyState::PUSHED) {
         // We need to get the play status since we need to know
         // what the actual playstate is without being modified
         // by whether the device is active.
@@ -516,14 +515,16 @@
                 }
               }
 
-              d->media_interface_->SendKeyEvent(0x44, 0);
+              d->media_interface_->SendKeyEvent(0x44, KeyState::PUSHED);
             },
             base::Unretained(this)));
         return;
       }
 
-      media_interface_->SendKeyEvent(pass_through_packet->GetOperationId(),
-                                     pass_through_packet->GetPushed() ? 0 : 1);
+      if (IsActive()) {
+        media_interface_->SendKeyEvent(pass_through_packet->GetOperationId(),
+                                       pass_through_packet->GetKeyState());
+      }
     } break;
     case Opcode::VENDOR: {
       auto vendor_pkt = Packet::Specialize<VendorPacket>(pkt);
diff --git a/profile/avrcp/tests/avrcp_device_test.cc b/profile/avrcp/tests/avrcp_device_test.cc
index b005ec4..6e3bb17 100644
--- a/profile/avrcp/tests/avrcp_device_test.cc
+++ b/profile/avrcp/tests/avrcp_device_test.cc
@@ -762,7 +762,7 @@
 
   test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
 
-  // Pretend the device is active
+  // Pretend the device isn't active
   EXPECT_CALL(a2dp_interface, active_peer())
       .WillRepeatedly(Return(RawAddress::kEmpty));
 
@@ -814,5 +814,129 @@
   EXPECT_CALL(response_cb, Call(_, _, _)).Times(0);
 }
 
+TEST_F(AvrcpDeviceTest, playPushedActiveDeviceTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+  MockVolumeInterface vol_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+  // Pretend the device is active
+  EXPECT_CALL(a2dp_interface, active_peer())
+      .WillRepeatedly(Return(test_device->GetAddress()));
+
+  auto play_pushed = PassThroughPacketBuilder::MakeBuilder(false, true, 0x44);
+  auto play_pushed_response =
+      PassThroughPacketBuilder::MakeBuilder(true, true, 0x44);
+  EXPECT_CALL(response_cb,
+              Call(_, false, matchPacket(std::move(play_pushed_response))))
+      .Times(1);
+
+  PlayStatus status = {0x1234, 0x5678, PlayState::PLAYING};
+  EXPECT_CALL(interface, GetPlayStatus(_))
+      .Times(1)
+      .WillOnce(InvokeCb<0>(status));
+
+  EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::PUSHED)).Times(1);
+
+  auto play_pushed_pkt = TestAvrcpPacket::Make();
+  play_pushed->Serialize(play_pushed_pkt);
+
+  SendMessage(1, play_pushed_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, playPushedInactiveDeviceTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+  MockVolumeInterface vol_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+  // Pretend the device is not active
+  EXPECT_CALL(a2dp_interface, active_peer())
+      .WillRepeatedly(Return(RawAddress::kEmpty));
+
+  auto play_pushed = PassThroughPacketBuilder::MakeBuilder(false, true, 0x44);
+  auto play_pushed_response =
+      PassThroughPacketBuilder::MakeBuilder(true, true, 0x44);
+  EXPECT_CALL(response_cb,
+              Call(_, false, matchPacket(std::move(play_pushed_response))))
+      .Times(1);
+
+  // Expect that the device will try to set itself as active
+  EXPECT_CALL(interface, SetActiveDevice(test_device->GetAddress())).Times(1);
+
+  // No play command should be sent since the music is already playing
+  PlayStatus status = {0x1234, 0x5678, PlayState::PLAYING};
+  EXPECT_CALL(interface, GetPlayStatus(_))
+      .Times(1)
+      .WillOnce(InvokeCb<0>(status));
+  EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::PUSHED)).Times(0);
+
+  auto play_pushed_pkt = TestAvrcpPacket::Make();
+  play_pushed->Serialize(play_pushed_pkt);
+
+  SendMessage(1, play_pushed_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, mediaKeyActiveDeviceTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+  MockVolumeInterface vol_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+  // Pretend the device is active
+  EXPECT_CALL(a2dp_interface, active_peer())
+      .WillRepeatedly(Return(test_device->GetAddress()));
+
+  auto play_released =
+      PassThroughPacketBuilder::MakeBuilder(false, false, 0x44);
+  auto play_released_response =
+      PassThroughPacketBuilder::MakeBuilder(true, false, 0x44);
+  EXPECT_CALL(response_cb,
+              Call(_, false, matchPacket(std::move(play_released_response))))
+      .Times(1);
+
+  EXPECT_CALL(interface, GetPlayStatus(_)).Times(0);
+
+  EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::RELEASED)).Times(1);
+
+  auto play_released_pkt = TestAvrcpPacket::Make();
+  play_released->Serialize(play_released_pkt);
+
+  SendMessage(1, play_released_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, mediaKeyInactiveDeviceTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+  MockVolumeInterface vol_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+  // Pretend the device is not active
+  EXPECT_CALL(a2dp_interface, active_peer())
+      .WillRepeatedly(Return(RawAddress::kEmpty));
+
+  auto play_released =
+      PassThroughPacketBuilder::MakeBuilder(false, false, 0x44);
+  auto play_released_response =
+      PassThroughPacketBuilder::MakeBuilder(true, false, 0x44);
+  EXPECT_CALL(response_cb,
+              Call(_, false, matchPacket(std::move(play_released_response))))
+      .Times(1);
+
+  EXPECT_CALL(interface, GetPlayStatus(_)).Times(0);
+
+  // Expect that the key event wont be sent to the media interface
+  EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::RELEASED)).Times(0);
+
+  auto play_released_pkt = TestAvrcpPacket::Make();
+  play_released->Serialize(play_released_pkt);
+
+  SendMessage(1, play_released_pkt);
+}
+
 }  // namespace avrcp
 }  // namespace bluetooth
\ No newline at end of file
diff --git a/profile/avrcp/tests/avrcp_test_helper.h b/profile/avrcp/tests/avrcp_test_helper.h
index 594a0ae..16fc31f 100644
--- a/profile/avrcp/tests/avrcp_test_helper.h
+++ b/profile/avrcp/tests/avrcp_test_helper.h
@@ -33,7 +33,7 @@
 
 class MockMediaInterface : public MediaInterface {
  public:
-  MOCK_METHOD2(SendKeyEvent, void(uint8_t, uint8_t));
+  MOCK_METHOD2(SendKeyEvent, void(uint8_t, KeyState));
   MOCK_METHOD1(GetSongInfo, void(MediaInterface::SongInfoCallback));
   MOCK_METHOD1(GetPlayStatus, void(MediaInterface::PlayStatusCallback));
   MOCK_METHOD1(GetNowPlayingList, void(MediaInterface::NowPlayingCallback));
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc
index d023062..1f8263f 100644
--- a/stack/btm/btm_ble_gap.cc
+++ b/stack/btm/btm_ble_gap.cc
@@ -485,37 +485,38 @@
   BTM_TRACE_DEBUG("%s", __func__);
 
   /* Check status of command complete event */
-  if ((p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF) &&
-      (p_vcs_cplt_params->param_len > 0)) {
-    p = p_vcs_cplt_params->p_param_buf;
-    STREAM_TO_UINT8(status, p);
+  CHECK(p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF);
+  CHECK(p_vcs_cplt_params->param_len > 0);
+
+  p = p_vcs_cplt_params->p_param_buf;
+  STREAM_TO_UINT8(status, p);
+
+  if (status != HCI_SUCCESS) {
+    BTM_TRACE_DEBUG("%s: Status = 0x%02x (0 is success)", __func__, status);
+    return;
+  }
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
+  STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, p);
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.filter_support, p);
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_filter, p);
+  STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.energy_support, p);
+
+  if (p_vcs_cplt_params->param_len >
+      BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE) {
+    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.version_supported, p);
+  } else {
+    btm_cb.cmn_ble_vsc_cb.version_supported = BTM_VSC_CHIP_CAPABILITY_L_VERSION;
   }
 
-  if (status == HCI_SUCCESS) {
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
-    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, p);
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.filter_support, p);
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_filter, p);
-    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.energy_support, p);
-
-    if (p_vcs_cplt_params->param_len >
-        BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE) {
-      STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.version_supported, p);
-    } else {
-      btm_cb.cmn_ble_vsc_cb.version_supported =
-          BTM_VSC_CHIP_CAPABILITY_L_VERSION;
-    }
-
-    if (btm_cb.cmn_ble_vsc_cb.version_supported >=
-        BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
-      STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
-      STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
-      STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
-    }
-    btm_cb.cmn_ble_vsc_cb.values_read = true;
+  if (btm_cb.cmn_ble_vsc_cb.version_supported >=
+      BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
+    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
+    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
+    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
   }
+  btm_cb.cmn_ble_vsc_cb.values_read = true;
 
   BTM_TRACE_DEBUG(
       "%s: stat=%d, irk=%d, ADV ins:%d, rpa=%d, ener=%d, ext_scan=%d", __func__,
diff --git a/tools/mcap_tool/Android.bp b/tools/mcap_tool/Android.bp
index eec750c..137578d 100644
--- a/tools/mcap_tool/Android.bp
+++ b/tools/mcap_tool/Android.bp
@@ -29,7 +29,6 @@
       "system/bt/stack/include",
       "system/bt/btcore/include",
     ],
-    tags: ["debug", "optional"],
     shared_libs: [
       "libcutils",
       "libutils",