Add MIDI 2.0 host mode support
Adding MIDI 2.0 host mode support to Android. MIDI 2.0 peripherals
create an alternative setting for Universal Midi Packets (UMP).
UMP packets can be passed directly through as the host has full
control. Instead of going through the ALSA, UMP packets can be
sent directly through a UsbDeviceConnection.
This CL also adds public apis to expose whether the pipe supports
UMP. This for MidiDeviceInfo in Java and AMidi in c++.
Bug: 201003646
Bug: 214447324
Test: Verified that the MIDI 1.0 path still works as before.
Test: Tested that MIDI 2.0 packets are passed through the pipe
with MIDIScope and MIDIKeyboard
Test: atest MidiSoloTest
Test: atest CtsMidiTestCases
Test: NativeMidiEchoTest
Change-Id: Idff8a3b9bdd05857239260fc3e6af7253f8f992f
diff --git a/media/native/midi/MidiDeviceInfo.cpp b/media/native/midi/MidiDeviceInfo.cpp
index 8a573fb..1452488 100644
--- a/media/native/midi/MidiDeviceInfo.cpp
+++ b/media/native/midi/MidiDeviceInfo.cpp
@@ -64,6 +64,7 @@
RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
+ RETURN_IF_FAILED(parcel->writeInt32(mDefaultProtocol));
RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
// This corresponds to "extra" properties written by Java code
RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
@@ -83,6 +84,7 @@
int32_t isPrivate;
RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
mIsPrivate = isPrivate == 1;
+ RETURN_IF_FAILED(parcel->readInt32(&mDefaultProtocol));
RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
// Ignore "extra" properties as they may contain Java Parcelables
return OK;
@@ -130,7 +132,8 @@
areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
lhs.mProperties == rhs.mProperties &&
- lhs.mIsPrivate == rhs.mIsPrivate);
+ lhs.mIsPrivate == rhs.mIsPrivate &&
+ lhs.mDefaultProtocol == rhs.mDefaultProtocol);
}
} // namespace midi
diff --git a/media/native/midi/MidiDeviceInfo.h b/media/native/midi/MidiDeviceInfo.h
index 5b4a241..23e1cb4 100644
--- a/media/native/midi/MidiDeviceInfo.h
+++ b/media/native/midi/MidiDeviceInfo.h
@@ -38,6 +38,7 @@
int getType() const { return mType; }
int getUid() const { return mId; }
bool isPrivate() const { return mIsPrivate; }
+ int getDefaultProtocol() const { return mDefaultProtocol; }
const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
const Vector<String16>& getOutputPortNames() const { return mOutputPortNames; }
String16 getProperty(const char* propertyName);
@@ -48,6 +49,18 @@
TYPE_VIRTUAL = 2,
TYPE_BLUETOOTH = 3,
};
+
+ enum {
+ PROTOCOL_UMP_USE_MIDI_CI = 0,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3,
+ PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4,
+ PROTOCOL_UMP_MIDI_2_0 = 17,
+ PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18,
+ PROTOCOL_UNKNOWN = -1,
+ };
+
static const char* const PROPERTY_NAME;
static const char* const PROPERTY_MANUFACTURER;
static const char* const PROPERTY_PRODUCT;
@@ -72,6 +85,7 @@
Vector<String16> mOutputPortNames;
os::PersistableBundle mProperties;
bool mIsPrivate;
+ int32_t mDefaultProtocol;
};
} // namespace midi
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index f90796e..aa076e8 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -138,6 +138,7 @@
outDeviceInfoPtr->type = deviceInfo.getType();
outDeviceInfoPtr->inputPortCount = deviceInfo.getInputPortNames().size();
outDeviceInfoPtr->outputPortCount = deviceInfo.getOutputPortNames().size();
+ outDeviceInfoPtr->defaultProtocol = deviceInfo.getDefaultProtocol();
return AMEDIA_OK;
}
@@ -238,6 +239,13 @@
return device->deviceInfo.outputPortCount;
}
+AMidiDevice_Protocol AMIDI_API AMidiDevice_getDefaultProtocol(const AMidiDevice *device) {
+ if (device == nullptr) {
+ return AMIDI_DEVICE_PROTOCOL_UNKNOWN;
+ }
+ return static_cast<AMidiDevice_Protocol>(device->deviceInfo.defaultProtocol);
+}
+
/*
* Port Helpers
*/
diff --git a/media/native/midi/amidi_internal.h b/media/native/midi/amidi_internal.h
index fce8596..023a6f5 100644
--- a/media/native/midi/amidi_internal.h
+++ b/media/native/midi/amidi_internal.h
@@ -25,6 +25,7 @@
int32_t type; /* one of AMIDI_DEVICE_TYPE_* constants */
int32_t inputPortCount; /* number of input (send) ports associated with the device */
int32_t outputPortCount; /* number of output (received) ports associated with the device */
+ int32_t defaultProtocol; /* one of the AMIDI_DEVICE_PROTOCOL_* constants */
} AMidiDeviceInfo;
struct AMidiDevice {
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index 742db34..fbb7fb3 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -62,6 +62,78 @@
};
/*
+ * Protocol IDs for various MIDI devices.
+ *
+ * Introduced in API 33.
+ */
+enum AMidiDevice_Protocol : int32_t {
+ /**
+ * 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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_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.
+ */
+ AMIDI_DEVICE_PROTOCOL_UNKNOWN = -1
+};
+
+/*
* Device API
*/
/**
@@ -134,6 +206,30 @@
*/
ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
+/**
+ * Gets the MIDI device default protocol.
+ *
+ * @param device Specifies the MIDI device.
+ *
+ * @return The identifier of the MIDI device default protocol:
+ * AMIDI_DEVICE_PROTOCOL_UMP_USE_MIDI_CI
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0
+ * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0_AND_JRTS
+ * AMIDI_DEVICE_PROTOCOL_UNKNOWN
+ *
+ * Most devices should return PROTOCOL_UNKNOWN (-1). This is intentional as devices
+ * with default UMP support are not backwards compatible. When the device is null,
+ * return AMIDI_DEVICE_PROTOCOL_UNKNOWN.
+ *
+ * Available since API 33.
+ */
+AMidiDevice_Protocol AMIDI_API AMidiDevice_getDefaultProtocol(const AMidiDevice *device)
+ __INTRODUCED_IN(33);
+
/*
* API for receiving data from the Output port of a device.
*/
diff --git a/media/native/midi/libamidi.map.txt b/media/native/midi/libamidi.map.txt
index 62627f8..f25f977 100644
--- a/media/native/midi/libamidi.map.txt
+++ b/media/native/midi/libamidi.map.txt
@@ -2,6 +2,7 @@
global:
AMidiDevice_fromJava;
AMidiDevice_release;
+ AMidiDevice_getDefaultProtocol; # introduced=Tiramisu
AMidiDevice_getType;
AMidiDevice_getNumInputPorts;
AMidiDevice_getNumOutputPorts;