diff options
author | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 08:23:48 +0000 |
---|---|---|
committer | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 08:23:48 +0000 |
commit | 3e17c7e42f11398b1e0387bd551379b13b7b4538 (patch) | |
tree | 6e42087202a32b33a388b588ac43a5cfb2a1c0e3 | |
parent | 5fb6f94f70432acc9b5c995e3cc6f1f85fc767bd (diff) | |
download | chromium_src-3e17c7e42f11398b1e0387bd551379b13b7b4538.zip chromium_src-3e17c7e42f11398b1e0387bd551379b13b7b4538.tar.gz chromium_src-3e17c7e42f11398b1e0387bd551379b13b7b4538.tar.bz2 |
Implement WebMIDI for android, output side.
Implement WebMIDI for android.
This CL implements the output function only.
BUG=303596
R=toyoshim@chromium.org
Review URL: https://codereview.chromium.org/133163006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250648 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java | 126 | ||||
-rw-r--r-- | media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java | 164 | ||||
-rw-r--r-- | media/base/android/media_jni_registrar.cc | 6 | ||||
-rw-r--r-- | media/media.gyp | 7 | ||||
-rw-r--r-- | media/midi/midi_manager.cc | 3 | ||||
-rw-r--r-- | media/midi/midi_manager_android.cc | 16 | ||||
-rw-r--r-- | media/midi/usb_midi_device.h | 1 | ||||
-rw-r--r-- | media/midi/usb_midi_device_android.cc | 49 | ||||
-rw-r--r-- | media/midi/usb_midi_device_android.h | 45 | ||||
-rw-r--r-- | media/midi/usb_midi_device_factory_android.cc | 78 | ||||
-rw-r--r-- | media/midi/usb_midi_device_factory_android.h | 48 |
11 files changed, 542 insertions, 1 deletions
diff --git a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java new file mode 100644 index 0000000..84c35ea --- /dev/null +++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java @@ -0,0 +1,126 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.media; + +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; +import android.hardware.usb.UsbRequest; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +/** + * Owned by its native counterpart declared in usb_midi_device_android.h. + * Refer to that class for general comments. + */ +@JNINamespace("media") +class UsbMidiDeviceAndroid { + /** + * A connection handle for this device. + */ + private UsbDeviceConnection mConnection; + + /** + * A map from endpoint number to UsbEndpoint. + */ + private final Map<Integer, UsbEndpoint> mEndpointMap; + + /** + * A map from UsbEndpoint to UsbRequest associated to it. + */ + private final Map<UsbEndpoint, UsbRequest> mRequestMap; + + /** + * Audio interface subclass code for MIDI. + */ + static final int MIDI_SUBCLASS = 3; + + /** + * Constructs a UsbMidiDeviceAndroid. + * @param manager + * @param device The USB device which this object is assocated with. + */ + UsbMidiDeviceAndroid(UsbManager manager, UsbDevice device) { + mConnection = manager.openDevice(device); + mEndpointMap = new HashMap<Integer, UsbEndpoint>(); + mRequestMap = new HashMap<UsbEndpoint, UsbRequest>(); + + for (int i = 0; i < device.getInterfaceCount(); ++i) { + UsbInterface iface = device.getInterface(i); + if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_AUDIO || + iface.getInterfaceSubclass() != MIDI_SUBCLASS) { + continue; + } + mConnection.claimInterface(iface, true); + for (int j = 0; j < iface.getEndpointCount(); ++j) { + UsbEndpoint endpoint = iface.getEndpoint(j); + if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) { + mEndpointMap.put(endpoint.getEndpointNumber(), endpoint); + } + } + } + } + + /** + * Sends a USB-MIDI data to the device. + * @param endpointNumber The endpoint number of the destination endpoint. + * @param bs The data to be sent. + */ + @CalledByNative + void send(int endpointNumber, byte[] bs) { + if (mConnection == null) { + return; + } + if (!mEndpointMap.containsKey(endpointNumber)) { + return; + } + UsbEndpoint endpoint = mEndpointMap.get(endpointNumber); + UsbRequest request; + if (mRequestMap.containsKey(endpoint)) { + request = mRequestMap.get(endpoint); + } else { + request = new UsbRequest(); + request.initialize(mConnection, endpoint); + mRequestMap.put(endpoint, request); + } + request.queue(ByteBuffer.wrap(bs), bs.length); + } + + /** + * Returns the descriptors bytes of this device. + * @return The descriptors bytes of this device. + */ + @CalledByNative + byte[] getDescriptors() { + if (mConnection == null) { + return new byte[0]; + } + return mConnection.getRawDescriptors(); + } + + /** + * Closes the device connection. + */ + @CalledByNative + void close() { + mEndpointMap.clear(); + for (UsbRequest request : mRequestMap.values()) { + request.close(); + } + mRequestMap.clear(); + if (mConnection != null) { + mConnection.close(); + mConnection = null; + } + } +} diff --git a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java new file mode 100644 index 0000000..7c0953f --- /dev/null +++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java @@ -0,0 +1,164 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.media; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Owned by its native counterpart declared in + * usb_midi_device_factory_android.h. Refer to that class for general comments. + */ +@JNINamespace("media") +class UsbMidiDeviceFactoryAndroid { + /** + * The UsbManager of this system. + */ + private UsbManager mUsbManager; + + /** + * A BroadcastReceiver for USB device permission requests. + */ + private BroadcastReceiver mReceiver; + + /** + * Accessible USB-MIDI devices got so far. + */ + private final List<UsbMidiDeviceAndroid> mDevices = new ArrayList<UsbMidiDeviceAndroid>(); + + /** + * Devices whose access permission requested but not resolved so far. + */ + private Set<UsbDevice> mRequestedDevices; + + /** + * The identifier of this factory. + */ + private long mNativePointer; + + private static final String ACTION_USB_PERMISSION = + "org.chromium.media.USB_PERMISSION"; + + /** + * Constructs a UsbMidiDeviceAndroid. + * @param natviePointer The native pointer to which the created factory is associated. + */ + UsbMidiDeviceFactoryAndroid(long nativePointer) { + mNativePointer = nativePointer; + } + + /** + * Constructs a UsbMidiDeviceAndroid. + * @param nativePointer The native pointer to which the created factory is associated. + */ + @CalledByNative + static UsbMidiDeviceFactoryAndroid create(long nativePointer) { + return new UsbMidiDeviceFactoryAndroid(nativePointer); + } + + /** + * Enumerates USB-MIDI devices. + * If there are devices having USB-MIDI interfaces, this function requests permission for + * accessing the device to the user. + * When the permission request is accepted or rejected onRequestDone will be called. + * + * If there are no USB-MIDI interfaces, this function returns false. + * @return true if some permission requests are in progress. + */ + @CalledByNative + boolean enumerateDevices(Context context) { + mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); + Map<String, UsbDevice> devices = mUsbManager.getDeviceList(); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + context, 0, new Intent(ACTION_USB_PERMISSION), 0); + mRequestedDevices = new HashSet<UsbDevice>(); + for (UsbDevice device : devices.values()) { + boolean found = false; + for (int i = 0; i < device.getInterfaceCount() && !found; ++i) { + UsbInterface iface = device.getInterface(i); + if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO && + iface.getInterfaceSubclass() == UsbMidiDeviceAndroid.MIDI_SUBCLASS) { + found = true; + } + } + if (found) { + mUsbManager.requestPermission(device, pendingIntent); + mRequestedDevices.add(device); + } + } + if (mRequestedDevices.isEmpty()) { + // No USB-MIDI devices are found. + return false; + } + + IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); + mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + if (ACTION_USB_PERMISSION.equals(intent.getAction())) { + onRequestDone(context, intent); + } + } + }; + context.registerReceiver(mReceiver, filter); + return true; + } + + /** + * Called when the user accepts or rejects the permission request requested by + * EnumerateDevices. + * If all permission requests are responded, this function calls + * nativeOnUsbMidiDeviceRequestDone with the accessible USB-MIDI devices. + */ + private void onRequestDone(Context context, Intent intent) { + UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (!mRequestedDevices.contains(device)) { + // We are not interested in the device. + return; + } + mRequestedDevices.remove(device); + if (!intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + // The request was rejected. + device = null; + } + if (device != null) { + // Now we can add the device. + mDevices.add(new UsbMidiDeviceAndroid(mUsbManager, device)); + } + if (mRequestedDevices.isEmpty()) { + // All requests are done. + context.unregisterReceiver(mReceiver); + if (mNativePointer != 0) { + nativeOnUsbMidiDeviceRequestDone(mNativePointer, mDevices.toArray()); + } + } + } + + /** + * Disconnects the native object. + */ + @CalledByNative + void close() { + mNativePointer = 0; + } + + private static native void nativeOnUsbMidiDeviceRequestDone( + long nativeUsbMidiDeviceFactoryAndroid, Object[] devices); +} diff --git a/media/base/android/media_jni_registrar.cc b/media/base/android/media_jni_registrar.cc index d26c71e..fe0ff67 100644 --- a/media/base/android/media_jni_registrar.cc +++ b/media/base/android/media_jni_registrar.cc @@ -15,6 +15,8 @@ #include "media/base/android/media_player_bridge.h" #include "media/base/android/media_player_listener.h" #include "media/base/android/webaudio_media_codec_bridge.h" +#include "media/midi/usb_midi_device_android.h" +#include "media/midi/usb_midi_device_factory_android.h" #include "media/video/capture/android/video_capture_device_android.h" namespace media { @@ -32,6 +34,10 @@ static base::android::RegistrationMethod kMediaRegisteredMethods[] = { MediaPlayerBridge::RegisterMediaPlayerBridge }, { "MediaPlayerListener", MediaPlayerListener::RegisterMediaPlayerListener }, + { "UsbMidiDevice", + UsbMidiDeviceAndroid::RegisterUsbMidiDevice }, + { "UsbMidiDeviceFactory", + UsbMidiDeviceFactoryAndroid::RegisterUsbMidiDeviceFactory }, { "VideoCaptureDevice", VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice }, { "WebAudioMediaCodecBridge", diff --git a/media/media.gyp b/media/media.gyp index baeb378..2fc8898 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -417,6 +417,7 @@ 'midi/midi_manager.h', 'midi/midi_manager_alsa.cc', 'midi/midi_manager_alsa.h', + 'midi/midi_manager_android.cc', 'midi/midi_manager_mac.cc', 'midi/midi_manager_mac.h', 'midi/midi_manager_usb.cc', @@ -432,6 +433,10 @@ 'midi/usb_midi_descriptor_parser.cc', 'midi/usb_midi_descriptor_parser.h', 'midi/usb_midi_device.h', + 'midi/usb_midi_device_android.cc', + 'midi/usb_midi_device_android.h', + 'midi/usb_midi_device_factory_android.cc', + 'midi/usb_midi_device_factory_android.h', 'midi/usb_midi_input_stream.cc', 'midi/usb_midi_input_stream.h', 'midi/usb_midi_jack.h', @@ -1516,6 +1521,8 @@ 'base/android/java/src/org/chromium/media/MediaDrmBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerListener.java', + 'base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java', + 'base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java', 'base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java', ], 'variables': { diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc index 49a51b3..4447a05 100644 --- a/media/midi/midi_manager.cc +++ b/media/midi/midi_manager.cc @@ -9,7 +9,8 @@ namespace media { -#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) +#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \ + !defined(OS_ANDROID) // TODO(toyoshim): implement MidiManager for other platforms. MidiManager* MidiManager::Create() { return new MidiManager; diff --git a/media/midi/midi_manager_android.cc b/media/midi/midi_manager_android.cc new file mode 100644 index 0000000..b8385fb --- /dev/null +++ b/media/midi/midi_manager_android.cc @@ -0,0 +1,16 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "media/midi/midi_manager_usb.h" +#include "media/midi/usb_midi_device_factory_android.h" + +namespace media { + +MidiManager* MidiManager::Create() { + return new MidiManagerUsb( + scoped_ptr<UsbMidiDevice::Factory>(new UsbMidiDeviceFactoryAndroid)); +} + +} // namespace media diff --git a/media/midi/usb_midi_device.h b/media/midi/usb_midi_device.h index 59f129d..28b32bc 100644 --- a/media/midi/usb_midi_device.h +++ b/media/midi/usb_midi_device.h @@ -51,6 +51,7 @@ class MEDIA_EXPORT UsbMidiDevice { // Otherwise |callback| will be called with |false| and empty devices. // When this factory is destroyed during the operation, the operation // will be canceled silently (i.e. |callback| will not be called). + // This function can be called at most once per instance. virtual void EnumerateDevices(UsbMidiDeviceDelegate* delegate, Callback callback) = 0; }; diff --git a/media/midi/usb_midi_device_android.cc b/media/midi/usb_midi_device_android.cc new file mode 100644 index 0000000..f3ccc43 --- /dev/null +++ b/media/midi/usb_midi_device_android.cc @@ -0,0 +1,49 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/midi/usb_midi_device_android.h" + +#include <jni.h> +#include <vector> + +#include "base/android/jni_array.h" +#include "jni/UsbMidiDeviceAndroid_jni.h" + +namespace media { + +UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device, + UsbMidiDeviceDelegate* delegate) + : raw_device_(raw_device), delegate_(delegate) {} + +UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_UsbMidiDeviceAndroid_close(env, raw_device_.obj()); +} + +std::vector<uint8> UsbMidiDeviceAndroid::GetDescriptor() { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jbyteArray> descriptors = + Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_.obj()); + + std::vector<uint8> ret; + base::android::JavaByteArrayToByteVector(env, descriptors.obj(), &ret); + return ret; +} + +void UsbMidiDeviceAndroid::Send(int endpoint_number, + const std::vector<uint8>& data) { + JNIEnv* env = base::android::AttachCurrentThread(); + const uint8* head = data.size() ? &data[0] : NULL; + ScopedJavaLocalRef<jbyteArray> data_to_pass = + base::android::ToJavaByteArray(env, head, data.size()); + + Java_UsbMidiDeviceAndroid_send( + env, raw_device_.obj(), endpoint_number, data_to_pass.obj()); +} + +bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace media diff --git a/media/midi/usb_midi_device_android.h b/media/midi/usb_midi_device_android.h new file mode 100644 index 0000000..ed0a414 --- /dev/null +++ b/media/midi/usb_midi_device_android.h @@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_MIDI_USB_MIDI_DEVICE_ANDROID_H_ +#define MEDIA_MIDI_USB_MIDI_DEVICE_ANDROID_H_ + +#include <jni.h> +#include <vector> + +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/callback.h" +#include "media/base/media_export.h" +#include "media/midi/usb_midi_device.h" + +namespace media { + +class MEDIA_EXPORT UsbMidiDeviceAndroid : public UsbMidiDevice { + public: + typedef base::android::ScopedJavaLocalRef<jobject> ObjectRef; + + static scoped_ptr<Factory> CreateFactory(); + + UsbMidiDeviceAndroid(ObjectRef raw_device, UsbMidiDeviceDelegate* delegate); + virtual ~UsbMidiDeviceAndroid(); + + // UsbMidiDevice implementation. + virtual std::vector<uint8> GetDescriptor() OVERRIDE; + virtual void Send(int endpoint_number, + const std::vector<uint8>& data) OVERRIDE; + + static bool RegisterUsbMidiDevice(JNIEnv* env); + + private: + // The actual device object. + base::android::ScopedJavaGlobalRef<jobject> raw_device_; + UsbMidiDeviceDelegate* delegate_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(UsbMidiDeviceAndroid); +}; + +} // namespace media + +#endif // MEDIA_MIDI_USB_MIDI_DEVICE_ANDROID_H_ diff --git a/media/midi/usb_midi_device_factory_android.cc b/media/midi/usb_midi_device_factory_android.cc new file mode 100644 index 0000000..11385c26 --- /dev/null +++ b/media/midi/usb_midi_device_factory_android.cc @@ -0,0 +1,78 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/midi/usb_midi_device_factory_android.h" + +#include <jni.h> +#include <vector> + +#include "base/android/scoped_java_ref.h" +#include "base/bind.h" +#include "base/containers/hash_tables.h" +#include "base/lazy_instance.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/synchronization/lock.h" +#include "jni/UsbMidiDeviceFactoryAndroid_jni.h" +#include "media/midi/usb_midi_device_android.h" + +namespace media { + +namespace { + +typedef UsbMidiDevice::Factory::Callback Callback; + +} // namespace + +UsbMidiDeviceFactoryAndroid::UsbMidiDeviceFactoryAndroid() : delegate_(NULL) {} + +UsbMidiDeviceFactoryAndroid::~UsbMidiDeviceFactoryAndroid() { + JNIEnv* env = base::android::AttachCurrentThread(); + if (!raw_factory_.is_null()) + Java_UsbMidiDeviceFactoryAndroid_close(env, raw_factory_.obj()); +} + +void UsbMidiDeviceFactoryAndroid::EnumerateDevices( + UsbMidiDeviceDelegate* delegate, + Callback callback) { + DCHECK(!delegate_); + JNIEnv* env = base::android::AttachCurrentThread(); + uintptr_t pointer = reinterpret_cast<uintptr_t>(this); + raw_factory_.Reset(Java_UsbMidiDeviceFactoryAndroid_create(env, pointer)); + + delegate_ = delegate; + callback_ = callback; + + if (Java_UsbMidiDeviceFactoryAndroid_enumerateDevices( + env, raw_factory_.obj(), base::android::GetApplicationContext())) { + // Asynchronous operation. + return; + } + // No devices are found. + ScopedVector<UsbMidiDevice> devices; + callback.Run(true, &devices); +} + +// Called from the Java world. +void UsbMidiDeviceFactoryAndroid::OnUsbMidiDeviceRequestDone( + JNIEnv* env, + jobject caller, + jobjectArray devices) { + size_t size = env->GetArrayLength(devices); + ScopedVector<UsbMidiDevice> devices_to_pass; + for (size_t i = 0; i < size; ++i) { + UsbMidiDeviceAndroid::ObjectRef raw_device( + env, env->GetObjectArrayElement(devices, i)); + devices_to_pass.push_back(new UsbMidiDeviceAndroid(raw_device, delegate_)); + } + + callback_.Run(true, &devices_to_pass); +} + +bool UsbMidiDeviceFactoryAndroid::RegisterUsbMidiDeviceFactory(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace media diff --git a/media/midi/usb_midi_device_factory_android.h b/media/midi/usb_midi_device_factory_android.h new file mode 100644 index 0000000..63a9eb3 --- /dev/null +++ b/media/midi/usb_midi_device_factory_android.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_MIDI_USB_MIDI_DEVICE_FACTORY_ANDROID_H_ +#define MEDIA_MIDI_USB_MIDI_DEVICE_FACTORY_ANDROID_H_ + +#include <jni.h> +#include <vector> + +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "media/base/media_export.h" +#include "media/midi/usb_midi_device.h" + +namespace media { + +// This class enumerates UsbMidiDevices. +class MEDIA_EXPORT UsbMidiDeviceFactoryAndroid : public UsbMidiDevice::Factory { + public: + UsbMidiDeviceFactoryAndroid(); + virtual ~UsbMidiDeviceFactoryAndroid(); + + // UsbMidiDevice::Factory implementation. + virtual void EnumerateDevices(UsbMidiDeviceDelegate* delegate, + Callback callback) OVERRIDE; + + void OnUsbMidiDeviceRequestDone(JNIEnv* env, + jobject caller, + jobjectArray devices); + + static bool RegisterUsbMidiDeviceFactory(JNIEnv* env); + + private: + base::android::ScopedJavaGlobalRef<jobject> raw_factory_; + // Not owned. + UsbMidiDeviceDelegate* delegate_; + Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(UsbMidiDeviceFactoryAndroid); +}; + +} // namespace media + +#endif // MEDIA_MIDI_USB_MIDI_DEVICE_FACTORY_ANDROID_H_ |