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