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

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

Add BLE MIDI peripheral connection to standard BT connect UI

Bug: 25689266
Test: Connect to various BT MIDI peripherals and test function
with software synthesizer (DRC)

Change-Id: I1df2f3bfbc6302eb9d139546e825f2eb9b4abdd5
parent dbbc6fc4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -99,6 +99,12 @@ public class MidiFramer extends MidiReceiver {
                }
            } else { // data byte
                if (!mInSysEx) {
                    // Hack to avoid crashing if we start parsing in the middle
                    // of a data stream
                    if (mNeeded <= 0) {
                        break;
                    }

                    mBuffer[mCount++] = currentByte;
                    if (--mNeeded == 0) {
                        if (mRunningStatus != 0) {
+14 −0
Original line number Diff line number Diff line
@@ -31,12 +31,15 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

// BLE-MIDI

/**
 * This class is the public application interface to the MIDI service.
 */
@@ -399,9 +402,11 @@ public final class MidiManager {
        final OnDeviceOpenedListener listenerF = listener;
        final Handler handlerF = handler;

        Log.d(TAG, "openBluetoothDevice() " + bluetoothDevice);
        IMidiDeviceOpenCallback callback = new IMidiDeviceOpenCallback.Stub() {
            @Override
            public void onDeviceOpened(IMidiDeviceServer server, IBinder deviceToken) {
                Log.d(TAG, "onDeviceOpened() server:" + server);
                MidiDevice device = null;
                if (server != null) {
                    try {
@@ -423,6 +428,15 @@ public final class MidiManager {
        }
    }

    /** @hide */ // for now
    public void closeBluetoothDevice(@NonNull MidiDevice midiDevice) {
        try {
            midiDevice.close();
        } catch (IOException ex) {
            Log.e(TAG, "Exception closing BLE-MIDI device" + ex);
        }
    }

    /** @hide */
    public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
            int numOutputPorts, String[] inputPortNames, String[] outputPortNames,
+17 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.midi.MidiDevice;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceServer;
import android.media.midi.MidiDeviceStatus;
@@ -63,6 +64,7 @@ public final class BluetoothMidiDevice {
            "00002902-0000-1000-8000-00805f9b34fb");

    private final BluetoothDevice mBluetoothDevice;
    private final Context mContext;
    private final BluetoothMidiService mService;
    private final MidiManager mMidiManager;
    private MidiReceiver mOutputReceiver;
@@ -136,6 +138,8 @@ public final class BluetoothMidiDevice {
                        // switch to receiving notifications
                        mBluetoothGatt.readCharacteristic(characteristic);
                    }

                    openBluetoothDevice(mBluetoothDevice);
                }
            } else {
                Log.e(TAG, "onServicesDiscovered received: " + status);
@@ -249,6 +253,7 @@ public final class BluetoothMidiDevice {

        mBluetoothGatt = mBluetoothDevice.connectGatt(context, false, mGattCallback);

        mContext = context;
        mMidiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);

        Bundle properties = new Bundle();
@@ -310,6 +315,18 @@ public final class BluetoothMidiDevice {
        }
    }

    void openBluetoothDevice(BluetoothDevice btDevice) {
        Log.d(TAG, "openBluetoothDevice() device: " + btDevice);

        MidiManager midiManager = mContext.getSystemService(MidiManager.class);
        midiManager.openBluetoothDevice(btDevice,
                new MidiManager.OnDeviceOpenedListener() {
                    @Override
                    public void onDeviceOpened(MidiDevice device) {
                    }
                }, null);
    }

    public IBinder getBinder() {
        return mDeviceServer.asBinder();
    }
+77 −1
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.server.midi;

import android.annotation.NonNull;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -33,6 +35,7 @@ import android.media.midi.IMidiDeviceListener;
import android.media.midi.IMidiDeviceOpenCallback;
import android.media.midi.IMidiDeviceServer;
import android.media.midi.IMidiManager;
import android.media.midi.MidiDevice;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceService;
import android.media.midi.MidiDeviceStatus;
@@ -55,6 +58,7 @@ import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParser;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -99,6 +103,9 @@ public class MidiService extends IMidiManager.Stub {
    private final HashMap<BluetoothDevice, Device> mBluetoothDevices
            = new HashMap<BluetoothDevice, Device>();

    private final HashMap<BluetoothDevice, MidiDevice> mBleMidiDeviceMap =
            new HashMap<BluetoothDevice, MidiDevice>();

    // list of all devices, keyed by IMidiDeviceServer
    private final HashMap<IBinder, Device> mDevicesByServer = new HashMap<IBinder, Device>();

@@ -569,10 +576,45 @@ public class MidiService extends IMidiManager.Stub {
        }
    }

    private final BroadcastReceiver mBleMidiReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == null) {
                Log.w(TAG, "MidiService, action is null");
                return;
            }

            switch (action) {
                case BluetoothDevice.ACTION_ACL_CONNECTED: {
                    Log.d(TAG, "ACTION_ACL_CONNECTED");
                    BluetoothDevice btDevice =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    openBluetoothDevice(btDevice);
                }
                break;

                case BluetoothDevice.ACTION_ACL_DISCONNECTED: {
                    Log.d(TAG, "ACTION_ACL_DISCONNECTED");
                    BluetoothDevice btDevice =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    closeBluetoothDevice(btDevice);
                }
                break;
            }
        }
    };

    public MidiService(Context context) {
        mContext = context;
        mPackageManager = context.getPackageManager();

        // Setup broadcast receivers
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        context.registerReceiver(mBleMidiReceiver, filter);

        mBluetoothServiceUid = -1;
    }

@@ -701,9 +743,43 @@ public class MidiService extends IMidiManager.Stub {
        }
    }

    private void openBluetoothDevice(BluetoothDevice bluetoothDevice) {
        Log.d(TAG, "openBluetoothDevice() device: " + bluetoothDevice);

        MidiManager midiManager = mContext.getSystemService(MidiManager.class);
        midiManager.openBluetoothDevice(bluetoothDevice,
                new MidiManager.OnDeviceOpenedListener() {
                    @Override
                    public void onDeviceOpened(MidiDevice device) {
                        synchronized (mBleMidiDeviceMap) {
                            mBleMidiDeviceMap.put(bluetoothDevice, device);
                        }
                    }
                }, null);
    }

    private void closeBluetoothDevice(BluetoothDevice bluetoothDevice) {
        Log.d(TAG, "closeBluetoothDevice() device: " + bluetoothDevice);

        MidiDevice midiDevice;
        synchronized (mBleMidiDeviceMap) {
            midiDevice = mBleMidiDeviceMap.remove(bluetoothDevice);
        }

        if (midiDevice != null) {
            try {
                midiDevice.close();
            } catch (IOException ex) {
                Log.e(TAG, "Exception closing BLE-MIDI device" + ex);
            }
        }
    }

    @Override
    public void openBluetoothDevice(IBinder token, BluetoothDevice bluetoothDevice,
            IMidiDeviceOpenCallback callback) {
        Log.d(TAG, "openBluetoothDevice()");

        Client client = getClient(token);
        if (client == null) return;