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.
4
5#include "media/midi/usb_midi_device_factory_android.h"
6
7#include <jni.h>
8#include <vector>
9
10#include "base/android/scoped_java_ref.h"
11#include "base/bind.h"
12#include "base/containers/hash_tables.h"
13#include "base/lazy_instance.h"
14#include "base/memory/scoped_vector.h"
15#include "base/message_loop/message_loop.h"
16#include "base/synchronization/lock.h"
17#include "jni/UsbMidiDeviceFactoryAndroid_jni.h"
18#include "media/midi/usb_midi_device_android.h"
19
20namespace media {
21
22namespace {
23
24typedef UsbMidiDevice::Factory::Callback Callback;
25
26}  // namespace
27
28UsbMidiDeviceFactoryAndroid::UsbMidiDeviceFactoryAndroid() : delegate_(NULL) {}
29
30UsbMidiDeviceFactoryAndroid::~UsbMidiDeviceFactoryAndroid() {
31  JNIEnv* env = base::android::AttachCurrentThread();
32  if (!raw_factory_.is_null())
33    Java_UsbMidiDeviceFactoryAndroid_close(env, raw_factory_.obj());
34}
35
36void UsbMidiDeviceFactoryAndroid::EnumerateDevices(
37    UsbMidiDeviceDelegate* delegate,
38    Callback callback) {
39  DCHECK(!delegate_);
40  JNIEnv* env = base::android::AttachCurrentThread();
41  uintptr_t pointer = reinterpret_cast<uintptr_t>(this);
42  raw_factory_.Reset(Java_UsbMidiDeviceFactoryAndroid_create(env, pointer));
43
44  delegate_ = delegate;
45  callback_ = callback;
46
47  if (Java_UsbMidiDeviceFactoryAndroid_enumerateDevices(
48          env, raw_factory_.obj(), base::android::GetApplicationContext())) {
49    // Asynchronous operation.
50    return;
51  }
52  // No devices are found.
53  ScopedVector<UsbMidiDevice> devices;
54  callback.Run(true, &devices);
55}
56
57// Called from the Java world.
58void UsbMidiDeviceFactoryAndroid::OnUsbMidiDeviceRequestDone(
59    JNIEnv* env,
60    jobject caller,
61    jobjectArray devices) {
62  size_t size = env->GetArrayLength(devices);
63  ScopedVector<UsbMidiDevice> devices_to_pass;
64  for (size_t i = 0; i < size; ++i) {
65    UsbMidiDeviceAndroid::ObjectRef raw_device(
66        env, env->GetObjectArrayElement(devices, i));
67    devices_to_pass.push_back(new UsbMidiDeviceAndroid(raw_device, delegate_));
68  }
69
70  callback_.Run(true, &devices_to_pass);
71}
72
73bool UsbMidiDeviceFactoryAndroid::RegisterUsbMidiDeviceFactory(JNIEnv* env) {
74  return RegisterNativesImpl(env);
75}
76
77}  // namespace media
78