Merge "Addressing ANR in BT-MIDI disconnect logic."

This commit is contained in:
Paul Mclean
2022-02-12 18:13:29 +00:00
committed by Android (Google) Code Review

View File

@@ -43,6 +43,7 @@ import android.media.midi.MidiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -64,6 +65,14 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
// NOTE about locking order:
// if there is a path that syncs on BOTH mDevicesByInfo AND mDeviceConnections,
// this order must be observed
// 1. synchronized (mDevicesByInfo)
// 2. synchronized (mDeviceConnections)
//TODO Introduce a single lock object to lock the whole state and avoid the requirement above.
public class MidiService extends IMidiManager.Stub {
@@ -122,6 +131,9 @@ public class MidiService extends IMidiManager.Stub {
// UID of BluetoothMidiService
private int mBluetoothServiceUid;
private static final UUID MIDI_SERVICE = UUID.fromString(
"03B80E5A-EDE8-4B33-A751-6CE34EC4C700");
// PackageMonitor for listening to package changes
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
@@ -434,14 +446,19 @@ public class MidiService extends IMidiManager.Stub {
public void onServiceConnected(ComponentName name, IBinder service) {
IMidiDeviceServer server = null;
if (mBluetoothDevice != null) {
IBluetoothMidiService mBluetoothMidiService = IBluetoothMidiService.Stub.asInterface(service);
try {
// We need to explicitly add the device in a separate method
// because onBind() is only called once.
IBinder deviceBinder = mBluetoothMidiService.addBluetoothDevice(mBluetoothDevice);
server = IMidiDeviceServer.Stub.asInterface(deviceBinder);
} catch(RemoteException e) {
Log.e(TAG, "Could not call addBluetoothDevice()", e);
IBluetoothMidiService mBluetoothMidiService =
IBluetoothMidiService.Stub.asInterface(service);
if (mBluetoothMidiService != null) {
try {
// We need to explicitly add the device in a separate method
// because onBind() is only called once.
IBinder deviceBinder =
mBluetoothMidiService.addBluetoothDevice(
mBluetoothDevice);
server = IMidiDeviceServer.Stub.asInterface(deviceBinder);
} catch (RemoteException e) {
Log.e(TAG, "Could not call addBluetoothDevice()", e);
}
}
} else {
server = IMidiDeviceServer.Stub.asInterface(service);
@@ -482,19 +499,19 @@ public class MidiService extends IMidiManager.Stub {
}
public void removeDeviceConnection(DeviceConnection connection) {
synchronized (mDeviceConnections) {
mDeviceConnections.remove(connection);
synchronized (mDevicesByInfo) {
synchronized (mDeviceConnections) {
mDeviceConnections.remove(connection);
if (mDeviceConnections.size() == 0 && mServiceConnection != null) {
mContext.unbindService(mServiceConnection);
mServiceConnection = null;
if (mBluetoothDevice != null) {
// Bluetooth devices are ephemeral - remove when no clients exist
synchronized (mDevicesByInfo) {
if (mDeviceConnections.size() == 0 && mServiceConnection != null) {
mContext.unbindService(mServiceConnection);
mServiceConnection = null;
if (mBluetoothDevice != null) {
// Bluetooth devices are ephemeral - remove when no clients exist
closeLocked();
} else {
setDeviceServer(null);
}
} else {
setDeviceServer(null);
}
}
}
@@ -589,6 +606,20 @@ public class MidiService extends IMidiManager.Stub {
}
}
// Note, this isn't useful at connect-time because the service UUIDs haven't
// been gathered yet.
private boolean isBLEMIDIDevice(BluetoothDevice btDevice) {
ParcelUuid[] uuids = btDevice.getUuids();
if (uuids != null) {
for (ParcelUuid uuid : uuids) {
if (uuid.getUuid().equals(MIDI_SERVICE)) {
return true;
}
}
}
return false;
}
private final BroadcastReceiver mBleMidiReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -603,6 +634,8 @@ public class MidiService extends IMidiManager.Stub {
Log.d(TAG, "ACTION_ACL_CONNECTED");
BluetoothDevice btDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// We can't determine here if this is a BLD-MIDI device, so go ahead and try
// to open as a MIDI device, further down it will get figured out.
openBluetoothDevice(btDevice);
}
break;
@@ -611,7 +644,11 @@ public class MidiService extends IMidiManager.Stub {
Log.d(TAG, "ACTION_ACL_DISCONNECTED");
BluetoothDevice btDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
closeBluetoothDevice(btDevice);
// We DO know at this point if we are disconnecting a MIDI device, so
// don't bother if we are not.
if (isBLEMIDIDevice(btDevice)) {
closeBluetoothDevice(btDevice);
}
}
break;
}