Check for BR/EDR transport when receiving ACL DISCONNECTED events
The ACTION_ACL_DISCONNECTED broadcast began sending events for both the
BR/EDR and LE transports, but consuming code was not utilizing the
transport when using it to decide if a profile's link was torn down or
not. This was causing the BR/EDR based map and pbap profiles to get torn
down when LE disconnections were happening.
Tag: #stability
Bug: 285326205
Test: atest BluetoothInstrumentationTests
(cherry picked from https://android-review.googlesource.com/q/commit:ce420b04203f03861d6d224b4ada5537730f63b3)
Merged-In: I186040b763cfea43e807f53b87fdbb4bff500d26
Change-Id: I186040b763cfea43e807f53b87fdbb4bff500d26
diff --git a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
index c99d79e..ab2d565 100644
--- a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
+++ b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
@@ -743,16 +743,23 @@
Log.e(TAG, "broadcast has NO device param!");
return;
}
- if (DBG) {
- Log.d(TAG, "broadcast has device: (" + device.getAddress() + ")");
- }
+
MceStateMachine stateMachine = mMapInstanceMap.get(device);
if (stateMachine == null) {
- Log.e(TAG, "No Statemachine found for the device from broadcast");
+ Log.e(TAG, "No Statemachine found for the device=" + device.toString());
return;
}
if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+ int transport =
+ intent.getIntExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.ERROR);
+ Log.i(TAG, "Received ACL disconnection event, device=" + device.toString()
+ + ", transport=" + transport);
+
+ if (transport != BluetoothDevice.TRANSPORT_BREDR) {
+ return;
+ }
+
if (stateMachine.getState() == BluetoothProfile.STATE_CONNECTED) {
stateMachine.disconnect();
}
@@ -761,7 +768,8 @@
if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
if (DBG) {
- Log.d(TAG, "UUID of SDP: " + uuid);
+ Log.d(TAG, "Received SDP Record event, device=" + device.toString() + ", uuid="
+ + uuid);
}
if (uuid.equals(BluetoothUuid.MAS)) {
diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
index 8845b86..50040dd 100644
--- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
+++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
@@ -293,6 +293,16 @@
if (DBG) Log.v(TAG, "onReceive" + action);
if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ int transport =
+ intent.getIntExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.ERROR);
+
+ Log.i(TAG, "Received ACL disconnection event, device=" + device.toString()
+ + ", transport=" + transport);
+
+ if (transport != BluetoothDevice.TRANSPORT_BREDR) {
+ return;
+ }
+
if (getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) {
disconnect(device);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java
index 060379d..9ec13b9 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java
@@ -26,12 +26,10 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Intent;
-import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -42,7 +40,6 @@
import com.android.bluetooth.btservice.storage.DatabaseManager;
import org.junit.After;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -278,7 +275,8 @@
}
@Test
- public void broadcastReceiver_withActionAclDisconnected_whenConnected_callsDisconnect() {
+ public void
+ broadcastReceiver_withActionAclDisconnectedNoTransport_whenConnected_doesNotCallDisconnect() {
int connectionState = BluetoothProfile.STATE_CONNECTED;
MceStateMachine sm = mock(MceStateMachine.class);
mService.getInstanceMap().put(mRemoteDevice, sm);
@@ -288,6 +286,38 @@
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
mService.mMapReceiver.onReceive(mService, intent);
+ verify(sm, never()).disconnect();
+ }
+
+ @Test
+ public void
+ broadcastReceiver_withActionAclDisconnectedLeTransport_whenConnected_doesNotCallDisconnect() {
+ int connectionState = BluetoothProfile.STATE_CONNECTED;
+ MceStateMachine sm = mock(MceStateMachine.class);
+ mService.getInstanceMap().put(mRemoteDevice, sm);
+ when(sm.getState()).thenReturn(connectionState);
+
+ Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
+ intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE);
+ mService.mMapReceiver.onReceive(mService, intent);
+
+ verify(sm, never()).disconnect();
+ }
+
+ @Test
+ public void
+ broadcastReceiver_withActionAclDisconnectedBrEdrTransport_whenConnected_callsDisconnect() {
+ int connectionState = BluetoothProfile.STATE_CONNECTED;
+ MceStateMachine sm = mock(MceStateMachine.class);
+ mService.getInstanceMap().put(mRemoteDevice, sm);
+ when(sm.getState()).thenReturn(connectionState);
+
+ Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
+ intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR);
+ mService.mMapReceiver.onReceive(mService, intent);
+
verify(sm).disconnect();
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java
index d01436d..7603c33 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -48,7 +49,6 @@
import org.junit.After;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
@@ -311,7 +311,7 @@
}
@Test
- public void broadcastReceiver_withActionAclDisconnected_callsDisconnect() {
+ public void broadcastReceiver_withActionAclDisconnectedNoTransport_doesNotCallDisconnect() {
int connectionState = BluetoothProfile.STATE_CONNECTED;
PbapClientStateMachine sm = mock(PbapClientStateMachine.class);
mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm);
@@ -321,6 +321,36 @@
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
mService.mPbapBroadcastReceiver.onReceive(mService, intent);
+ verify(sm, never()).disconnect(mRemoteDevice);
+ }
+
+ @Test
+ public void broadcastReceiver_withActionAclDisconnectedLeTransport_doesNotCallDisconnect() {
+ int connectionState = BluetoothProfile.STATE_CONNECTED;
+ PbapClientStateMachine sm = mock(PbapClientStateMachine.class);
+ mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm);
+ when(sm.getConnectionState(mRemoteDevice)).thenReturn(connectionState);
+
+ Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
+ intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE);
+ mService.mPbapBroadcastReceiver.onReceive(mService, intent);
+
+ verify(sm, never()).disconnect(mRemoteDevice);
+ }
+
+ @Test
+ public void broadcastReceiver_withActionAclDisconnectedBrEdrTransport_callsDisconnect() {
+ int connectionState = BluetoothProfile.STATE_CONNECTED;
+ PbapClientStateMachine sm = mock(PbapClientStateMachine.class);
+ mService.mPbapClientStateMachineMap.put(mRemoteDevice, sm);
+ when(sm.getConnectionState(mRemoteDevice)).thenReturn(connectionState);
+
+ Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
+ intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR);
+ mService.mPbapBroadcastReceiver.onReceive(mService, intent);
+
verify(sm).disconnect(mRemoteDevice);
}