Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5cfa666 authored by Paul McLean's avatar Paul McLean
Browse files

Addressing ANR in BT-MIDI disconnect logic.

Also, don't attempt disconnect for non-BT-MIDI devices.

Bug: 216783547
Bug: 188924179
Bug: 216498842

Test: build, install, connect BLE-MIDI device. play a synthesizer to
verify

Change-Id: I7788264b304da2372da090c55db0a1e033c505d8
parent a1e7a448
Loading
Loading
Loading
Loading
+56 −19
Original line number Diff line number Diff line
@@ -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 {

@@ -117,6 +126,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
@@ -421,15 +433,20 @@ 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);
                                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);
                                        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);
                            }
@@ -469,6 +486,7 @@ public class MidiService extends IMidiManager.Stub {
        }

        public void removeDeviceConnection(DeviceConnection connection) {
            synchronized (mDevicesByInfo) {
                synchronized (mDeviceConnections) {
                    mDeviceConnections.remove(connection);

@@ -477,15 +495,14 @@ public class MidiService extends IMidiManager.Stub {
                        mServiceConnection = null;
                        if (mBluetoothDevice != null) {
                            // Bluetooth devices are ephemeral - remove when no clients exist
                        synchronized (mDevicesByInfo) {
                            closeLocked();
                        }
                        } else {
                            setDeviceServer(null);
                        }
                    }
                }
            }
        }

        // synchronize on mDevicesByInfo
        public void closeLocked() {
@@ -576,6 +593,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) {
@@ -590,6 +621,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;
@@ -598,8 +631,12 @@ public class MidiService extends IMidiManager.Stub {
                    Log.d(TAG, "ACTION_ACL_DISCONNECTED");
                    BluetoothDevice btDevice =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    // 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;
            }
        }