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",