Merge "MidiManager: Add MIDI device status notifications"
diff --git a/media/java/android/media/midi/IMidiDeviceListener.aidl b/media/java/android/media/midi/IMidiDeviceListener.aidl
index 17d9bfd..31c66e3 100644
--- a/media/java/android/media/midi/IMidiDeviceListener.aidl
+++ b/media/java/android/media/midi/IMidiDeviceListener.aidl
@@ -17,10 +17,12 @@
package android.media.midi;
import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceStatus;
/** @hide */
oneway interface IMidiDeviceListener
{
void onDeviceAdded(in MidiDeviceInfo device);
void onDeviceRemoved(in MidiDeviceInfo device);
+ void onDeviceStatusChanged(in MidiDeviceStatus status);
}
diff --git a/media/java/android/media/midi/IMidiManager.aidl b/media/java/android/media/midi/IMidiManager.aidl
index 617b03e..a3b40d6 100644
--- a/media/java/android/media/midi/IMidiManager.aidl
+++ b/media/java/android/media/midi/IMidiManager.aidl
@@ -19,6 +19,7 @@
import android.media.midi.IMidiDeviceListener;
import android.media.midi.IMidiDeviceServer;
import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceStatus;
import android.os.Bundle;
import android.os.IBinder;
@@ -44,4 +45,11 @@
// used by MidiDeviceService to access the MidiDeviceInfo that was created based on its
// manifest's meta-data
MidiDeviceInfo getServiceDeviceInfo(String packageName, String className);
+
+ // used for client's to retrieve a device's MidiDeviceStatus
+ MidiDeviceStatus getDeviceStatus(in MidiDeviceInfo deviceInfo);
+
+ // used by MIDI devices to report their status
+ // the token is used by MidiService for death notification
+ void setDeviceStatus(IBinder token, in MidiDeviceStatus status);
}
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 6531052..b3c0e3a 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -16,8 +16,8 @@
package android.media.midi;
-import android.os.IBinder;
import android.os.Binder;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
@@ -61,7 +61,25 @@
private final CopyOnWriteArrayList<MidiInputPort> mInputPorts
= new CopyOnWriteArrayList<MidiInputPort>();
+
+ // for reporting device status
+ private final IBinder mDeviceStatusToken = new Binder();
+ private final boolean[] mInputPortBusy;
+ private final int[] mOutputPortOpenCount;
+
private final CloseGuard mGuard = CloseGuard.get();
+ private boolean mIsClosed;
+
+ private final Callback mCallback;
+
+ public interface Callback {
+ /**
+ * Called to notify when an our device status has changed
+ * @param server the {@link MidiDeviceServer} that changed
+ * @param status the {@link MidiDeviceStatus} for the device
+ */
+ public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status);
+ }
abstract private class PortClient implements IBinder.DeathRecipient {
final IBinder mToken;
@@ -96,7 +114,10 @@
void close() {
mToken.unlinkToDeath(this, 0);
synchronized (mInputPortOutputPorts) {
- mInputPortOutputPorts[mOutputPort.getPortNumber()] = null;
+ int portNumber = mOutputPort.getPortNumber();
+ mInputPortOutputPorts[portNumber] = null;
+ mInputPortBusy[portNumber] = false;
+ updateDeviceStatus();
}
IoUtils.closeQuietly(mOutputPort);
}
@@ -113,7 +134,15 @@
@Override
void close() {
mToken.unlinkToDeath(this, 0);
- mOutputPortDispatchers[mInputPort.getPortNumber()].getSender().disconnect(mInputPort);
+ int portNumber = mInputPort.getPortNumber();
+ MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
+ synchronized (dispatcher) {
+ dispatcher.getSender().disconnect(mInputPort);
+ int openCount = dispatcher.getReceiverCount();
+ mOutputPortOpenCount[portNumber] = openCount;
+ updateDeviceStatus();
+ }
+
mInputPorts.remove(mInputPort);
IoUtils.closeQuietly(mInputPort);
}
@@ -153,6 +182,8 @@
synchronized (mPortClients) {
mPortClients.put(token, client);
}
+ mInputPortBusy[portNumber] = true;
+ updateDeviceStatus();
return pair[1];
} catch (IOException e) {
Log.e(TAG, "unable to create ParcelFileDescriptors in openInputPort");
@@ -178,7 +209,14 @@
ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
OsConstants.SOCK_SEQPACKET);
MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber);
- mOutputPortDispatchers[portNumber].getSender().connect(inputPort);
+ MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
+ synchronized (dispatcher) {
+ dispatcher.getSender().connect(inputPort);
+ int openCount = dispatcher.getReceiverCount();
+ mOutputPortOpenCount[portNumber] = openCount;
+ updateDeviceStatus();
+ }
+
mInputPorts.add(inputPort);
OutputPortClient client = new OutputPortClient(token, inputPort);
synchronized (mPortClients) {
@@ -215,11 +253,12 @@
};
/* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
- int numOutputPorts) {
+ int numOutputPorts, Callback callback) {
mMidiManager = midiManager;
mInputPortReceivers = inputPortReceivers;
mInputPortCount = inputPortReceivers.length;
mOutputPortCount = numOutputPorts;
+ mCallback = callback;
mInputPortOutputPorts = new MidiOutputPort[mInputPortCount];
@@ -228,6 +267,9 @@
mOutputPortDispatchers[i] = new MidiDispatcher();
}
+ mInputPortBusy = new boolean[mInputPortCount];
+ mOutputPortOpenCount = new int[numOutputPorts];
+
mGuard.open("close");
}
@@ -242,9 +284,28 @@
mDeviceInfo = deviceInfo;
}
+ private void updateDeviceStatus() {
+ // clear calling identity, since we may be in a Binder call from one of our clients
+ long identityToken = Binder.clearCallingIdentity();
+
+ MidiDeviceStatus status = new MidiDeviceStatus(mDeviceInfo, mInputPortBusy,
+ mOutputPortOpenCount);
+ if (mCallback != null) {
+ mCallback.onDeviceStatusChanged(this, status);
+ }
+ try {
+ mMidiManager.setDeviceStatus(mDeviceStatusToken, status);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in updateDeviceStatus");
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
@Override
public void close() throws IOException {
synchronized (mGuard) {
+ if (mIsClosed) return;
mGuard.close();
for (int i = 0; i < mInputPortCount; i++) {
@@ -263,6 +324,7 @@
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in unregisterDeviceServer");
}
+ mIsClosed = true;
}
}
diff --git a/media/java/android/media/midi/MidiDeviceService.java b/media/java/android/media/midi/MidiDeviceService.java
index 64f69cd..5f55ae2 100644
--- a/media/java/android/media/midi/MidiDeviceService.java
+++ b/media/java/android/media/midi/MidiDeviceService.java
@@ -57,6 +57,13 @@
private MidiDeviceServer mServer;
private MidiDeviceInfo mDeviceInfo;
+ private final MidiDeviceServer.Callback mCallback = new MidiDeviceServer.Callback() {
+ @Override
+ public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status) {
+ MidiDeviceService.this.onDeviceStatusChanged(status);
+ }
+ };
+
@Override
public void onCreate() {
mMidiManager = IMidiManager.Stub.asInterface(
@@ -75,7 +82,7 @@
inputPortReceivers = new MidiReceiver[0];
}
server = new MidiDeviceServer(mMidiManager, inputPortReceivers,
- deviceInfo.getOutputPortCount());
+ deviceInfo.getOutputPortCount(), mCallback);
server.setDeviceInfo(deviceInfo);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in IMidiManager.getServiceDeviceInfo");
@@ -114,6 +121,13 @@
return mDeviceInfo;
}
+ /**
+ * Called to notify when an our {@link MidiDeviceStatus} has changed
+ * @param status the number of the port that was opened
+ */
+ public void onDeviceStatusChanged(MidiDeviceStatus status) {
+ }
+
@Override
public IBinder onBind(Intent intent) {
if (SERVICE_INTERFACE.equals(intent.getAction()) && mServer != null) {
diff --git a/media/java/android/media/midi/MidiDeviceStatus.aidl b/media/java/android/media/midi/MidiDeviceStatus.aidl
new file mode 100644
index 0000000..1a848c0
--- /dev/null
+++ b/media/java/android/media/midi/MidiDeviceStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.midi;
+
+parcelable MidiDeviceStatus;
diff --git a/media/java/android/media/midi/MidiDeviceStatus.java b/media/java/android/media/midi/MidiDeviceStatus.java
new file mode 100644
index 0000000..cc04889
--- /dev/null
+++ b/media/java/android/media/midi/MidiDeviceStatus.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.midi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This is an immutable class that describes the current status of a MIDI device's ports.
+ *
+ * CANDIDATE FOR PUBLIC API
+ * @hide
+ */
+public final class MidiDeviceStatus implements Parcelable {
+
+ private static final String TAG = "MidiDeviceStatus";
+
+ private final MidiDeviceInfo mDeviceInfo;
+ // true if input ports are busy
+ private final boolean mInputPortBusy[];
+ // open counts for output ports
+ private final int mOutputPortOpenCount[];
+
+ /**
+ * @hide
+ */
+ public MidiDeviceStatus(MidiDeviceInfo deviceInfo, boolean inputPortBusy[],
+ int outputPortOpenCount[]) {
+ // MidiDeviceInfo is immutable so we can share references
+ mDeviceInfo = deviceInfo;
+
+ // make copies of the arrays
+ mInputPortBusy = new boolean[inputPortBusy.length];
+ System.arraycopy(inputPortBusy, 0, mInputPortBusy, 0, inputPortBusy.length);
+ mOutputPortOpenCount = new int[outputPortOpenCount.length];
+ System.arraycopy(outputPortOpenCount, 0, mOutputPortOpenCount, 0,
+ outputPortOpenCount.length);
+ }
+
+ /**
+ * Creates a MidiDeviceStatus with false for all input port busy values
+ * and zero for all output port open counts
+ * @hide
+ */
+ public MidiDeviceStatus(MidiDeviceInfo deviceInfo) {
+ mDeviceInfo = deviceInfo;
+ mInputPortBusy = new boolean[deviceInfo.getInputPortCount()];
+ mOutputPortOpenCount = new int[deviceInfo.getOutputPortCount()];
+ }
+
+ /**
+ * Returns the {@link MidiDeviceInfo} of the device.
+ *
+ * @return the device info
+ */
+ public MidiDeviceInfo getDeviceInfo() {
+ return mDeviceInfo;
+ }
+
+ /**
+ * Returns true if an input port is busy.
+ *
+ * @param input port's port number
+ * @return input port busy status
+ */
+ public boolean isInputPortBusy(int portNumber) {
+ return mInputPortBusy[portNumber];
+ }
+
+ /**
+ * Returns the open count for an output port.
+ *
+ * @param output port's port number
+ * @return output port open count
+ */
+ public int getOutputPortOpenCount(int portNumber) {
+ return mOutputPortOpenCount[portNumber];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(mDeviceInfo.toString());
+ int inputPortCount = mDeviceInfo.getInputPortCount();
+ int outputPortCount = mDeviceInfo.getOutputPortCount();
+ builder.append(" mInputPortBusy=[");
+ for (int i = 0; i < inputPortCount; i++) {
+ builder.append(mInputPortBusy[i]);
+ if (i < inputPortCount -1) {
+ builder.append(",");
+ }
+ }
+ builder.append("] mOutputPortOpenCount=[");
+ for (int i = 0; i < outputPortCount; i++) {
+ builder.append(mOutputPortOpenCount[i]);
+ if (i < outputPortCount -1) {
+ builder.append(",");
+ }
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static final Parcelable.Creator<MidiDeviceStatus> CREATOR =
+ new Parcelable.Creator<MidiDeviceStatus>() {
+ public MidiDeviceStatus createFromParcel(Parcel in) {
+ ClassLoader classLoader = MidiDeviceInfo.class.getClassLoader();
+ MidiDeviceInfo deviceInfo = in.readParcelable(classLoader);
+ boolean[] inputPortBusy = in.createBooleanArray();
+ int[] outputPortOpenCount = in.createIntArray();
+ return new MidiDeviceStatus(deviceInfo, inputPortBusy, outputPortOpenCount);
+ }
+
+ public MidiDeviceStatus[] newArray(int size) {
+ return new MidiDeviceStatus[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeParcelable(mDeviceInfo, flags);
+ parcel.writeBooleanArray(mInputPortBusy);
+ parcel.writeIntArray(mOutputPortOpenCount);
+ }
+}
diff --git a/media/java/android/media/midi/MidiDispatcher.java b/media/java/android/media/midi/MidiDispatcher.java
index 90789e5..d13ca74 100644
--- a/media/java/android/media/midi/MidiDispatcher.java
+++ b/media/java/android/media/midi/MidiDispatcher.java
@@ -55,11 +55,11 @@
};
/**
- * Returns whether this dispatcher contains any receivers.
- * @return true if the receiver list is not empty
+ * Returns the number of {@link MidiReceiver}s this dispatcher contains.
+ * @return the number of receivers
*/
- public boolean hasReceivers() {
- return mReceivers.size() > 0;
+ public int getReceiverCount() {
+ return mReceivers.size();
}
/**
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index d7b8c57..bab9064 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -62,6 +62,7 @@
mHandler = handler;
}
+ @Override
public void onDeviceAdded(MidiDeviceInfo device) {
if (mHandler != null) {
final MidiDeviceInfo deviceF = device;
@@ -75,6 +76,7 @@
}
}
+ @Override
public void onDeviceRemoved(MidiDeviceInfo device) {
if (mHandler != null) {
final MidiDeviceInfo deviceF = device;
@@ -87,25 +89,49 @@
mCallback.onDeviceRemoved(device);
}
}
+
+ @Override
+ public void onDeviceStatusChanged(MidiDeviceStatus status) {
+ if (mHandler != null) {
+ final MidiDeviceStatus statusF = status;
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ mCallback.onDeviceStatusChanged(statusF);
+ }
+ });
+ } else {
+ mCallback.onDeviceStatusChanged(status);
+ }
+ }
}
/**
* Callback class used for clients to receive MIDI device added and removed notifications
*/
- abstract public static class DeviceCallback {
+ public static class DeviceCallback {
/**
* Called to notify when a new MIDI device has been added
*
* @param device a {@link MidiDeviceInfo} for the newly added device
*/
- abstract public void onDeviceAdded(MidiDeviceInfo device);
+ public void onDeviceAdded(MidiDeviceInfo device) {
+ }
/**
* Called to notify when a MIDI device has been removed
*
* @param device a {@link MidiDeviceInfo} for the removed device
*/
- abstract public void onDeviceRemoved(MidiDeviceInfo device);
+ public void onDeviceRemoved(MidiDeviceInfo device) {
+ }
+
+ /**
+ * Called to notify when the status of a MIDI device has changed
+ *
+ * @param device a {@link MidiDeviceStatus} for the changed device
+ */
+ public void onDeviceStatusChanged(MidiDeviceStatus status) {
+ }
}
/**
@@ -251,10 +277,10 @@
/** @hide */
public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
- int numOutputPorts, Bundle properties, int type) {
+ int numOutputPorts, Bundle properties, int type, MidiDeviceServer.Callback callback) {
try {
MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers,
- numOutputPorts);
+ numOutputPorts, callback);
MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(),
inputPortReceivers.length, numOutputPorts, properties, type);
if (deviceInfo == null) {
diff --git a/services/core/java/com/android/server/MidiService.java b/services/core/java/com/android/server/MidiService.java
index 7f98b30..d534548 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/core/java/com/android/server/MidiService.java
@@ -29,6 +29,7 @@
import android.media.midi.IMidiManager;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceService;
+import android.media.midi.MidiDeviceStatus;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -147,6 +148,19 @@
}
}
+ public void deviceStatusChanged(Device device, MidiDeviceStatus status) {
+ // ignore private devices that our client cannot access
+ if (!device.isUidAllowed(mUid)) return;
+
+ try {
+ for (IMidiDeviceListener listener : mListeners) {
+ listener.onDeviceStatusChanged(status);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "remote exception", e);
+ }
+ }
+
public void binderDied() {
removeClient(mToken);
}
@@ -187,6 +201,8 @@
private final class Device implements IBinder.DeathRecipient {
private final IMidiDeviceServer mServer;
private final MidiDeviceInfo mDeviceInfo;
+ private MidiDeviceStatus mDeviceStatus;
+ private IBinder mDeviceStatusToken;
// ServiceInfo for the device's MidiDeviceServer implementation (virtual devices only)
private final ServiceInfo mServiceInfo;
// UID of device implementation
@@ -204,6 +220,33 @@
return mDeviceInfo;
}
+ public MidiDeviceStatus getDeviceStatus() {
+ return mDeviceStatus;
+ }
+
+ public void setDeviceStatus(IBinder token, MidiDeviceStatus status) {
+ mDeviceStatus = status;
+
+ if (mDeviceStatusToken == null && token != null) {
+ // register a death recipient so we can clear the status when the device dies
+ try {
+ token.linkToDeath(new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ // reset to default status and clear the token
+ mDeviceStatus = new MidiDeviceStatus(mDeviceInfo);
+ mDeviceStatusToken = null;
+ notifyDeviceStatusChanged(Device.this, mDeviceStatus);
+ }
+ }, 0);
+ mDeviceStatusToken = token;
+ } catch (RemoteException e) {
+ // reset to default status
+ mDeviceStatus = new MidiDeviceStatus(mDeviceInfo);
+ }
+ }
+ }
+
public IMidiDeviceServer getDeviceServer() {
return mServer;
}
@@ -216,6 +259,10 @@
return (mServiceInfo == null ? null : mServiceInfo.packageName);
}
+ public int getUid() {
+ return mUid;
+ }
+
public boolean isUidAllowed(int uid) {
return (!mDeviceInfo.isPrivate() || mUid == uid);
}
@@ -302,13 +349,14 @@
@Override
public MidiDeviceInfo registerDeviceServer(IMidiDeviceServer server, int numInputPorts,
int numOutputPorts, Bundle properties, int type) {
- if (type != MidiDeviceInfo.TYPE_VIRTUAL && Binder.getCallingUid() != Process.SYSTEM_UID) {
+ int uid = Binder.getCallingUid();
+ if (type != MidiDeviceInfo.TYPE_VIRTUAL && uid != Process.SYSTEM_UID) {
throw new SecurityException("only system can create non-virtual devices");
}
synchronized (mDevicesByInfo) {
return addDeviceLocked(type, numInputPorts, numOutputPorts, properties,
- server, null, false, -1);
+ server, null, false, uid);
}
}
@@ -337,6 +385,39 @@
}
}
+ @Override
+ public MidiDeviceStatus getDeviceStatus(MidiDeviceInfo deviceInfo) {
+ Device device = mDevicesByInfo.get(deviceInfo);
+ if (device == null) {
+ throw new IllegalArgumentException("no such device for " + deviceInfo);
+ }
+ return device.getDeviceStatus();
+ }
+
+ @Override
+ public void setDeviceStatus(IBinder token, MidiDeviceStatus status) {
+ MidiDeviceInfo deviceInfo = status.getDeviceInfo();
+ Device device = mDevicesByInfo.get(deviceInfo);
+ if (device == null) {
+ // Just return quietly here if device no longer exists
+ return;
+ }
+ if (Binder.getCallingUid() != device.getUid()) {
+ throw new SecurityException("setDeviceStatus() caller UID " + Binder.getCallingUid()
+ + " does not match device's UID " + device.getUid());
+ }
+ device.setDeviceStatus(token, status);
+ notifyDeviceStatusChanged(device, status);
+ }
+
+ private void notifyDeviceStatusChanged(Device device, MidiDeviceStatus status) {
+ synchronized (mClients) {
+ for (Client c : mClients.values()) {
+ c.deviceStatusChanged(device, status);
+ }
+ }
+ }
+
// synchronize on mDevicesByInfo
private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts,
Bundle properties, IMidiDeviceServer server, ServiceInfo serviceInfo,
@@ -469,17 +550,15 @@
continue;
}
- int uid = -1;
- if (isPrivate) {
- try {
- ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
- serviceInfo.packageName, 0);
- uid = appInfo.uid;
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "could not fetch ApplicationInfo for "
- + serviceInfo.packageName);
- continue;
- }
+ int uid;
+ try {
+ ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+ serviceInfo.packageName, 0);
+ uid = appInfo.uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "could not fetch ApplicationInfo for "
+ + serviceInfo.packageName);
+ continue;
}
synchronized (mDevicesByInfo) {
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index f927965..725f393 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -121,7 +121,7 @@
int outputCount = mOutputStreams.length;
mServer = midiManager.createDeviceServer(mInputPortReceivers, outputCount,
- properties, MidiDeviceInfo.TYPE_USB);
+ properties, MidiDeviceInfo.TYPE_USB, null);
if (mServer == null) {
return false;
}