diff --git a/core/api/current.txt b/core/api/current.txt
index 69422212fb841..5145f03b9f091 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25710,6 +25710,7 @@ package android.media.midi {
public final class MidiDeviceInfo implements android.os.Parcelable {
method public int describeContents();
+ method public int getDefaultProtocol();
method public int getId();
method public int getInputPortCount();
method public int getOutputPortCount();
@@ -25726,6 +25727,14 @@ package android.media.midi {
field public static final String PROPERTY_SERIAL_NUMBER = "serial_number";
field public static final String PROPERTY_USB_DEVICE = "usb_device";
field public static final String PROPERTY_VERSION = "version";
+ field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3; // 0x3
+ field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4; // 0x4
+ field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1; // 0x1
+ field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2; // 0x2
+ field public static final int PROTOCOL_UMP_MIDI_2_0 = 17; // 0x11
+ field public static final int PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18; // 0x12
+ field public static final int PROTOCOL_UMP_USE_MIDI_CI = 0; // 0x0
+ field public static final int PROTOCOL_UNKNOWN = -1; // 0xffffffff
field public static final int TYPE_BLUETOOTH = 3; // 0x3
field public static final int TYPE_USB = 1; // 0x1
field public static final int TYPE_VIRTUAL = 2; // 0x2
@@ -25767,10 +25776,14 @@ package android.media.midi {
public final class MidiManager {
method public android.media.midi.MidiDeviceInfo[] getDevices();
+ method @NonNull public java.util.Collection getDevicesForTransport(int);
method public void openBluetoothDevice(android.bluetooth.BluetoothDevice, android.media.midi.MidiManager.OnDeviceOpenedListener, android.os.Handler);
method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.OnDeviceOpenedListener, android.os.Handler);
method public void registerDeviceCallback(android.media.midi.MidiManager.DeviceCallback, android.os.Handler);
+ method public void registerDeviceCallbackForTransport(@NonNull android.media.midi.MidiManager.DeviceCallback, @Nullable android.os.Handler, int);
method public void unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
+ field public static final int TRANSPORT_MIDI_BYTE_STREAM = 1; // 0x1
+ field public static final int TRANSPORT_UNIVERSAL_MIDI_PACKETS = 2; // 0x2
}
public static class MidiManager.DeviceCallback {
diff --git a/media/java/android/media/midi/IMidiManager.aidl b/media/java/android/media/midi/IMidiManager.aidl
index d3c8e0adb3ced..b03f785046358 100644
--- a/media/java/android/media/midi/IMidiManager.aidl
+++ b/media/java/android/media/midi/IMidiManager.aidl
@@ -31,6 +31,8 @@ interface IMidiManager
{
MidiDeviceInfo[] getDevices();
+ MidiDeviceInfo[] getDevicesForTransport(int transport);
+
// for device creation & removal notifications
void registerListener(IBinder clientToken, in IMidiDeviceListener listener);
void unregisterListener(IBinder clientToken, in IMidiDeviceListener listener);
@@ -43,7 +45,7 @@ interface IMidiManager
// for registering built-in MIDI devices
MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts,
int numOutputPorts, in String[] inputPortNames, in String[] outputPortNames,
- in Bundle properties, int type);
+ in Bundle properties, int type, int defaultProtocol);
// for unregistering built-in MIDI devices
void unregisterDeviceServer(in IMidiDeviceServer server);
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index dd3b6dbd6a399..b888fb00df9bb 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -16,11 +16,15 @@
package android.media.midi;
+import android.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* This class contains information to describe a MIDI device.
* For now we only have information that can be retrieved easily for USB devices,
@@ -53,6 +57,110 @@ public final class MidiDeviceInfo implements Parcelable {
*/
public static final int TYPE_BLUETOOTH = 3;
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use UMP to negotiate with the device with MIDI-CI.
+ * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_USE_MIDI_CI = 0;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 1.0 through UMP with packet sizes up to 64 bits.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 1.0 through UMP with packet sizes up to 64 bits and jitter reduction timestamps.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 1.0 through UMP with packet sizes up to 128 bits.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 1.0 through UMP with packet sizes up to 128 bits and jitter reduction timestamps.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 2.0 through UMP.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_2_0 = 17;
+
+ /**
+ * Constant representing a default protocol with Universal MIDI Packets (UMP).
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * All UMP data should be a multiple of 4 bytes.
+ * Use MIDI 2.0 through UMP and jitter reduction timestamps.
+ * Call {@link MidiManager#getDevicesForTransport} with parameter
+ * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18;
+
+ /**
+ * Constant representing a device with an unknown default protocol.
+ * If Universal MIDI Packets (UMP) are needed, use MIDI-CI through MIDI 1.0.
+ * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
+ * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
+ * @see MidiDeviceInfo#getDefaultProtocol
+ */
+ public static final int PROTOCOL_UNKNOWN = -1;
+
+ /**
+ * @see MidiDeviceInfo#getDefaultProtocol
+ * @hide
+ */
+ @IntDef(prefix = { "PROTOCOL_" }, value = {
+ PROTOCOL_UMP_USE_MIDI_CI,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS,
+ PROTOCOL_UMP_MIDI_2_0,
+ PROTOCOL_UMP_MIDI_2_0_AND_JRTS,
+ PROTOCOL_UNKNOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DefaultProtocol {}
+
/**
* Bundle key for the device's user visible name property.
* The value for this property is of type {@link java.lang.String}.
@@ -196,6 +304,7 @@ public final class MidiDeviceInfo implements Parcelable {
private final String[] mOutputPortNames;
private final Bundle mProperties;
private final boolean mIsPrivate;
+ private final int mDefaultProtocol;
/**
* MidiDeviceInfo should only be instantiated by MidiService implementation
@@ -203,7 +312,7 @@ public final class MidiDeviceInfo implements Parcelable {
*/
public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts,
String[] inputPortNames, String[] outputPortNames, Bundle properties,
- boolean isPrivate) {
+ boolean isPrivate, int defaultProtocol) {
// Check num ports for out-of-range values. Typical values will be
// between zero and three. More than 16 would be very unlikely
// because the port index field in the USB packet is only 4 bits.
@@ -234,6 +343,7 @@ public final class MidiDeviceInfo implements Parcelable {
}
mProperties = properties;
mIsPrivate = isPrivate;
+ mDefaultProtocol = defaultProtocol;
}
/**
@@ -312,6 +422,18 @@ public final class MidiDeviceInfo implements Parcelable {
return mIsPrivate;
}
+ /**
+ * Returns the default protocol. For most devices, this will be {@link #PROTOCOL_UNKNOWN}.
+ * Returning {@link #PROTOCOL_UNKNOWN} is not an error; the device just doesn't support
+ * Universal MIDI Packets by default.
+ *
+ * @return the device's default protocol.
+ */
+ @DefaultProtocol
+ public int getDefaultProtocol() {
+ return mDefaultProtocol;
+ }
+
@Override
public boolean equals(Object o) {
if (o instanceof MidiDeviceInfo) {
@@ -331,11 +453,12 @@ public final class MidiDeviceInfo implements Parcelable {
// This is a hack to force the mProperties Bundle to unparcel so we can
// print all the names and values.
mProperties.getString(PROPERTY_NAME);
- return ("MidiDeviceInfo[mType=" + mType +
- ",mInputPortCount=" + mInputPortCount +
- ",mOutputPortCount=" + mOutputPortCount +
- ",mProperties=" + mProperties +
- ",mIsPrivate=" + mIsPrivate);
+ return ("MidiDeviceInfo[mType=" + mType
+ + ",mInputPortCount=" + mInputPortCount
+ + ",mOutputPortCount=" + mOutputPortCount
+ + ",mProperties=" + mProperties
+ + ",mIsPrivate=" + mIsPrivate
+ + ",mDefaultProtocol=" + mDefaultProtocol);
}
public static final @android.annotation.NonNull Parcelable.Creator CREATOR =
@@ -349,10 +472,12 @@ public final class MidiDeviceInfo implements Parcelable {
String[] inputPortNames = in.createStringArray();
String[] outputPortNames = in.createStringArray();
boolean isPrivate = (in.readInt() == 1);
+ int defaultProtocol = in.readInt();
Bundle basicPropertiesIgnored = in.readBundle();
Bundle properties = in.readBundle();
return new MidiDeviceInfo(type, id, inputPortCount, outputPortCount,
- inputPortNames, outputPortNames, properties, isPrivate);
+ inputPortNames, outputPortNames, properties, isPrivate,
+ defaultProtocol);
}
public MidiDeviceInfo[] newArray(int size) {
@@ -390,6 +515,7 @@ public final class MidiDeviceInfo implements Parcelable {
parcel.writeStringArray(mInputPortNames);
parcel.writeStringArray(mOutputPortNames);
parcel.writeInt(mIsPrivate ? 1 : 0);
+ parcel.writeInt(mDefaultProtocol);
// "Basic" properties only contain properties of primitive types
// and thus can be read back by native code. "Extra" properties is
// a superset that contains all properties.
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index dee94c681e87a..a049a8891f48f 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -16,18 +16,25 @@
package android.media.midi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.SystemService;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.IBinder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -38,6 +45,39 @@ import java.util.concurrent.ConcurrentHashMap;
public final class MidiManager {
private static final String TAG = "MidiManager";
+ /**
+ * Constant representing MIDI devices.
+ * These devices do NOT support Universal MIDI Packets by default.
+ * These support the original MIDI 1.0 byte stream.
+ * When communicating to a USB device, a raw byte stream will be padded for USB.
+ * Likewise, for a Bluetooth device, the raw bytes will be converted for Bluetooth.
+ * For virtual devices, the byte stream will be passed directly.
+ * If Universal MIDI Packets are needed, please use MIDI-CI.
+ * @see MidiManager#getDevicesForTransport
+ */
+ public static final int TRANSPORT_MIDI_BYTE_STREAM = 1;
+
+ /**
+ * Constant representing Universal MIDI devices.
+ * These devices do support Universal MIDI Packets (UMP) by default.
+ * When sending data to these devices, please send UMP.
+ * Packets should always be a multiple of 4 bytes.
+ * UMP is defined in the USB MIDI 2.0 spec. Please read the standard for more info.
+ * @see MidiManager#getDevicesForTransport
+ */
+ public static final int TRANSPORT_UNIVERSAL_MIDI_PACKETS = 2;
+
+ /**
+ * @see MidiManager#getDevicesForTransport
+ * @hide
+ */
+ @IntDef(prefix = { "TRANSPORT_" }, value = {
+ TRANSPORT_MIDI_BYTE_STREAM,
+ TRANSPORT_UNIVERSAL_MIDI_PACKETS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Transport {}
+
/**
* Intent for starting BluetoothMidiService
* @hide
@@ -68,37 +108,43 @@ public final class MidiManager {
private class DeviceListener extends IMidiDeviceListener.Stub {
private final DeviceCallback mCallback;
private final Handler mHandler;
+ private final int mTransport;
- public DeviceListener(DeviceCallback callback, Handler handler) {
+ DeviceListener(DeviceCallback callback, Handler handler, int transport) {
mCallback = callback;
mHandler = handler;
+ mTransport = transport;
}
@Override
public void onDeviceAdded(MidiDeviceInfo device) {
- if (mHandler != null) {
- final MidiDeviceInfo deviceF = device;
- mHandler.post(new Runnable() {
- @Override public void run() {
- mCallback.onDeviceAdded(deviceF);
- }
- });
- } else {
- mCallback.onDeviceAdded(device);
+ if (shouldInvokeCallback(device)) {
+ if (mHandler != null) {
+ final MidiDeviceInfo deviceF = device;
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ mCallback.onDeviceAdded(deviceF);
+ }
+ });
+ } else {
+ mCallback.onDeviceAdded(device);
+ }
}
}
@Override
public void onDeviceRemoved(MidiDeviceInfo device) {
- if (mHandler != null) {
- final MidiDeviceInfo deviceF = device;
- mHandler.post(new Runnable() {
- @Override public void run() {
- mCallback.onDeviceRemoved(deviceF);
- }
- });
- } else {
- mCallback.onDeviceRemoved(device);
+ if (shouldInvokeCallback(device)) {
+ if (mHandler != null) {
+ final MidiDeviceInfo deviceF = device;
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ mCallback.onDeviceRemoved(deviceF);
+ }
+ });
+ } else {
+ mCallback.onDeviceRemoved(device);
+ }
}
}
@@ -115,6 +161,25 @@ public final class MidiManager {
mCallback.onDeviceStatusChanged(status);
}
}
+
+ /**
+ * Used to figure out whether callbacks should be invoked. Only invoke callbacks of
+ * the correct type.
+ *
+ * @param MidiDeviceInfo the device to check
+ * @return whether to invoke a callback
+ */
+ private boolean shouldInvokeCallback(MidiDeviceInfo device) {
+ // UMP devices have protocols that are not PROTOCOL_UNKNOWN
+ if (mTransport == TRANSPORT_UNIVERSAL_MIDI_PACKETS) {
+ return (device.getDefaultProtocol() != MidiDeviceInfo.PROTOCOL_UNKNOWN);
+ } else if (mTransport == TRANSPORT_MIDI_BYTE_STREAM) {
+ return (device.getDefaultProtocol() == MidiDeviceInfo.PROTOCOL_UNKNOWN);
+ } else {
+ Log.e(TAG, "Invalid transport type: " + mTransport);
+ return false;
+ }
+ }
}
/**
@@ -167,8 +232,10 @@ public final class MidiManager {
}
/**
- * Registers a callback to receive notifications when MIDI devices are added and removed.
- *
+ * Registers a callback to receive notifications when MIDI 1.0 devices are added and removed.
+ * These are devices that do not default to Universal MIDI Packets. To register for a callback
+ * for those, call {@link #registerDeviceCallbackForTransport} instead.
+
* The {@link DeviceCallback#onDeviceStatusChanged} method will be called immediately
* for any devices that have open ports. This allows applications to know which input
* ports are already in use and, therefore, unavailable.
@@ -182,7 +249,30 @@ public final class MidiManager {
* callback is unspecified.
*/
public void registerDeviceCallback(DeviceCallback callback, Handler handler) {
- DeviceListener deviceListener = new DeviceListener(callback, handler);
+ registerDeviceCallbackForTransport(callback, handler, TRANSPORT_MIDI_BYTE_STREAM);
+ }
+
+ /**
+ * Registers a callback to receive notifications when MIDI devices are added and removed
+ * for a specific transport type.
+ *
+ * The {@link DeviceCallback#onDeviceStatusChanged} method will be called immediately
+ * for any devices that have open ports. This allows applications to know which input
+ * ports are already in use and, therefore, unavailable.
+ *
+ * Applications should call {@link #getDevicesForTransport} before registering the callback
+ * to get a list of devices already added.
+ *
+ * @param callback a {@link DeviceCallback} for MIDI device notifications
+ * @param handler The {@link android.os.Handler Handler} that will be used for delivering the
+ * device notifications. If handler is null, then the thread used for the
+ * callback is unspecified.
+ * @param transport The transport to be used. This is either TRANSPORT_MIDI_BYTE_STREAM or
+ * TRANSPORT_UNIVERSAL_MIDI_PACKETS.
+ */
+ public void registerDeviceCallbackForTransport(@NonNull DeviceCallback callback,
+ @Nullable Handler handler, @Transport int transport) {
+ DeviceListener deviceListener = new DeviceListener(callback, handler, transport);
try {
mService.registerListener(mToken, deviceListener);
} catch (RemoteException e) {
@@ -208,9 +298,11 @@ public final class MidiManager {
}
/**
- * Gets the list of all connected MIDI devices.
+ * Gets a list of connected MIDI devices. This returns all devices that do
+ * not default to Universal MIDI Packets. To get those instead, please call
+ * {@link #getDevicesForTransport} instead.
*
- * @return an array of all MIDI devices
+ * @return an array of MIDI devices
*/
public MidiDeviceInfo[] getDevices() {
try {
@@ -220,6 +312,29 @@ public final class MidiManager {
}
}
+ /**
+ * Gets a list of connected MIDI devices by transport. TRANSPORT_MIDI_BYTE_STREAM
+ * is used for MIDI 1.0 and is the most common.
+ * For devices with built in Universal MIDI Packet support, use
+ * TRANSPORT_UNIVERSAL_MIDI_PACKETS instead.
+ *
+ * @param transport The transport to be used. This is either TRANSPORT_MIDI_BYTE_STREAM or
+ * TRANSPORT_UNIVERSAL_MIDI_PACKETS.
+ * @return a collection of MIDI devices
+ */
+ public @NonNull Collection getDevicesForTransport(@Transport int transport) {
+ try {
+ MidiDeviceInfo[] devices = mService.getDevicesForTransport(transport);
+ Collection out = new ArrayList(devices.length);
+ for (int i = 0; i < devices.length; i++) {
+ out.add(devices[i]);
+ }
+ return out;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private void sendOpenDeviceResponse(final MidiDevice device,
final OnDeviceOpenedListener listener, Handler handler) {
if (handler != null) {
@@ -311,13 +426,14 @@ public final class MidiManager {
/** @hide */
public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
int numOutputPorts, String[] inputPortNames, String[] outputPortNames,
- Bundle properties, int type, MidiDeviceServer.Callback callback) {
+ Bundle properties, int type, int defaultProtocol,
+ MidiDeviceServer.Callback callback) {
try {
MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers,
numOutputPorts, callback);
MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(),
inputPortReceivers.length, numOutputPorts, inputPortNames, outputPortNames,
- properties, type);
+ properties, type, defaultProtocol);
if (deviceInfo == null) {
Log.e(TAG, "registerVirtualDevice failed");
return null;
diff --git a/media/java/android/media/midi/package.html b/media/java/android/media/midi/package.html
index 33c54900cd07e..67df1b2fa3157 100644
--- a/media/java/android/media/midi/package.html
+++ b/media/java/android/media/midi/package.html
@@ -405,5 +405,46 @@ apps using the
MIDI device discovery calls described above.
+Using MIDI 2.0 over USB
+
+An app can use MIDI 2.0 over USB starting in Android T. MIDI 2.0 packets are embedded in
+Universal MIDI Packets, or UMP for short. A MIDI 2.0 USB device should create two interfaces,
+one endpoint that accepts only MIDI 1.0 packets and one that accepts only UMP packets.
+For more info about MIDI 2.0 and UMP, please read the MIDI 2.0 USB spec.
+
+MidiManager.getDevices() would simply return the 1.0 interface. This interface should work
+exactly the same as before. In order to use the new UMP interface, retrieve the device with the
+following code snippet.
+
+
+Collection<MidiDeviceInfo> universalDeviceInfos = midiManager.getDevicesForTransport(
+ MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS);
+
+
+UMP Packets are always in multiple of 4 bytes. For each set of 4 bytes, they are sent in network
+order. Compare the following NoteOn code snippet with the NoteOn code snippet above.
+
+
+byte[] buffer = new byte[32];
+int numBytes = 0;
+int channel = 3; // MIDI channels 1-16 are encoded as 0-15.
+int group = 0;
+buffer[numBytes++] = (byte)(0x20 + group); // MIDI 1.0 voice message
+buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
+buffer[numBytes++] = (byte)60; // pitch is middle C
+buffer[numBytes++] = (byte)127; // max velocity
+int offset = 0;
+// post is non-blocking
+inputPort.send(buffer, offset, numBytes);
+
+
+MIDI 2.0 messages can be sent through UMP after negotiating with the device. This is called
+MIDI-CI and is documented in the MIDI 2.0 spec. Some USB devices support pre-negotiated MIDI 2.0.
+For a MidiDeviceInfo, you can query the defaultProtocol.
+
+
+int defaultProtocol = info.getDefaultProtocol();
+
+