1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org
.chromium
.media
;
7 import android
.app
.PendingIntent
;
8 import android
.content
.BroadcastReceiver
;
9 import android
.content
.Context
;
10 import android
.content
.Intent
;
11 import android
.content
.IntentFilter
;
12 import android
.hardware
.usb
.UsbConstants
;
13 import android
.hardware
.usb
.UsbDevice
;
14 import android
.hardware
.usb
.UsbInterface
;
15 import android
.hardware
.usb
.UsbManager
;
17 import org
.chromium
.base
.CalledByNative
;
18 import org
.chromium
.base
.JNINamespace
;
20 import java
.util
.ArrayList
;
21 import java
.util
.HashSet
;
22 import java
.util
.List
;
27 * Owned by its native counterpart declared in
28 * usb_midi_device_factory_android.h. Refer to that class for general comments.
30 @JNINamespace("media")
31 class UsbMidiDeviceFactoryAndroid
{
33 * The UsbManager of this system.
35 private UsbManager mUsbManager
;
38 * A BroadcastReceiver for USB device permission requests.
40 private BroadcastReceiver mReceiver
;
43 * Accessible USB-MIDI devices got so far.
45 private final List
<UsbMidiDeviceAndroid
> mDevices
= new ArrayList
<UsbMidiDeviceAndroid
>();
48 * Devices whose access permission requested but not resolved so far.
50 private Set
<UsbDevice
> mRequestedDevices
;
53 * The identifier of this factory.
55 private long mNativePointer
;
57 private static final String ACTION_USB_PERMISSION
=
58 "org.chromium.media.USB_PERMISSION";
61 * Constructs a UsbMidiDeviceAndroid.
62 * @param natviePointer The native pointer to which the created factory is associated.
64 UsbMidiDeviceFactoryAndroid(long nativePointer
) {
65 mNativePointer
= nativePointer
;
69 * Constructs a UsbMidiDeviceAndroid.
70 * @param nativePointer The native pointer to which the created factory is associated.
73 static UsbMidiDeviceFactoryAndroid
create(long nativePointer
) {
74 return new UsbMidiDeviceFactoryAndroid(nativePointer
);
78 * Enumerates USB-MIDI devices.
79 * If there are devices having USB-MIDI interfaces, this function requests permission for
80 * accessing the device to the user.
81 * When the permission request is accepted or rejected onRequestDone will be called.
83 * If there are no USB-MIDI interfaces, this function returns false.
84 * @return true if some permission requests are in progress.
87 boolean enumerateDevices(Context context
) {
88 mUsbManager
= (UsbManager
)context
.getSystemService(Context
.USB_SERVICE
);
89 Map
<String
, UsbDevice
> devices
= mUsbManager
.getDeviceList();
90 PendingIntent pendingIntent
= PendingIntent
.getBroadcast(
91 context
, 0, new Intent(ACTION_USB_PERMISSION
), 0);
92 mRequestedDevices
= new HashSet
<UsbDevice
>();
93 for (UsbDevice device
: devices
.values()) {
94 boolean found
= false;
95 for (int i
= 0; i
< device
.getInterfaceCount() && !found
; ++i
) {
96 UsbInterface iface
= device
.getInterface(i
);
97 if (iface
.getInterfaceClass() == UsbConstants
.USB_CLASS_AUDIO
&&
98 iface
.getInterfaceSubclass() == UsbMidiDeviceAndroid
.MIDI_SUBCLASS
) {
103 mUsbManager
.requestPermission(device
, pendingIntent
);
104 mRequestedDevices
.add(device
);
107 if (mRequestedDevices
.isEmpty()) {
108 // No USB-MIDI devices are found.
112 IntentFilter filter
= new IntentFilter(ACTION_USB_PERMISSION
);
113 mReceiver
= new BroadcastReceiver() {
114 public void onReceive(Context context
, Intent intent
) {
115 if (ACTION_USB_PERMISSION
.equals(intent
.getAction())) {
116 onRequestDone(context
, intent
);
120 context
.registerReceiver(mReceiver
, filter
);
125 * Called when the user accepts or rejects the permission request requested by
127 * If all permission requests are responded, this function calls
128 * nativeOnUsbMidiDeviceRequestDone with the accessible USB-MIDI devices.
130 private void onRequestDone(Context context
, Intent intent
) {
131 UsbDevice device
= (UsbDevice
)intent
.getParcelableExtra(UsbManager
.EXTRA_DEVICE
);
132 if (!mRequestedDevices
.contains(device
)) {
133 // We are not interested in the device.
136 mRequestedDevices
.remove(device
);
137 if (!intent
.getBooleanExtra(UsbManager
.EXTRA_PERMISSION_GRANTED
, false)) {
138 // The request was rejected.
141 if (device
!= null) {
142 // Now we can add the device.
143 mDevices
.add(new UsbMidiDeviceAndroid(mUsbManager
, device
));
145 if (mRequestedDevices
.isEmpty()) {
146 // All requests are done.
147 context
.unregisterReceiver(mReceiver
);
148 if (mNativePointer
!= 0) {
149 nativeOnUsbMidiDeviceRequestDone(mNativePointer
, mDevices
.toArray());
155 * Disconnects the native object.
162 private static native void nativeOnUsbMidiDeviceRequestDone(
163 long nativeUsbMidiDeviceFactoryAndroid
, Object
[] devices
);