diff options
author | yhirano <yhirano@chromium.org> | 2015-02-26 18:44:10 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-27 02:45:02 +0000 |
commit | 7a529cc2c07eb8bf0bdbf757061c0146c216bff7 (patch) | |
tree | 6f123d71c9335c402a970e47037807abc7a011cb /media | |
parent | b8f5639f294a8849a50de6fffe421c044377f8e8 (diff) | |
download | chromium_src-7a529cc2c07eb8bf0bdbf757061c0146c216bff7.zip chromium_src-7a529cc2c07eb8bf0bdbf757061c0146c216bff7.tar.gz chromium_src-7a529cc2c07eb8bf0bdbf757061c0146c216bff7.tar.bz2 |
[MIDI][Android] Support device detach event.
This CL introduces device detach support for Android Web MIDI.
BUG=460901
Review URL: https://codereview.chromium.org/956853004
Cr-Commit-Position: refs/heads/master@{#318384}
Diffstat (limited to 'media')
-rw-r--r-- | media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java | 4 | ||||
-rw-r--r-- | media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java | 59 | ||||
-rw-r--r-- | media/midi/midi_manager_usb.cc | 18 | ||||
-rw-r--r-- | media/midi/midi_manager_usb.h | 1 | ||||
-rw-r--r-- | media/midi/midi_manager_usb_unittest.cc | 25 | ||||
-rw-r--r-- | media/midi/usb_midi_device.h | 2 | ||||
-rw-r--r-- | media/midi/usb_midi_device_factory_android.cc | 8 | ||||
-rw-r--r-- | media/midi/usb_midi_device_factory_android.h | 1 | ||||
-rw-r--r-- | media/midi/usb_midi_input_stream.cc | 14 | ||||
-rw-r--r-- | media/midi/usb_midi_input_stream.h | 3 |
10 files changed, 107 insertions, 28 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 index 35520b4..2f80b96 100644 --- a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java +++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java @@ -187,6 +187,10 @@ class UsbMidiDeviceAndroid { return mUsbDevice; } + boolean isClosed() { + return mIsClosed; + } + /** * Register the own native pointer. */ diff --git a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java index 5eafee6..814bb17 100644 --- a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java +++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java @@ -78,6 +78,9 @@ class UsbMidiDeviceFactoryAndroid { if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { requestDevicePermissionIfNecessary(context, (UsbDevice) extra); } + if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) { + onUsbDeviceDetached((UsbDevice) extra); + } if (ACTION_USB_PERMISSION.equals(intent.getAction())) { onUsbDevicePermissionRequestDone(context, intent); } @@ -85,6 +88,7 @@ class UsbMidiDeviceFactoryAndroid { }; IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); + filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); filter.addAction(ACTION_USB_PERMISSION); context.registerReceiver(mReceiver, filter); mRequestedDevices = new HashSet<UsbDevice>(); @@ -134,6 +138,13 @@ class UsbMidiDeviceFactoryAndroid { * @param device a USB device */ private void requestDevicePermissionIfNecessary(Context context, UsbDevice device) { + for (UsbDevice d: mRequestedDevices) { + if (d.getDeviceId() == device.getDeviceId()) { + // It is already requested. + return; + } + } + for (int i = 0; i < device.getInterfaceCount(); ++i) { UsbInterface iface = device.getInterface(i); if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO @@ -148,6 +159,41 @@ class UsbMidiDeviceFactoryAndroid { } /** + * Called when a USB device is detached. + * + * @param device a USB device + */ + private void onUsbDeviceDetached(UsbDevice device) { + for (UsbDevice usbDevice: mRequestedDevices) { + if (usbDevice.getDeviceId() == device.getDeviceId()) { + mRequestedDevices.remove(usbDevice); + break; + } + } + for (int i = 0; i < mDevices.size(); ++i) { + UsbMidiDeviceAndroid midiDevice = mDevices.get(i); + if (midiDevice.isClosed()) { + // Once a device is disconnected, the system may reassign its device ID to + // another device. So we should ignore disconnected ones. + continue; + } + if (midiDevice.getUsbDevice().getDeviceId() == device.getDeviceId()) { + midiDevice.close(); + if (mIsEnumeratingDevices) { + // In this case, we don't have to keep mDevices sync with the devices list + // in MidiManagerUsb. + mDevices.remove(i); + return; + } + if (mNativePointer != 0) { + nativeOnUsbMidiDeviceDetached(mNativePointer, i); + } + return; + } + } + } + + /** * Called when the user accepts or rejects the permission request requested by * EnumerateDevices. * @@ -168,6 +214,17 @@ class UsbMidiDeviceFactoryAndroid { } if (device != null) { + for (UsbMidiDeviceAndroid registered: mDevices) { + if (!registered.isClosed() + && registered.getUsbDevice().getDeviceId() == device.getDeviceId()) { + // The device is already registered. + device = null; + break; + } + } + } + + if (device != null) { // Now we can add the device. midiDevice = new UsbMidiDeviceAndroid(mUsbManager, device); mDevices.add(midiDevice); @@ -202,4 +259,6 @@ class UsbMidiDeviceFactoryAndroid { long nativeUsbMidiDeviceFactoryAndroid, Object[] devices); private static native void nativeOnUsbMidiDeviceAttached( long nativeUsbMidiDeviceFactoryAndroid, Object device); + private static native void nativeOnUsbMidiDeviceDetached( + long nativeUsbMidiDeviceFactoryAndroid, int index); } diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc index 3b6c885..8faba06 100644 --- a/media/midi/midi_manager_usb.cc +++ b/media/midi/midi_manager_usb.cc @@ -74,6 +74,24 @@ void MidiManagerUsb::OnDeviceAttached(scoped_ptr<UsbMidiDevice> device) { AddPorts(devices_.back(), device_id); } +void MidiManagerUsb::OnDeviceDetached(size_t index) { + if (index >= devices_.size()) { + return; + } + UsbMidiDevice* device = devices_[index]; + for (size_t i = 0; i < output_streams_.size(); ++i) { + if (output_streams_[i]->jack().device == device) { + SetOutputPortState(i, MIDI_PORT_DISCONNECTED); + } + } + const std::vector<UsbMidiJack>& input_jacks = input_stream_->jacks(); + for (size_t i = 0; i < input_jacks.size(); ++i) { + if (input_jacks[i].device == device) { + SetInputPortState(i, MIDI_PORT_DISCONNECTED); + } + } +} + void MidiManagerUsb::OnReceivedData(size_t jack_index, const uint8* data, size_t size, diff --git a/media/midi/midi_manager_usb.h b/media/midi/midi_manager_usb.h index 357b5da..ea9b589 100644 --- a/media/midi/midi_manager_usb.h +++ b/media/midi/midi_manager_usb.h @@ -45,6 +45,7 @@ class MEDIA_EXPORT MidiManagerUsb : public MidiManager, size_t size, base::TimeTicks time) override; void OnDeviceAttached(scoped_ptr<UsbMidiDevice> device) override; + void OnDeviceDetached(size_t index) override; // UsbMidiInputStream::Delegate implementation. void OnReceivedData(size_t jack_index, diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc index efcf604..0afb98b 100644 --- a/media/midi/midi_manager_usb_unittest.cc +++ b/media/midi/midi_manager_usb_unittest.cc @@ -243,13 +243,12 @@ TEST_F(MidiManagerUsbTest, Initialize) { ASSERT_EQ(1u, input_ports().size()); ASSERT_EQ(2u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); - std::vector<UsbMidiInputStream::JackUniqueKey> keys = - manager_->input_stream()->RegisteredJackKeysForTesting(); + std::vector<UsbMidiJack> jacks = manager_->input_stream()->jacks(); ASSERT_EQ(2u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); - ASSERT_EQ(1u, keys.size()); - EXPECT_EQ(2, keys[0].endpoint_number); + ASSERT_EQ(1u, jacks.size()); + EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); } @@ -285,13 +284,12 @@ TEST_F(MidiManagerUsbTest, InitializeMultipleDevices) { ASSERT_EQ(2u, input_ports().size()); ASSERT_EQ(4u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); - std::vector<UsbMidiInputStream::JackUniqueKey> keys = - manager_->input_stream()->RegisteredJackKeysForTesting(); + std::vector<UsbMidiJack> jacks = manager_->input_stream()->jacks(); ASSERT_EQ(4u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); - ASSERT_EQ(2u, keys.size()); - EXPECT_EQ(2, keys[0].endpoint_number); + ASSERT_EQ(2u, jacks.size()); + EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ( "UsbMidiDevice::GetDescriptor\n" @@ -484,10 +482,9 @@ TEST_F(MidiManagerUsbTest, AttachDevice) { ASSERT_EQ(0u, input_ports().size()); ASSERT_EQ(0u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); - std::vector<UsbMidiInputStream::JackUniqueKey> keys = - manager_->input_stream()->RegisteredJackKeysForTesting(); + std::vector<UsbMidiJack> jacks = manager_->input_stream()->jacks(); ASSERT_EQ(0u, manager_->output_streams().size()); - ASSERT_EQ(0u, keys.size()); + ASSERT_EQ(0u, jacks.size()); EXPECT_EQ("", logger_.TakeLog()); scoped_ptr<FakeUsbMidiDevice> new_device(new FakeUsbMidiDevice(&logger_)); @@ -497,12 +494,12 @@ TEST_F(MidiManagerUsbTest, AttachDevice) { ASSERT_EQ(1u, input_ports().size()); ASSERT_EQ(2u, output_ports().size()); ASSERT_TRUE(manager_->input_stream()); - keys = manager_->input_stream()->RegisteredJackKeysForTesting(); + jacks = manager_->input_stream()->jacks(); ASSERT_EQ(2u, manager_->output_streams().size()); EXPECT_EQ(2u, manager_->output_streams()[0]->jack().jack_id); EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); - ASSERT_EQ(1u, keys.size()); - EXPECT_EQ(2, keys[0].endpoint_number); + ASSERT_EQ(1u, jacks.size()); + EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); } diff --git a/media/midi/usb_midi_device.h b/media/midi/usb_midi_device.h index 4552f16..3216614 100644 --- a/media/midi/usb_midi_device.h +++ b/media/midi/usb_midi_device.h @@ -33,6 +33,8 @@ class MEDIA_EXPORT UsbMidiDeviceDelegate { // Called when a USB-MIDI device is attached. virtual void OnDeviceAttached(scoped_ptr<UsbMidiDevice> device) = 0; + // Called when a USB-MIDI device is detached. + virtual void OnDeviceDetached(size_t index) = 0; }; // UsbMidiDevice represents a USB-MIDI device. diff --git a/media/midi/usb_midi_device_factory_android.cc b/media/midi/usb_midi_device_factory_android.cc index 840e109..6302572 100644 --- a/media/midi/usb_midi_device_factory_android.cc +++ b/media/midi/usb_midi_device_factory_android.cc @@ -83,6 +83,14 @@ void UsbMidiDeviceFactoryAndroid::OnUsbMidiDeviceAttached( new UsbMidiDeviceAndroid(raw_device, delegate_))); } +// Called from the Java world. +void UsbMidiDeviceFactoryAndroid::OnUsbMidiDeviceDetached( + JNIEnv* env, + jobject caller, + jint index) { + delegate_->OnDeviceDetached(index); +} + bool UsbMidiDeviceFactoryAndroid::RegisterUsbMidiDeviceFactory(JNIEnv* env) { return RegisterNativesImpl(env); } diff --git a/media/midi/usb_midi_device_factory_android.h b/media/midi/usb_midi_device_factory_android.h index 6c5ce17..7beb9fd 100644 --- a/media/midi/usb_midi_device_factory_android.h +++ b/media/midi/usb_midi_device_factory_android.h @@ -32,6 +32,7 @@ class MEDIA_EXPORT UsbMidiDeviceFactoryAndroid : public UsbMidiDevice::Factory { jobject caller, jobjectArray devices); void OnUsbMidiDeviceAttached(JNIEnv* env, jobject caller, jobject device); + void OnUsbMidiDeviceDetached(JNIEnv* env, jobject caller, jint index); static bool RegisterUsbMidiDeviceFactory(JNIEnv* env); diff --git a/media/midi/usb_midi_input_stream.cc b/media/midi/usb_midi_input_stream.cc index 97e3079..63ca24b 100644 --- a/media/midi/usb_midi_input_stream.cc +++ b/media/midi/usb_midi_input_stream.cc @@ -47,6 +47,7 @@ void UsbMidiInputStream::Add(const UsbMidiJack& jack) { jack.endpoint_number(), jack.cable_number); + jacks_.push_back(jack); DCHECK(jack_dictionary_.end() == jack_dictionary_.find(key)); jack_dictionary_.insert(std::make_pair(key, jack_dictionary_.size())); } @@ -89,17 +90,4 @@ void UsbMidiInputStream::ProcessOnePacket(UsbMidiDevice* device, delegate_->OnReceivedData(it->second, &packet[1], packet_size, time); } -std::vector<UsbMidiInputStream::JackUniqueKey> -UsbMidiInputStream::RegisteredJackKeysForTesting() const { - std::vector<JackUniqueKey> result(jack_dictionary_.size(), - JackUniqueKey(0, 0, 0)); - for (std::map<JackUniqueKey, size_t>::const_iterator it = - jack_dictionary_.begin(); - it != jack_dictionary_.end(); ++it) { - DCHECK_LT(it->second, result.size()); - result[it->second] = it->first; - } - return result; -} - } // namespace media diff --git a/media/midi/usb_midi_input_stream.h b/media/midi/usb_midi_input_stream.h index 8b97fbf..bd12706 100644 --- a/media/midi/usb_midi_input_stream.h +++ b/media/midi/usb_midi_input_stream.h @@ -60,7 +60,7 @@ class MEDIA_EXPORT UsbMidiInputStream { size_t size, base::TimeTicks time); - std::vector<JackUniqueKey> RegisteredJackKeysForTesting() const; + const std::vector<UsbMidiJack>& jacks() const { return jacks_; } private: static const size_t kPacketSize = 4; @@ -71,6 +71,7 @@ class MEDIA_EXPORT UsbMidiInputStream { const uint8* packet, base::TimeTicks time); + std::vector<UsbMidiJack> jacks_; // A map from UsbMidiJack to its index in |jacks_|. std::map<JackUniqueKey, size_t> jack_dictionary_; |