Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -174,6 +174,7 @@ LOCAL_SRC_FILES += \ core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \ core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \ core/java/android/hardware/usb/IUsbManager.aidl \ core/java/android/midi/IMidiDeviceServer.aidl \ core/java/android/midi/IMidiListener.aidl \ core/java/android/midi/IMidiManager.aidl \ core/java/android/net/IConnectivityManager.aidl \ Loading core/java/android/midi/MidiDevice.aidl→core/java/android/midi/IMidiDeviceServer.aidl +10 −3 Original line number Diff line number Diff line /* * Copyright (C) 2014, The Android Open Source Project * Copyright (C) 2014 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. Loading @@ -16,4 +16,11 @@ package android.midi; parcelable MidiDevice; import android.os.ParcelFileDescriptor; /** @hide */ interface IMidiDeviceServer { ParcelFileDescriptor openInputPort(int portNumber); ParcelFileDescriptor openOutputPort(int portNumber); } core/java/android/midi/IMidiManager.aidl +5 −11 Original line number Diff line number Diff line Loading @@ -16,13 +16,11 @@ package android.midi; import android.hardware.usb.UsbDevice; import android.midi.IMidiDeviceServer; import android.midi.IMidiListener; import android.midi.MidiDevice; import android.midi.MidiDeviceInfo; import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; /** @hide */ interface IMidiManager Loading @@ -34,14 +32,10 @@ interface IMidiManager void unregisterListener(IBinder token, in IMidiListener listener); // for communicating with MIDI devices ParcelFileDescriptor openDevice(IBinder token, in MidiDeviceInfo device); IMidiDeviceServer openDevice(IBinder token, in MidiDeviceInfo device); // for implementing virtual MIDI devices MidiDevice registerVirtualDevice(IBinder token, int numInputPorts, int numOutputPorts, in Bundle properties); void unregisterVirtualDevice(IBinder token, in MidiDeviceInfo device); // for use by UsbAudioManager void alsaDeviceAdded(int card, int device, in UsbDevice usbDevice); void alsaDeviceRemoved(in UsbDevice usbDevice); MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts, int numOutputPorts, in Bundle properties, boolean isPrivate, int type); void unregisterDeviceServer(in IMidiDeviceServer server); } core/java/android/midi/MidiDevice.java +30 −278 Original line number Diff line number Diff line Loading @@ -16,9 +16,8 @@ package android.midi; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import java.io.FileDescriptor; Loading @@ -30,114 +29,31 @@ import java.util.ArrayList; /** * This class is used for sending and receiving data to and from an MIDI device * Instances of this class are created by {@link MidiManager#openDevice}. * This class can also be used to provide the implementation for a virtual device. * * This class implements Parcelable so it can be returned from MidiService when creating * virtual MIDI devices. * * @hide */ public final class MidiDevice implements Parcelable { public final class MidiDevice { private static final String TAG = "MidiDevice"; private final MidiDeviceInfo mDeviceInfo; private ParcelFileDescriptor mParcelFileDescriptor; private FileInputStream mInputStream; private FileOutputStream mOutputStream; // lazily populated lists of ports private final MidiInputPort[] mInputPorts; private final MidiOutputPort[] mOutputPorts; // array of receiver lists, indexed by port number private final ArrayList<MidiReceiver>[] mReceivers; private int mReceiverCount; // total number of receivers for all ports /** * Minimum size of packed message as sent through our ParcelFileDescriptor * 8 bytes for timestamp, 1 byte for port number and 1 to 3 bytes for message * @hide */ public static final int MIN_PACKED_MESSAGE_SIZE = 10; private final IMidiDeviceServer mServer; /** * Maximum size of packed message as sent through our ParcelFileDescriptor * 8 bytes for timestamp, 1 byte for port number and 1 to 3 bytes for message * MidiDevice should only be instantiated by MidiManager * @hide */ public static final int MAX_PACKED_MESSAGE_SIZE = 12; // This thread reads MIDI events from a socket and distributes them to the list of // MidiReceivers attached to this device. private final Thread mThread = new Thread() { @Override public void run() { byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE]; ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>(); try { while (true) { // read next event int count = mInputStream.read(buffer); if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) { Log.e(TAG, "Number of bytes read out of range: " + count); break; } int offset = getMessageOffset(buffer, count); int size = getMessageSize(buffer, count); long timestamp = getMessageTimeStamp(buffer, count); int port = getMessagePortNumber(buffer, count); synchronized (mReceivers) { ArrayList<MidiReceiver> receivers = mReceivers[port]; if (receivers != null) { for (int i = 0; i < receivers.size(); i++) { MidiReceiver receiver = receivers.get(i); try { receivers.get(i).onPost(buffer, offset, size, timestamp); } catch (IOException e) { Log.e(TAG, "post failed"); deadReceivers.add(receiver); } } // remove any receivers that failed if (deadReceivers.size() > 0) { for (MidiReceiver receiver: deadReceivers) { receivers.remove(receiver); mReceiverCount--; } deadReceivers.clear(); } if (receivers.size() == 0) { mReceivers[port] = null; } // exit if we have no receivers left if (mReceiverCount == 0) { break; } } } } } catch (IOException e) { Log.e(TAG, "read failed"); } public MidiDevice(MidiDeviceInfo deviceInfo, IMidiDeviceServer server) { mDeviceInfo = deviceInfo; mServer = server; } }; /** * MidiDevice should only be instantiated by MidiManager or MidiService * @hide * Returns a {@link MidiDeviceInfo} object, which describes this device. * * @return the {@link MidiDeviceInfo} object */ public MidiDevice(MidiDeviceInfo deviceInfo, ParcelFileDescriptor pfd) { mDeviceInfo = deviceInfo; mParcelFileDescriptor = pfd; int inputPorts = deviceInfo.getInputPortCount(); int outputPorts = deviceInfo.getOutputPortCount(); mInputPorts = new MidiInputPort[inputPorts]; mOutputPorts = new MidiOutputPort[outputPorts]; mReceivers = new ArrayList[outputPorts]; public MidiDeviceInfo getInfo() { return mDeviceInfo; } /** Loading @@ -147,14 +63,15 @@ public final class MidiDevice implements Parcelable { * @return the {@link MidiInputPort} */ public MidiInputPort openInputPort(int portNumber) { if (portNumber < 0 || portNumber >= mDeviceInfo.getInputPortCount()) { throw new IllegalArgumentException("input port number out of range"); } synchronized (mInputPorts) { if (mInputPorts[portNumber] == null) { mInputPorts[portNumber] = new MidiInputPort(mOutputStream, portNumber); try { ParcelFileDescriptor pfd = mServer.openInputPort(portNumber); if (pfd == null) { return null; } return mInputPorts[portNumber]; return new MidiInputPort(pfd, portNumber); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openInputPort"); return null; } } Loading @@ -165,185 +82,20 @@ public final class MidiDevice implements Parcelable { * @return the {@link MidiOutputPort} */ public MidiOutputPort openOutputPort(int portNumber) { if (portNumber < 0 || portNumber >= mDeviceInfo.getOutputPortCount()) { throw new IllegalArgumentException("output port number out of range"); } synchronized (mOutputPorts) { if (mOutputPorts[portNumber] == null) { mOutputPorts[portNumber] = new MidiOutputPort(this, portNumber); } return mOutputPorts[portNumber]; } } /* package */ void connect(MidiReceiver receiver, int portNumber) { synchronized (mReceivers) { if (mReceivers[portNumber] == null) { mReceivers[portNumber] = new ArrayList<MidiReceiver>(); } mReceivers[portNumber].add(receiver); if (mReceiverCount++ == 0) { mThread.start(); } } } /* package */ void disconnect(MidiReceiver receiver, int portNumber) { synchronized (mReceivers) { ArrayList<MidiReceiver> receivers = mReceivers[portNumber]; if (receivers != null && receivers.remove(receiver)) { mReceiverCount--; } } } /* package */ boolean open() { FileDescriptor fd = mParcelFileDescriptor.getFileDescriptor(); try { mInputStream = new FileInputStream(fd); } catch (Exception e) { Log.e(TAG, "could not create mInputStream", e); return false; } try { mOutputStream = new FileOutputStream(fd); } catch (Exception e) { Log.e(TAG, "could not create mOutputStream", e); return false; } return true; } /* package */ void close() { try { if (mInputStream != null) { mInputStream.close(); } if (mOutputStream != null) { mOutputStream.close(); ParcelFileDescriptor pfd = mServer.openOutputPort(portNumber); if (pfd == null) { return null; } mParcelFileDescriptor.close(); } catch (IOException e) { return new MidiOutputPort(pfd, portNumber); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openOutputPort"); return null; } } /** * Returns a {@link MidiDeviceInfo} object, which describes this device. * * @return the {@link MidiDeviceInfo} object */ public MidiDeviceInfo getInfo() { return mDeviceInfo; } @Override public String toString() { return ("MidiDevice: " + mDeviceInfo.toString() + " fd: " + mParcelFileDescriptor); } public static final Parcelable.Creator<MidiDevice> CREATOR = new Parcelable.Creator<MidiDevice>() { public MidiDevice createFromParcel(Parcel in) { MidiDeviceInfo deviceInfo = (MidiDeviceInfo)in.readParcelable(null); ParcelFileDescriptor pfd = (ParcelFileDescriptor)in.readParcelable(null); return new MidiDevice(deviceInfo, pfd); } public MidiDevice[] newArray(int size) { return new MidiDevice[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeParcelable(mDeviceInfo, flags); parcel.writeParcelable(mParcelFileDescriptor, flags); } /** * Utility function for packing a MIDI message to be sent through our ParcelFileDescriptor * * message byte array contains variable length MIDI message. * messageSize is size of variable length MIDI message * timestamp is message timestamp to pack * dest is buffer to pack into * returns size of packed message * * @hide */ public static int packMessage(byte[] message, int offset, int size, long timestamp, int portNumber, byte[] dest) { // pack variable length message first System.arraycopy(message, offset, dest, 0, size); int destOffset = size; // timestamp takes 8 bytes for (int i = 0; i < 8; i++) { dest[destOffset++] = (byte)timestamp; timestamp >>= 8; } // portNumber is last dest[destOffset++] = (byte)portNumber; return destOffset; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * returns the offet of of MIDI message in packed buffer * * @hide */ public static int getMessageOffset(byte[] buffer, int bufferLength) { // message is at start of buffer return 0; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * returns size of MIDI message in packed buffer * * @hide */ public static int getMessageSize(byte[] buffer, int bufferLength) { // message length is total buffer length minus size of the timestamp and port number return bufferLength - 9 /* (sizeof(timestamp) + sizeof(portNumber)) */; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * unpacks timestamp from packed buffer * * @hide */ public static long getMessageTimeStamp(byte[] buffer, int bufferLength) { long timestamp = 0; // timestamp follows variable length message data int dataLength = getMessageSize(buffer, bufferLength); for (int i = dataLength + 7; i >= dataLength; i--) { // why can't Java deal with unsigned ints? int b = buffer[i]; if (b < 0) b += 256; timestamp = (timestamp << 8) | b; } return timestamp; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * unpacks port number from packed buffer * * @hide */ public static int getMessagePortNumber(byte[] buffer, int bufferLength) { // timestamp follows variable length message data and timestamp int dataLength = getMessageSize(buffer, bufferLength); return buffer[dataLength + 8 /* sizeof(timestamp) */]; return ("MidiDevice: " + mDeviceInfo.toString()); } } core/java/android/midi/MidiDeviceInfo.java +14 −41 Original line number Diff line number Diff line Loading @@ -50,10 +50,6 @@ public class MidiDeviceInfo implements Parcelable { private final int mOutputPortCount; private final Bundle mProperties; // used for USB devices only private final int mAlsaCard; private final int mAlsaDevice; /** * Bundle key for the device's manufacturer name property. * Used with the {@link android.os.Bundle} returned by {@link #getProperties}. Loading Loading @@ -83,33 +79,30 @@ public class MidiDeviceInfo implements Parcelable { public static final String PROPERTY_USB_DEVICE = "usb_device"; /** * MidiDeviceInfo should only be instantiated by MidiService implementation * @hide * Bundle key for the device's ALSA card number. * Only set for USB MIDI devices. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} */ public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts, Bundle properties) { mType = type; mId = id; mInputPortCount = numInputPorts; mOutputPortCount = numOutputPorts; mProperties = properties; mAlsaCard = -1; mAlsaDevice = -1; } public static final String PROPERTY_ALSA_CARD = "alsa_card"; /** * Bundle key for the device's ALSA device number. * Only set for USB MIDI devices. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} */ public static final String PROPERTY_ALSA_DEVICE = "alsa_device"; /** * MidiDeviceInfo should only be instantiated by MidiService implementation * @hide */ public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts, Bundle properties, int alsaCard, int alsaDevice) { Bundle properties) { mType = type; mId = id; mInputPortCount = numInputPorts; mOutputPortCount = numOutputPorts; mProperties = properties; mAlsaCard = alsaCard; mAlsaDevice = alsaDevice; } /** Loading Loading @@ -158,20 +151,6 @@ public class MidiDeviceInfo implements Parcelable { return mProperties; } /** * @hide */ public int getAlsaCard() { return mAlsaCard; } /** * @hide */ public int getAlsaDevice() { return mAlsaDevice; } @Override public boolean equals(Object o) { if (o instanceof MidiDeviceInfo) { Loading @@ -191,9 +170,7 @@ public class MidiDeviceInfo implements Parcelable { return ("MidiDeviceInfo[mType=" + mType + ",mInputPortCount=" + mInputPortCount + ",mOutputPortCount=" + mOutputPortCount + ",mProperties=" + mProperties + ",mAlsaCard=" + mAlsaCard + ",mAlsaDevice=" + mAlsaDevice); ",mProperties=" + mProperties); } public static final Parcelable.Creator<MidiDeviceInfo> CREATOR = Loading @@ -204,9 +181,7 @@ public class MidiDeviceInfo implements Parcelable { int inputPorts = in.readInt(); int outputPorts = in.readInt(); Bundle properties = in.readBundle(); int card = in.readInt(); int device = in.readInt(); return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties, card, device); return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties); } public MidiDeviceInfo[] newArray(int size) { Loading @@ -224,7 +199,5 @@ public class MidiDeviceInfo implements Parcelable { parcel.writeInt(mInputPortCount); parcel.writeInt(mOutputPortCount); parcel.writeBundle(mProperties); parcel.writeInt(mAlsaCard); parcel.writeInt(mAlsaDevice); } } Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -174,6 +174,7 @@ LOCAL_SRC_FILES += \ core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \ core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \ core/java/android/hardware/usb/IUsbManager.aidl \ core/java/android/midi/IMidiDeviceServer.aidl \ core/java/android/midi/IMidiListener.aidl \ core/java/android/midi/IMidiManager.aidl \ core/java/android/net/IConnectivityManager.aidl \ Loading
core/java/android/midi/MidiDevice.aidl→core/java/android/midi/IMidiDeviceServer.aidl +10 −3 Original line number Diff line number Diff line /* * Copyright (C) 2014, The Android Open Source Project * Copyright (C) 2014 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. Loading @@ -16,4 +16,11 @@ package android.midi; parcelable MidiDevice; import android.os.ParcelFileDescriptor; /** @hide */ interface IMidiDeviceServer { ParcelFileDescriptor openInputPort(int portNumber); ParcelFileDescriptor openOutputPort(int portNumber); }
core/java/android/midi/IMidiManager.aidl +5 −11 Original line number Diff line number Diff line Loading @@ -16,13 +16,11 @@ package android.midi; import android.hardware.usb.UsbDevice; import android.midi.IMidiDeviceServer; import android.midi.IMidiListener; import android.midi.MidiDevice; import android.midi.MidiDeviceInfo; import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; /** @hide */ interface IMidiManager Loading @@ -34,14 +32,10 @@ interface IMidiManager void unregisterListener(IBinder token, in IMidiListener listener); // for communicating with MIDI devices ParcelFileDescriptor openDevice(IBinder token, in MidiDeviceInfo device); IMidiDeviceServer openDevice(IBinder token, in MidiDeviceInfo device); // for implementing virtual MIDI devices MidiDevice registerVirtualDevice(IBinder token, int numInputPorts, int numOutputPorts, in Bundle properties); void unregisterVirtualDevice(IBinder token, in MidiDeviceInfo device); // for use by UsbAudioManager void alsaDeviceAdded(int card, int device, in UsbDevice usbDevice); void alsaDeviceRemoved(in UsbDevice usbDevice); MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts, int numOutputPorts, in Bundle properties, boolean isPrivate, int type); void unregisterDeviceServer(in IMidiDeviceServer server); }
core/java/android/midi/MidiDevice.java +30 −278 Original line number Diff line number Diff line Loading @@ -16,9 +16,8 @@ package android.midi; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import java.io.FileDescriptor; Loading @@ -30,114 +29,31 @@ import java.util.ArrayList; /** * This class is used for sending and receiving data to and from an MIDI device * Instances of this class are created by {@link MidiManager#openDevice}. * This class can also be used to provide the implementation for a virtual device. * * This class implements Parcelable so it can be returned from MidiService when creating * virtual MIDI devices. * * @hide */ public final class MidiDevice implements Parcelable { public final class MidiDevice { private static final String TAG = "MidiDevice"; private final MidiDeviceInfo mDeviceInfo; private ParcelFileDescriptor mParcelFileDescriptor; private FileInputStream mInputStream; private FileOutputStream mOutputStream; // lazily populated lists of ports private final MidiInputPort[] mInputPorts; private final MidiOutputPort[] mOutputPorts; // array of receiver lists, indexed by port number private final ArrayList<MidiReceiver>[] mReceivers; private int mReceiverCount; // total number of receivers for all ports /** * Minimum size of packed message as sent through our ParcelFileDescriptor * 8 bytes for timestamp, 1 byte for port number and 1 to 3 bytes for message * @hide */ public static final int MIN_PACKED_MESSAGE_SIZE = 10; private final IMidiDeviceServer mServer; /** * Maximum size of packed message as sent through our ParcelFileDescriptor * 8 bytes for timestamp, 1 byte for port number and 1 to 3 bytes for message * MidiDevice should only be instantiated by MidiManager * @hide */ public static final int MAX_PACKED_MESSAGE_SIZE = 12; // This thread reads MIDI events from a socket and distributes them to the list of // MidiReceivers attached to this device. private final Thread mThread = new Thread() { @Override public void run() { byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE]; ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>(); try { while (true) { // read next event int count = mInputStream.read(buffer); if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) { Log.e(TAG, "Number of bytes read out of range: " + count); break; } int offset = getMessageOffset(buffer, count); int size = getMessageSize(buffer, count); long timestamp = getMessageTimeStamp(buffer, count); int port = getMessagePortNumber(buffer, count); synchronized (mReceivers) { ArrayList<MidiReceiver> receivers = mReceivers[port]; if (receivers != null) { for (int i = 0; i < receivers.size(); i++) { MidiReceiver receiver = receivers.get(i); try { receivers.get(i).onPost(buffer, offset, size, timestamp); } catch (IOException e) { Log.e(TAG, "post failed"); deadReceivers.add(receiver); } } // remove any receivers that failed if (deadReceivers.size() > 0) { for (MidiReceiver receiver: deadReceivers) { receivers.remove(receiver); mReceiverCount--; } deadReceivers.clear(); } if (receivers.size() == 0) { mReceivers[port] = null; } // exit if we have no receivers left if (mReceiverCount == 0) { break; } } } } } catch (IOException e) { Log.e(TAG, "read failed"); } public MidiDevice(MidiDeviceInfo deviceInfo, IMidiDeviceServer server) { mDeviceInfo = deviceInfo; mServer = server; } }; /** * MidiDevice should only be instantiated by MidiManager or MidiService * @hide * Returns a {@link MidiDeviceInfo} object, which describes this device. * * @return the {@link MidiDeviceInfo} object */ public MidiDevice(MidiDeviceInfo deviceInfo, ParcelFileDescriptor pfd) { mDeviceInfo = deviceInfo; mParcelFileDescriptor = pfd; int inputPorts = deviceInfo.getInputPortCount(); int outputPorts = deviceInfo.getOutputPortCount(); mInputPorts = new MidiInputPort[inputPorts]; mOutputPorts = new MidiOutputPort[outputPorts]; mReceivers = new ArrayList[outputPorts]; public MidiDeviceInfo getInfo() { return mDeviceInfo; } /** Loading @@ -147,14 +63,15 @@ public final class MidiDevice implements Parcelable { * @return the {@link MidiInputPort} */ public MidiInputPort openInputPort(int portNumber) { if (portNumber < 0 || portNumber >= mDeviceInfo.getInputPortCount()) { throw new IllegalArgumentException("input port number out of range"); } synchronized (mInputPorts) { if (mInputPorts[portNumber] == null) { mInputPorts[portNumber] = new MidiInputPort(mOutputStream, portNumber); try { ParcelFileDescriptor pfd = mServer.openInputPort(portNumber); if (pfd == null) { return null; } return mInputPorts[portNumber]; return new MidiInputPort(pfd, portNumber); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openInputPort"); return null; } } Loading @@ -165,185 +82,20 @@ public final class MidiDevice implements Parcelable { * @return the {@link MidiOutputPort} */ public MidiOutputPort openOutputPort(int portNumber) { if (portNumber < 0 || portNumber >= mDeviceInfo.getOutputPortCount()) { throw new IllegalArgumentException("output port number out of range"); } synchronized (mOutputPorts) { if (mOutputPorts[portNumber] == null) { mOutputPorts[portNumber] = new MidiOutputPort(this, portNumber); } return mOutputPorts[portNumber]; } } /* package */ void connect(MidiReceiver receiver, int portNumber) { synchronized (mReceivers) { if (mReceivers[portNumber] == null) { mReceivers[portNumber] = new ArrayList<MidiReceiver>(); } mReceivers[portNumber].add(receiver); if (mReceiverCount++ == 0) { mThread.start(); } } } /* package */ void disconnect(MidiReceiver receiver, int portNumber) { synchronized (mReceivers) { ArrayList<MidiReceiver> receivers = mReceivers[portNumber]; if (receivers != null && receivers.remove(receiver)) { mReceiverCount--; } } } /* package */ boolean open() { FileDescriptor fd = mParcelFileDescriptor.getFileDescriptor(); try { mInputStream = new FileInputStream(fd); } catch (Exception e) { Log.e(TAG, "could not create mInputStream", e); return false; } try { mOutputStream = new FileOutputStream(fd); } catch (Exception e) { Log.e(TAG, "could not create mOutputStream", e); return false; } return true; } /* package */ void close() { try { if (mInputStream != null) { mInputStream.close(); } if (mOutputStream != null) { mOutputStream.close(); ParcelFileDescriptor pfd = mServer.openOutputPort(portNumber); if (pfd == null) { return null; } mParcelFileDescriptor.close(); } catch (IOException e) { return new MidiOutputPort(pfd, portNumber); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openOutputPort"); return null; } } /** * Returns a {@link MidiDeviceInfo} object, which describes this device. * * @return the {@link MidiDeviceInfo} object */ public MidiDeviceInfo getInfo() { return mDeviceInfo; } @Override public String toString() { return ("MidiDevice: " + mDeviceInfo.toString() + " fd: " + mParcelFileDescriptor); } public static final Parcelable.Creator<MidiDevice> CREATOR = new Parcelable.Creator<MidiDevice>() { public MidiDevice createFromParcel(Parcel in) { MidiDeviceInfo deviceInfo = (MidiDeviceInfo)in.readParcelable(null); ParcelFileDescriptor pfd = (ParcelFileDescriptor)in.readParcelable(null); return new MidiDevice(deviceInfo, pfd); } public MidiDevice[] newArray(int size) { return new MidiDevice[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeParcelable(mDeviceInfo, flags); parcel.writeParcelable(mParcelFileDescriptor, flags); } /** * Utility function for packing a MIDI message to be sent through our ParcelFileDescriptor * * message byte array contains variable length MIDI message. * messageSize is size of variable length MIDI message * timestamp is message timestamp to pack * dest is buffer to pack into * returns size of packed message * * @hide */ public static int packMessage(byte[] message, int offset, int size, long timestamp, int portNumber, byte[] dest) { // pack variable length message first System.arraycopy(message, offset, dest, 0, size); int destOffset = size; // timestamp takes 8 bytes for (int i = 0; i < 8; i++) { dest[destOffset++] = (byte)timestamp; timestamp >>= 8; } // portNumber is last dest[destOffset++] = (byte)portNumber; return destOffset; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * returns the offet of of MIDI message in packed buffer * * @hide */ public static int getMessageOffset(byte[] buffer, int bufferLength) { // message is at start of buffer return 0; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * returns size of MIDI message in packed buffer * * @hide */ public static int getMessageSize(byte[] buffer, int bufferLength) { // message length is total buffer length minus size of the timestamp and port number return bufferLength - 9 /* (sizeof(timestamp) + sizeof(portNumber)) */; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * unpacks timestamp from packed buffer * * @hide */ public static long getMessageTimeStamp(byte[] buffer, int bufferLength) { long timestamp = 0; // timestamp follows variable length message data int dataLength = getMessageSize(buffer, bufferLength); for (int i = dataLength + 7; i >= dataLength; i--) { // why can't Java deal with unsigned ints? int b = buffer[i]; if (b < 0) b += 256; timestamp = (timestamp << 8) | b; } return timestamp; } /** * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor * unpacks port number from packed buffer * * @hide */ public static int getMessagePortNumber(byte[] buffer, int bufferLength) { // timestamp follows variable length message data and timestamp int dataLength = getMessageSize(buffer, bufferLength); return buffer[dataLength + 8 /* sizeof(timestamp) */]; return ("MidiDevice: " + mDeviceInfo.toString()); } }
core/java/android/midi/MidiDeviceInfo.java +14 −41 Original line number Diff line number Diff line Loading @@ -50,10 +50,6 @@ public class MidiDeviceInfo implements Parcelable { private final int mOutputPortCount; private final Bundle mProperties; // used for USB devices only private final int mAlsaCard; private final int mAlsaDevice; /** * Bundle key for the device's manufacturer name property. * Used with the {@link android.os.Bundle} returned by {@link #getProperties}. Loading Loading @@ -83,33 +79,30 @@ public class MidiDeviceInfo implements Parcelable { public static final String PROPERTY_USB_DEVICE = "usb_device"; /** * MidiDeviceInfo should only be instantiated by MidiService implementation * @hide * Bundle key for the device's ALSA card number. * Only set for USB MIDI devices. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} */ public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts, Bundle properties) { mType = type; mId = id; mInputPortCount = numInputPorts; mOutputPortCount = numOutputPorts; mProperties = properties; mAlsaCard = -1; mAlsaDevice = -1; } public static final String PROPERTY_ALSA_CARD = "alsa_card"; /** * Bundle key for the device's ALSA device number. * Only set for USB MIDI devices. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} */ public static final String PROPERTY_ALSA_DEVICE = "alsa_device"; /** * MidiDeviceInfo should only be instantiated by MidiService implementation * @hide */ public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts, Bundle properties, int alsaCard, int alsaDevice) { Bundle properties) { mType = type; mId = id; mInputPortCount = numInputPorts; mOutputPortCount = numOutputPorts; mProperties = properties; mAlsaCard = alsaCard; mAlsaDevice = alsaDevice; } /** Loading Loading @@ -158,20 +151,6 @@ public class MidiDeviceInfo implements Parcelable { return mProperties; } /** * @hide */ public int getAlsaCard() { return mAlsaCard; } /** * @hide */ public int getAlsaDevice() { return mAlsaDevice; } @Override public boolean equals(Object o) { if (o instanceof MidiDeviceInfo) { Loading @@ -191,9 +170,7 @@ public class MidiDeviceInfo implements Parcelable { return ("MidiDeviceInfo[mType=" + mType + ",mInputPortCount=" + mInputPortCount + ",mOutputPortCount=" + mOutputPortCount + ",mProperties=" + mProperties + ",mAlsaCard=" + mAlsaCard + ",mAlsaDevice=" + mAlsaDevice); ",mProperties=" + mProperties); } public static final Parcelable.Creator<MidiDeviceInfo> CREATOR = Loading @@ -204,9 +181,7 @@ public class MidiDeviceInfo implements Parcelable { int inputPorts = in.readInt(); int outputPorts = in.readInt(); Bundle properties = in.readBundle(); int card = in.readInt(); int device = in.readInt(); return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties, card, device); return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties); } public MidiDeviceInfo[] newArray(int size) { Loading @@ -224,7 +199,5 @@ public class MidiDeviceInfo implements Parcelable { parcel.writeInt(mInputPortCount); parcel.writeInt(mOutputPortCount); parcel.writeBundle(mProperties); parcel.writeInt(mAlsaCard); parcel.writeInt(mAlsaDevice); } }