Home | History | Annotate | Download | only in midi
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.midi;
     18 
     19 import android.os.Bundle;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 
     23 import android.util.Log;
     24 
     25 /**
     26  * This class contains information to describe a MIDI device.
     27  * For now we only have information that can be retrieved easily for USB devices,
     28  * but we will probably expand this in the future.
     29  *
     30  * This class is just an immutable object to encapsulate the MIDI device description.
     31  * Use the MidiDevice class to actually communicate with devices.
     32  */
     33 public final class MidiDeviceInfo implements Parcelable {
     34 
     35     private static final String TAG = "MidiDeviceInfo";
     36 
     37     /*
     38      * Please note that constants and (un)marshalling code need to be kept in sync
     39      * with the native implementation (MidiDeviceInfo.h|cpp)
     40      */
     41 
     42     /**
     43      * Constant representing USB MIDI devices for {@link #getType}
     44      */
     45     public static final int TYPE_USB = 1;
     46 
     47     /**
     48      * Constant representing virtual (software based) MIDI devices for {@link #getType}
     49      */
     50     public static final int TYPE_VIRTUAL = 2;
     51 
     52     /**
     53      * Constant representing Bluetooth MIDI devices for {@link #getType}
     54      */
     55     public static final int TYPE_BLUETOOTH = 3;
     56 
     57     /**
     58      * Bundle key for the device's user visible name property.
     59      * The value for this property is of type {@link java.lang.String}.
     60      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
     61      * For USB devices, this is a concatenation of the manufacturer and product names.
     62      */
     63     public static final String PROPERTY_NAME = "name";
     64 
     65     /**
     66      * Bundle key for the device's manufacturer name property.
     67      * The value for this property is of type {@link java.lang.String}.
     68      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
     69      * Matches the USB device manufacturer name string for USB MIDI devices.
     70      */
     71     public static final String PROPERTY_MANUFACTURER = "manufacturer";
     72 
     73     /**
     74      * Bundle key for the device's product name property.
     75      * The value for this property is of type {@link java.lang.String}.
     76      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
     77      * Matches the USB device product name string for USB MIDI devices.
     78      */
     79     public static final String PROPERTY_PRODUCT = "product";
     80 
     81     /**
     82      * Bundle key for the device's version property.
     83      * The value for this property is of type {@link java.lang.String}.
     84      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
     85      * Matches the USB device version number for USB MIDI devices.
     86      */
     87     public static final String PROPERTY_VERSION = "version";
     88 
     89     /**
     90      * Bundle key for the device's serial number property.
     91      * The value for this property is of type {@link java.lang.String}.
     92      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
     93      * Matches the USB device serial number for USB MIDI devices.
     94      */
     95     public static final String PROPERTY_SERIAL_NUMBER = "serial_number";
     96 
     97     /**
     98      * Bundle key for the device's corresponding USB device.
     99      * The value for this property is of type {@link android.hardware.usb.UsbDevice}.
    100      * Only set for USB MIDI devices.
    101      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
    102      */
    103     public static final String PROPERTY_USB_DEVICE = "usb_device";
    104 
    105     /**
    106      * Bundle key for the device's corresponding Bluetooth device.
    107      * The value for this property is of type {@link android.bluetooth.BluetoothDevice}.
    108      * Only set for Bluetooth MIDI devices.
    109      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
    110      */
    111     public static final String PROPERTY_BLUETOOTH_DEVICE = "bluetooth_device";
    112 
    113     /**
    114      * Bundle key for the device's ALSA card number.
    115      * The value for this property is an integer.
    116      * Only set for USB MIDI devices.
    117      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
    118      *
    119      * @hide
    120      */
    121     public static final String PROPERTY_ALSA_CARD = "alsa_card";
    122 
    123     /**
    124      * Bundle key for the device's ALSA device number.
    125      * The value for this property is an integer.
    126      * Only set for USB MIDI devices.
    127      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
    128      *
    129      * @hide
    130      */
    131     public static final String PROPERTY_ALSA_DEVICE = "alsa_device";
    132 
    133     /**
    134      * ServiceInfo for the service hosting the device implementation.
    135      * The value for this property is of type {@link android.content.pm.ServiceInfo}.
    136      * Only set for Virtual MIDI devices.
    137      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
    138      *
    139      * @hide
    140      */
    141     public static final String PROPERTY_SERVICE_INFO = "service_info";
    142 
    143     /**
    144      * Contains information about an input or output port.
    145      */
    146     public static final class PortInfo {
    147         /**
    148          * Port type for input ports
    149          */
    150         public static final int TYPE_INPUT = 1;
    151 
    152         /**
    153          * Port type for output ports
    154          */
    155         public static final int TYPE_OUTPUT = 2;
    156 
    157         private final int mPortType;
    158         private final int mPortNumber;
    159         private final String mName;
    160 
    161         PortInfo(int type, int portNumber, String name) {
    162             mPortType = type;
    163             mPortNumber = portNumber;
    164             mName = (name == null ? "" : name);
    165         }
    166 
    167         /**
    168          * Returns the port type of the port (either {@link #TYPE_INPUT} or {@link #TYPE_OUTPUT})
    169          * @return the port type
    170          */
    171         public int getType() {
    172             return mPortType;
    173         }
    174 
    175         /**
    176          * Returns the port number of the port
    177          * @return the port number
    178          */
    179         public int getPortNumber() {
    180             return mPortNumber;
    181         }
    182 
    183         /**
    184          * Returns the name of the port, or empty string if the port has no name
    185          * @return the port name
    186          */
    187         public String getName() {
    188             return mName;
    189         }
    190     }
    191 
    192     private final int mType;    // USB or virtual
    193     private final int mId;      // unique ID generated by MidiService
    194     private final int mInputPortCount;
    195     private final int mOutputPortCount;
    196     private final String[] mInputPortNames;
    197     private final String[] mOutputPortNames;
    198     private final Bundle mProperties;
    199     private final boolean mIsPrivate;
    200 
    201     /**
    202      * MidiDeviceInfo should only be instantiated by MidiService implementation
    203      * @hide
    204      */
    205     public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts,
    206             String[] inputPortNames, String[] outputPortNames, Bundle properties,
    207             boolean isPrivate) {
    208         mType = type;
    209         mId = id;
    210         mInputPortCount = numInputPorts;
    211         mOutputPortCount = numOutputPorts;
    212         if (inputPortNames == null) {
    213             mInputPortNames = new String[numInputPorts];
    214         } else {
    215             mInputPortNames = inputPortNames;
    216         }
    217         if (outputPortNames == null) {
    218             mOutputPortNames = new String[numOutputPorts];
    219         } else {
    220             mOutputPortNames = outputPortNames;
    221         }
    222         mProperties = properties;
    223         mIsPrivate = isPrivate;
    224     }
    225 
    226     /**
    227      * Returns the type of the device.
    228      *
    229      * @return the device's type
    230      */
    231     public int getType() {
    232         return mType;
    233     }
    234 
    235     /**
    236      * Returns the ID of the device.
    237      * This ID is generated by the MIDI service and is not persistent across device unplugs.
    238      *
    239      * @return the device's ID
    240      */
    241     public int getId() {
    242         return mId;
    243     }
    244 
    245     /**
    246      * Returns the device's number of input ports.
    247      *
    248      * @return the number of input ports
    249      */
    250     public int getInputPortCount() {
    251         return mInputPortCount;
    252     }
    253 
    254     /**
    255      * Returns the device's number of output ports.
    256      *
    257      * @return the number of output ports
    258      */
    259     public int getOutputPortCount() {
    260         return mOutputPortCount;
    261     }
    262 
    263     /**
    264      * Returns information about the device's ports.
    265      * The ports are in unspecified order.
    266      *
    267      * @return array of {@link PortInfo}
    268      */
    269     public PortInfo[] getPorts() {
    270         PortInfo[] ports = new PortInfo[mInputPortCount + mOutputPortCount];
    271 
    272         int index = 0;
    273         for (int i = 0; i < mInputPortCount; i++) {
    274             ports[index++] = new PortInfo(PortInfo.TYPE_INPUT, i, mInputPortNames[i]);
    275         }
    276         for (int i = 0; i < mOutputPortCount; i++) {
    277             ports[index++] = new PortInfo(PortInfo.TYPE_OUTPUT, i, mOutputPortNames[i]);
    278         }
    279 
    280         return ports;
    281     }
    282 
    283     /**
    284      * Returns the {@link android.os.Bundle} containing the device's properties.
    285      *
    286      * @return the device's properties
    287      */
    288     public Bundle getProperties() {
    289         return mProperties;
    290     }
    291 
    292     /**
    293      * Returns true if the device is private.  Private devices are only visible and accessible
    294      * to clients with the same UID as the application that is hosting the device.
    295      *
    296      * @return true if the device is private
    297      */
    298     public boolean isPrivate() {
    299         return mIsPrivate;
    300     }
    301 
    302     @Override
    303     public boolean equals(Object o) {
    304         if (o instanceof MidiDeviceInfo) {
    305             return (((MidiDeviceInfo)o).mId == mId);
    306         } else {
    307             return false;
    308         }
    309     }
    310 
    311     @Override
    312     public int hashCode() {
    313         return mId;
    314     }
    315 
    316     @Override
    317     public String toString() {
    318         // This is a hack to force the mProperties Bundle to unparcel so we can
    319         // print all the names and values.
    320         mProperties.getString(PROPERTY_NAME);
    321         return ("MidiDeviceInfo[mType=" + mType +
    322                 ",mInputPortCount=" + mInputPortCount +
    323                 ",mOutputPortCount=" + mOutputPortCount +
    324                 ",mProperties=" + mProperties +
    325                 ",mIsPrivate=" + mIsPrivate);
    326     }
    327 
    328     public static final Parcelable.Creator<MidiDeviceInfo> CREATOR =
    329         new Parcelable.Creator<MidiDeviceInfo>() {
    330         public MidiDeviceInfo createFromParcel(Parcel in) {
    331             // Needs to be kept in sync with code in MidiDeviceInfo.cpp
    332             int type = in.readInt();
    333             int id = in.readInt();
    334             int inputPortCount = in.readInt();
    335             int outputPortCount = in.readInt();
    336             String[] inputPortNames = in.createStringArray();
    337             String[] outputPortNames = in.createStringArray();
    338             boolean isPrivate = (in.readInt() == 1);
    339             Bundle basicPropertiesIgnored = in.readBundle();
    340             Bundle properties = in.readBundle();
    341             return new MidiDeviceInfo(type, id, inputPortCount, outputPortCount,
    342                     inputPortNames, outputPortNames, properties, isPrivate);
    343         }
    344 
    345         public MidiDeviceInfo[] newArray(int size) {
    346             return new MidiDeviceInfo[size];
    347         }
    348     };
    349 
    350     public int describeContents() {
    351         return 0;
    352     }
    353 
    354     private Bundle getBasicProperties(String[] keys) {
    355         Bundle basicProperties = new Bundle();
    356         for (String key : keys) {
    357             Object val = mProperties.get(key);
    358             if (val != null) {
    359                 if (val instanceof String) {
    360                     basicProperties.putString(key, (String) val);
    361                 } else if (val instanceof Integer) {
    362                     basicProperties.putInt(key, (Integer) val);
    363                 } else {
    364                     Log.w(TAG, "Unsupported property type: " + val.getClass().getName());
    365                 }
    366             }
    367         }
    368         return basicProperties;
    369     }
    370 
    371     public void writeToParcel(Parcel parcel, int flags) {
    372         // Needs to be kept in sync with code in MidiDeviceInfo.cpp
    373         parcel.writeInt(mType);
    374         parcel.writeInt(mId);
    375         parcel.writeInt(mInputPortCount);
    376         parcel.writeInt(mOutputPortCount);
    377         parcel.writeStringArray(mInputPortNames);
    378         parcel.writeStringArray(mOutputPortNames);
    379         parcel.writeInt(mIsPrivate ? 1 : 0);
    380         // "Basic" properties only contain properties of primitive types
    381         // and thus can be read back by native code. "Extra" properties is
    382         // a superset that contains all properties.
    383         parcel.writeBundle(getBasicProperties(new String[] {
    384             PROPERTY_NAME, PROPERTY_MANUFACTURER, PROPERTY_PRODUCT, PROPERTY_VERSION,
    385             PROPERTY_SERIAL_NUMBER, PROPERTY_ALSA_CARD, PROPERTY_ALSA_DEVICE
    386         }));
    387         // Must be serialized last so native code can safely ignore it.
    388         parcel.writeBundle(mProperties);
    389    }
    390 }
    391