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 /**
24  * This class contains information to describe a MIDI device.
25  * For now we only have information that can be retrieved easily for USB devices,
26  * but we will probably expand this in the future.
27  *
28  * This class is just an immutable object to encapsulate the MIDI device description.
29  * Use the MidiDevice class to actually communicate with devices.
30  */
31 public final class MidiDeviceInfo implements Parcelable {
32 
33     private static final String TAG = "MidiDeviceInfo";
34 
35     /**
36      * Constant representing USB MIDI devices for {@link #getType}
37      */
38     public static final int TYPE_USB = 1;
39 
40     /**
41      * Constant representing virtual (software based) MIDI devices for {@link #getType}
42      */
43     public static final int TYPE_VIRTUAL = 2;
44 
45     /**
46      * Constant representing Bluetooth MIDI devices for {@link #getType}
47      */
48     public static final int TYPE_BLUETOOTH = 3;
49 
50     /**
51      * Bundle key for the device's user visible name property.
52      * The value for this property is of type {@link java.lang.String}.
53      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
54      * For USB devices, this is a concatenation of the manufacturer and product names.
55      */
56     public static final String PROPERTY_NAME = "name";
57 
58     /**
59      * Bundle key for the device's manufacturer name property.
60      * The value for this property is of type {@link java.lang.String}.
61      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
62      * Matches the USB device manufacturer name string for USB MIDI devices.
63      */
64     public static final String PROPERTY_MANUFACTURER = "manufacturer";
65 
66     /**
67      * Bundle key for the device's product name property.
68      * The value for this property is of type {@link java.lang.String}.
69      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
70      * Matches the USB device product name string for USB MIDI devices.
71      */
72     public static final String PROPERTY_PRODUCT = "product";
73 
74     /**
75      * Bundle key for the device's version property.
76      * The value for this property is of type {@link java.lang.String}.
77      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
78      * Matches the USB device version number for USB MIDI devices.
79      */
80     public static final String PROPERTY_VERSION = "version";
81 
82     /**
83      * Bundle key for the device's serial number property.
84      * The value for this property is of type {@link java.lang.String}.
85      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
86      * Matches the USB device serial number for USB MIDI devices.
87      */
88     public static final String PROPERTY_SERIAL_NUMBER = "serial_number";
89 
90     /**
91      * Bundle key for the device's corresponding USB device.
92      * The value for this property is of type {@link android.hardware.usb.UsbDevice}.
93      * Only set for USB MIDI devices.
94      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
95      */
96     public static final String PROPERTY_USB_DEVICE = "usb_device";
97 
98     /**
99      * Bundle key for the device's corresponding Bluetooth device.
100      * The value for this property is of type {@link android.bluetooth.BluetoothDevice}.
101      * Only set for Bluetooth MIDI devices.
102      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
103      */
104     public static final String PROPERTY_BLUETOOTH_DEVICE = "bluetooth_device";
105 
106     /**
107      * Bundle key for the device's ALSA card number.
108      * The value for this property is an integer.
109      * Only set for USB MIDI devices.
110      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
111      *
112      * @hide
113      */
114     public static final String PROPERTY_ALSA_CARD = "alsa_card";
115 
116     /**
117      * Bundle key for the device's ALSA device number.
118      * The value for this property is an integer.
119      * Only set for USB MIDI devices.
120      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
121      *
122      * @hide
123      */
124     public static final String PROPERTY_ALSA_DEVICE = "alsa_device";
125 
126     /**
127      * ServiceInfo for the service hosting the device implementation.
128      * The value for this property is of type {@link android.content.pm.ServiceInfo}.
129      * Only set for Virtual MIDI devices.
130      * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
131      *
132      * @hide
133      */
134     public static final String PROPERTY_SERVICE_INFO = "service_info";
135 
136     /**
137      * Contains information about an input or output port.
138      */
139     public static final class PortInfo {
140         /**
141          * Port type for input ports
142          */
143         public static final int TYPE_INPUT = 1;
144 
145         /**
146          * Port type for output ports
147          */
148         public static final int TYPE_OUTPUT = 2;
149 
150         private final int mPortType;
151         private final int mPortNumber;
152         private final String mName;
153 
PortInfo(int type, int portNumber, String name)154         PortInfo(int type, int portNumber, String name) {
155             mPortType = type;
156             mPortNumber = portNumber;
157             mName = (name == null ? "" : name);
158         }
159 
160         /**
161          * Returns the port type of the port (either {@link #TYPE_INPUT} or {@link #TYPE_OUTPUT})
162          * @return the port type
163          */
getType()164         public int getType() {
165             return mPortType;
166         }
167 
168         /**
169          * Returns the port number of the port
170          * @return the port number
171          */
getPortNumber()172         public int getPortNumber() {
173             return mPortNumber;
174         }
175 
176         /**
177          * Returns the name of the port, or empty string if the port has no name
178          * @return the port name
179          */
getName()180         public String getName() {
181             return mName;
182         }
183     }
184 
185     private final int mType;    // USB or virtual
186     private final int mId;      // unique ID generated by MidiService
187     private final int mInputPortCount;
188     private final int mOutputPortCount;
189     private final String[] mInputPortNames;
190     private final String[] mOutputPortNames;
191     private final Bundle mProperties;
192     private final boolean mIsPrivate;
193 
194     /**
195      * MidiDeviceInfo should only be instantiated by MidiService implementation
196      * @hide
197      */
MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts, String[] inputPortNames, String[] outputPortNames, Bundle properties, boolean isPrivate)198     public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts,
199             String[] inputPortNames, String[] outputPortNames, Bundle properties,
200             boolean isPrivate) {
201         mType = type;
202         mId = id;
203         mInputPortCount = numInputPorts;
204         mOutputPortCount = numOutputPorts;
205         if (inputPortNames == null) {
206             mInputPortNames = new String[numInputPorts];
207         } else {
208             mInputPortNames = inputPortNames;
209         }
210         if (outputPortNames == null) {
211             mOutputPortNames = new String[numOutputPorts];
212         } else {
213             mOutputPortNames = outputPortNames;
214         }
215         mProperties = properties;
216         mIsPrivate = isPrivate;
217     }
218 
219     /**
220      * Returns the type of the device.
221      *
222      * @return the device's type
223      */
getType()224     public int getType() {
225         return mType;
226     }
227 
228     /**
229      * Returns the ID of the device.
230      * This ID is generated by the MIDI service and is not persistent across device unplugs.
231      *
232      * @return the device's ID
233      */
getId()234     public int getId() {
235         return mId;
236     }
237 
238     /**
239      * Returns the device's number of input ports.
240      *
241      * @return the number of input ports
242      */
getInputPortCount()243     public int getInputPortCount() {
244         return mInputPortCount;
245     }
246 
247     /**
248      * Returns the device's number of output ports.
249      *
250      * @return the number of output ports
251      */
getOutputPortCount()252     public int getOutputPortCount() {
253         return mOutputPortCount;
254     }
255 
256     /**
257      * Returns information about the device's ports.
258      * The ports are in unspecified order.
259      *
260      * @return array of {@link PortInfo}
261      */
getPorts()262     public PortInfo[] getPorts() {
263         PortInfo[] ports = new PortInfo[mInputPortCount + mOutputPortCount];
264 
265         int index = 0;
266         for (int i = 0; i < mInputPortCount; i++) {
267             ports[index++] = new PortInfo(PortInfo.TYPE_INPUT, i, mInputPortNames[i]);
268         }
269         for (int i = 0; i < mOutputPortCount; i++) {
270             ports[index++] = new PortInfo(PortInfo.TYPE_OUTPUT, i, mOutputPortNames[i]);
271         }
272 
273         return ports;
274     }
275 
276     /**
277      * Returns the {@link android.os.Bundle} containing the device's properties.
278      *
279      * @return the device's properties
280      */
getProperties()281     public Bundle getProperties() {
282         return mProperties;
283     }
284 
285     /**
286      * Returns true if the device is private.  Private devices are only visible and accessible
287      * to clients with the same UID as the application that is hosting the device.
288      *
289      * @return true if the device is private
290      */
isPrivate()291     public boolean isPrivate() {
292         return mIsPrivate;
293     }
294 
295     @Override
equals(Object o)296     public boolean equals(Object o) {
297         if (o instanceof MidiDeviceInfo) {
298             return (((MidiDeviceInfo)o).mId == mId);
299         } else {
300             return false;
301         }
302     }
303 
304     @Override
hashCode()305     public int hashCode() {
306         return mId;
307     }
308 
309     @Override
toString()310     public String toString() {
311         // This is a hack to force the mProperties Bundle to unparcel so we can
312         // print all the names and values.
313         mProperties.getString(PROPERTY_NAME);
314         return ("MidiDeviceInfo[mType=" + mType +
315                 ",mInputPortCount=" + mInputPortCount +
316                 ",mOutputPortCount=" + mOutputPortCount +
317                 ",mProperties=" + mProperties +
318                 ",mIsPrivate=" + mIsPrivate);
319     }
320 
321     public static final Parcelable.Creator<MidiDeviceInfo> CREATOR =
322         new Parcelable.Creator<MidiDeviceInfo>() {
323         public MidiDeviceInfo createFromParcel(Parcel in) {
324             int type = in.readInt();
325             int id = in.readInt();
326             int inputPorts = in.readInt();
327             int outputPorts = in.readInt();
328             String[] inputPortNames = in.createStringArray();
329             String[] outputPortNames = in.createStringArray();
330             Bundle properties = in.readBundle();
331             boolean isPrivate = (in.readInt() == 1);
332             return new MidiDeviceInfo(type, id, inputPorts, outputPorts,
333                     inputPortNames, outputPortNames, properties, isPrivate);
334         }
335 
336         public MidiDeviceInfo[] newArray(int size) {
337             return new MidiDeviceInfo[size];
338         }
339     };
340 
describeContents()341     public int describeContents() {
342         return 0;
343     }
344 
writeToParcel(Parcel parcel, int flags)345     public void writeToParcel(Parcel parcel, int flags) {
346         parcel.writeInt(mType);
347         parcel.writeInt(mId);
348         parcel.writeInt(mInputPortCount);
349         parcel.writeInt(mOutputPortCount);
350         parcel.writeStringArray(mInputPortNames);
351         parcel.writeStringArray(mOutputPortNames);
352         parcel.writeBundle(mProperties);
353         parcel.writeInt(mIsPrivate ? 1 : 0);
354    }
355 }
356