MidiManager: Add MIDI device status notifications

MidiManager clients can be notified of device status changes via a new MidiDeviceStatus object.
MidiDeviceStatus contains the busy status of the device's input ports and number of
connections to the output ports.
MidiDeviceService now has an optional callback for receiving notifications when its ports change as well.

Change-Id: I1600df4464d82724bc026c27b9633ae9c412d3f0
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;
         }