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;
         }