OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/midi/usb_midi_device_android.h" | 5 #include "media/midi/usb_midi_device_android.h" |
6 | 6 |
7 #include <jni.h> | 7 #include <jni.h> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/android/jni_array.h" | 10 #include "base/android/jni_array.h" |
| 11 #include "base/i18n/icu_string_conversions.h" |
| 12 #include "base/strings/stringprintf.h" |
11 #include "base/time/time.h" | 13 #include "base/time/time.h" |
12 #include "jni/UsbMidiDeviceAndroid_jni.h" | 14 #include "jni/UsbMidiDeviceAndroid_jni.h" |
| 15 #include "media/midi/usb_midi_descriptor_parser.h" |
13 | 16 |
14 namespace media { | 17 namespace media { |
15 | 18 |
16 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device, | 19 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device, |
17 UsbMidiDeviceDelegate* delegate) | 20 UsbMidiDeviceDelegate* delegate) |
18 : raw_device_(raw_device), delegate_(delegate) { | 21 : raw_device_(raw_device), delegate_(delegate) { |
19 JNIEnv* env = base::android::AttachCurrentThread(); | 22 JNIEnv* env = base::android::AttachCurrentThread(); |
20 Java_UsbMidiDeviceAndroid_registerSelf( | 23 Java_UsbMidiDeviceAndroid_registerSelf( |
21 env, raw_device_.obj(), reinterpret_cast<jlong>(this)); | 24 env, raw_device_.obj(), reinterpret_cast<jlong>(this)); |
| 25 |
| 26 GetDescriptorsInternal(); |
| 27 InitDeviceInfo(); |
22 } | 28 } |
23 | 29 |
24 UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() { | 30 UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() { |
25 JNIEnv* env = base::android::AttachCurrentThread(); | 31 JNIEnv* env = base::android::AttachCurrentThread(); |
26 Java_UsbMidiDeviceAndroid_close(env, raw_device_.obj()); | 32 Java_UsbMidiDeviceAndroid_close(env, raw_device_.obj()); |
27 } | 33 } |
28 | 34 |
29 std::vector<uint8> UsbMidiDeviceAndroid::GetDescriptor() { | 35 std::vector<uint8> UsbMidiDeviceAndroid::GetDescriptors() { |
30 JNIEnv* env = base::android::AttachCurrentThread(); | 36 return descriptors_; |
31 base::android::ScopedJavaLocalRef<jbyteArray> descriptors = | 37 } |
32 Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_.obj()); | |
33 | 38 |
34 std::vector<uint8> ret; | 39 std::string UsbMidiDeviceAndroid::GetManufacturer() { |
35 base::android::JavaByteArrayToByteVector(env, descriptors.obj(), &ret); | 40 return manufacturer_; |
36 return ret; | 41 } |
| 42 |
| 43 std::string UsbMidiDeviceAndroid::GetProductName() { |
| 44 return product_; |
| 45 } |
| 46 |
| 47 std::string UsbMidiDeviceAndroid::GetDeviceVersion() { |
| 48 return device_version_; |
37 } | 49 } |
38 | 50 |
39 void UsbMidiDeviceAndroid::Send(int endpoint_number, | 51 void UsbMidiDeviceAndroid::Send(int endpoint_number, |
40 const std::vector<uint8>& data) { | 52 const std::vector<uint8>& data) { |
41 JNIEnv* env = base::android::AttachCurrentThread(); | 53 JNIEnv* env = base::android::AttachCurrentThread(); |
42 const uint8* head = data.size() ? &data[0] : NULL; | 54 const uint8* head = data.size() ? &data[0] : NULL; |
43 ScopedJavaLocalRef<jbyteArray> data_to_pass = | 55 ScopedJavaLocalRef<jbyteArray> data_to_pass = |
44 base::android::ToJavaByteArray(env, head, data.size()); | 56 base::android::ToJavaByteArray(env, head, data.size()); |
45 | 57 |
46 Java_UsbMidiDeviceAndroid_send( | 58 Java_UsbMidiDeviceAndroid_send( |
47 env, raw_device_.obj(), endpoint_number, data_to_pass.obj()); | 59 env, raw_device_.obj(), endpoint_number, data_to_pass.obj()); |
48 } | 60 } |
49 | 61 |
50 void UsbMidiDeviceAndroid::OnData(JNIEnv* env, | 62 void UsbMidiDeviceAndroid::OnData(JNIEnv* env, |
51 jobject caller, | 63 jobject caller, |
52 jint endpoint_number, | 64 jint endpoint_number, |
53 jbyteArray data) { | 65 jbyteArray data) { |
54 std::vector<uint8> bytes; | 66 std::vector<uint8> bytes; |
55 base::android::JavaByteArrayToByteVector(env, data, &bytes); | 67 base::android::JavaByteArrayToByteVector(env, data, &bytes); |
56 | 68 |
57 const uint8* head = bytes.size() ? &bytes[0] : NULL; | 69 const uint8* head = bytes.size() ? &bytes[0] : NULL; |
58 delegate_->ReceiveUsbMidiData(this, endpoint_number, head, bytes.size(), | 70 delegate_->ReceiveUsbMidiData(this, endpoint_number, head, bytes.size(), |
59 base::TimeTicks::Now()); | 71 base::TimeTicks::Now()); |
60 } | 72 } |
61 | 73 |
62 bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv* env) { | 74 bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv* env) { |
63 return RegisterNativesImpl(env); | 75 return RegisterNativesImpl(env); |
64 } | 76 } |
65 | 77 |
| 78 void UsbMidiDeviceAndroid::GetDescriptorsInternal() { |
| 79 JNIEnv* env = base::android::AttachCurrentThread(); |
| 80 base::android::ScopedJavaLocalRef<jbyteArray> descriptors = |
| 81 Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_.obj()); |
| 82 |
| 83 base::android::JavaByteArrayToByteVector(env, descriptors.obj(), |
| 84 &descriptors_); |
| 85 } |
| 86 |
| 87 void UsbMidiDeviceAndroid::InitDeviceInfo() { |
| 88 UsbMidiDescriptorParser parser; |
| 89 UsbMidiDescriptorParser::DeviceInfo info; |
| 90 |
| 91 const uint8* data = descriptors_.size() > 0 ? &descriptors_[0] : nullptr; |
| 92 |
| 93 if (!parser.ParseDeviceInfo(data, descriptors_.size(), &info)) { |
| 94 // We don't report the error here. If it is critical, we will realize it |
| 95 // when we parse the descriptors again for ports. |
| 96 manufacturer_ = "invalid descriptor"; |
| 97 product_ = "invalid descriptor"; |
| 98 device_version_ = "invalid descriptor"; |
| 99 return; |
| 100 } |
| 101 |
| 102 manufacturer_ = |
| 103 GetString(info.manufacturer_index, |
| 104 base::StringPrintf("(vendor id = 0x%04x)", info.vendor_id)); |
| 105 product_ = |
| 106 GetString(info.product_index, |
| 107 base::StringPrintf("(product id = 0x%04x)", info.product_id)); |
| 108 device_version_ = info.BcdVersionToString(info.bcd_device_version); |
| 109 } |
| 110 |
| 111 std::vector<uint8> UsbMidiDeviceAndroid::GetStringDescriptor(int index) { |
| 112 JNIEnv* env = base::android::AttachCurrentThread(); |
| 113 base::android::ScopedJavaLocalRef<jbyteArray> descriptors = |
| 114 Java_UsbMidiDeviceAndroid_getStringDescriptor(env, raw_device_.obj(), |
| 115 index); |
| 116 |
| 117 std::vector<uint8> ret; |
| 118 base::android::JavaByteArrayToByteVector(env, descriptors.obj(), &ret); |
| 119 return ret; |
| 120 } |
| 121 |
| 122 std::string UsbMidiDeviceAndroid::GetString(int index, |
| 123 const std::string& backup) { |
| 124 const uint8 DESCRIPTOR_TYPE_STRING = 3; |
| 125 |
| 126 if (!index) { |
| 127 // index 0 means there is no such descriptor. |
| 128 return backup; |
| 129 } |
| 130 std::vector<uint8> descriptor = GetStringDescriptor(index); |
| 131 if (descriptor.size() < 2 || descriptor.size() < descriptor[0] || |
| 132 descriptor[1] != DESCRIPTOR_TYPE_STRING) { |
| 133 // |descriptor| is not a valid string descriptor. |
| 134 return backup; |
| 135 } |
| 136 size_t size = descriptor[0]; |
| 137 std::string encoded(reinterpret_cast<char*>(&descriptor[0]) + 2, size - 2); |
| 138 std::string result; |
| 139 // Unicode ECN specifies that the string is encoded in UTF-16LE. |
| 140 if (!base::ConvertToUtf8AndNormalize(encoded, "utf-16le", &result)) |
| 141 return backup; |
| 142 return result; |
| 143 } |
| 144 |
66 } // namespace media | 145 } // namespace media |
OLD | NEW |