1 // Copyright (c) 2012 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 "base/android/jni_array.h" 6 7 #include "base/android/jni_android.h" 8 #include "base/android/jni_string.h" 9 #include "base/logging.h" 10 11 namespace base { 12 namespace android { 13 namespace { 14 15 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it 16 // may be -1 if |array| is not a valid Java array), provide a safe wrapper 17 // that always returns a valid, non-negative size. 18 template <typename JavaArrayType> 19 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { 20 DCHECK(jarray); 21 jsize length = env->GetArrayLength(jarray); 22 DCHECK_GE(length, 0) << "Invalid array length: " << length; 23 return static_cast<size_t>(std::max(0, length)); 24 } 25 26 } // namespace 27 28 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, 29 const uint8_t* bytes, 30 size_t len) { 31 jbyteArray byte_array = env->NewByteArray(len); 32 CheckException(env); 33 DCHECK(byte_array); 34 35 env->SetByteArrayRegion( 36 byte_array, 0, len, reinterpret_cast<const jbyte*>(bytes)); 37 CheckException(env); 38 39 return ScopedJavaLocalRef<jbyteArray>(env, byte_array); 40 } 41 42 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( 43 JNIEnv* env, 44 const std::vector<uint8_t>& bytes) { 45 return ToJavaByteArray(env, bytes.data(), bytes.size()); 46 } 47 48 ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray(JNIEnv* env, 49 const bool* bools, 50 size_t len) { 51 jbooleanArray boolean_array = env->NewBooleanArray(len); 52 CheckException(env); 53 DCHECK(boolean_array); 54 55 env->SetBooleanArrayRegion(boolean_array, 0, len, 56 reinterpret_cast<const jboolean*>(bools)); 57 CheckException(env); 58 59 return ScopedJavaLocalRef<jbooleanArray>(env, boolean_array); 60 } 61 62 ScopedJavaLocalRef<jintArray> ToJavaIntArray( 63 JNIEnv* env, const int* ints, size_t len) { 64 jintArray int_array = env->NewIntArray(len); 65 CheckException(env); 66 DCHECK(int_array); 67 68 env->SetIntArrayRegion( 69 int_array, 0, len, reinterpret_cast<const jint*>(ints)); 70 CheckException(env); 71 72 return ScopedJavaLocalRef<jintArray>(env, int_array); 73 } 74 75 ScopedJavaLocalRef<jintArray> ToJavaIntArray( 76 JNIEnv* env, const std::vector<int>& ints) { 77 return ToJavaIntArray(env, ints.data(), ints.size()); 78 } 79 80 ScopedJavaLocalRef<jlongArray> ToJavaLongArray(JNIEnv* env, 81 const int64_t* longs, 82 size_t len) { 83 jlongArray long_array = env->NewLongArray(len); 84 CheckException(env); 85 DCHECK(long_array); 86 87 env->SetLongArrayRegion( 88 long_array, 0, len, reinterpret_cast<const jlong*>(longs)); 89 CheckException(env); 90 91 return ScopedJavaLocalRef<jlongArray>(env, long_array); 92 } 93 94 // Returns a new Java long array converted from the given int64_t array. 95 BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray( 96 JNIEnv* env, 97 const std::vector<int64_t>& longs) { 98 return ToJavaLongArray(env, longs.data(), longs.size()); 99 } 100 101 // Returns a new Java float array converted from the given C++ float array. 102 BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray( 103 JNIEnv* env, const float* floats, size_t len) { 104 jfloatArray float_array = env->NewFloatArray(len); 105 CheckException(env); 106 DCHECK(float_array); 107 108 env->SetFloatArrayRegion( 109 float_array, 0, len, reinterpret_cast<const jfloat*>(floats)); 110 CheckException(env); 111 112 return ScopedJavaLocalRef<jfloatArray>(env, float_array); 113 } 114 115 BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray( 116 JNIEnv* env, 117 const std::vector<float>& floats) { 118 return ToJavaFloatArray(env, floats.data(), floats.size()); 119 } 120 121 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( 122 JNIEnv* env, const std::vector<std::string>& v) { 123 ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B"); 124 jobjectArray joa = env->NewObjectArray(v.size(), 125 byte_array_clazz.obj(), NULL); 126 CheckException(env); 127 128 for (size_t i = 0; i < v.size(); ++i) { 129 ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray( 130 env, reinterpret_cast<const uint8_t*>(v[i].data()), v[i].length()); 131 env->SetObjectArrayElement(joa, i, byte_array.obj()); 132 } 133 return ScopedJavaLocalRef<jobjectArray>(env, joa); 134 } 135 136 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( 137 JNIEnv* env, const std::vector<std::string>& v) { 138 ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String"); 139 jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL); 140 CheckException(env); 141 142 for (size_t i = 0; i < v.size(); ++i) { 143 ScopedJavaLocalRef<jstring> item = ConvertUTF8ToJavaString(env, v[i]); 144 env->SetObjectArrayElement(joa, i, item.obj()); 145 } 146 return ScopedJavaLocalRef<jobjectArray>(env, joa); 147 } 148 149 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( 150 JNIEnv* env, const std::vector<string16>& v) { 151 ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String"); 152 jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL); 153 CheckException(env); 154 155 for (size_t i = 0; i < v.size(); ++i) { 156 ScopedJavaLocalRef<jstring> item = ConvertUTF16ToJavaString(env, v[i]); 157 env->SetObjectArrayElement(joa, i, item.obj()); 158 } 159 return ScopedJavaLocalRef<jobjectArray>(env, joa); 160 } 161 162 void AppendJavaStringArrayToStringVector(JNIEnv* env, 163 jobjectArray array, 164 std::vector<string16>* out) { 165 DCHECK(out); 166 if (!array) 167 return; 168 size_t len = SafeGetArrayLength(env, array); 169 size_t back = out->size(); 170 out->resize(back + len); 171 for (size_t i = 0; i < len; ++i) { 172 ScopedJavaLocalRef<jstring> str(env, 173 static_cast<jstring>(env->GetObjectArrayElement(array, i))); 174 ConvertJavaStringToUTF16(env, str.obj(), out->data() + back + i); 175 } 176 } 177 178 void AppendJavaStringArrayToStringVector(JNIEnv* env, 179 jobjectArray array, 180 std::vector<std::string>* out) { 181 DCHECK(out); 182 if (!array) 183 return; 184 size_t len = SafeGetArrayLength(env, array); 185 size_t back = out->size(); 186 out->resize(back + len); 187 for (size_t i = 0; i < len; ++i) { 188 ScopedJavaLocalRef<jstring> str(env, 189 static_cast<jstring>(env->GetObjectArrayElement(array, i))); 190 ConvertJavaStringToUTF8(env, str.obj(), out->data() + back + i); 191 } 192 } 193 194 void AppendJavaByteArrayToByteVector(JNIEnv* env, 195 jbyteArray byte_array, 196 std::vector<uint8_t>* out) { 197 DCHECK(out); 198 if (!byte_array) 199 return; 200 size_t len = SafeGetArrayLength(env, byte_array); 201 if (!len) 202 return; 203 size_t back = out->size(); 204 out->resize(back + len); 205 env->GetByteArrayRegion(byte_array, 0, len, 206 reinterpret_cast<int8_t*>(out->data() + back)); 207 } 208 209 void JavaByteArrayToByteVector(JNIEnv* env, 210 jbyteArray byte_array, 211 std::vector<uint8_t>* out) { 212 DCHECK(out); 213 DCHECK(byte_array); 214 out->clear(); 215 AppendJavaByteArrayToByteVector(env, byte_array, out); 216 } 217 218 void JavaBooleanArrayToBoolVector(JNIEnv* env, 219 jbooleanArray boolean_array, 220 std::vector<bool>* out) { 221 DCHECK(out); 222 if (!boolean_array) 223 return; 224 size_t len = SafeGetArrayLength(env, boolean_array); 225 if (!len) 226 return; 227 out->resize(len); 228 // It is not possible to get bool* out of vector<bool>. 229 jboolean* values = env->GetBooleanArrayElements(boolean_array, nullptr); 230 for (size_t i = 0; i < len; ++i) { 231 out->at(i) = static_cast<bool>(values[i]); 232 } 233 } 234 235 void JavaIntArrayToIntVector(JNIEnv* env, 236 jintArray int_array, 237 std::vector<int>* out) { 238 DCHECK(out); 239 size_t len = SafeGetArrayLength(env, int_array); 240 out->resize(len); 241 if (!len) 242 return; 243 env->GetIntArrayRegion(int_array, 0, len, out->data()); 244 } 245 246 void JavaLongArrayToInt64Vector(JNIEnv* env, 247 jlongArray long_array, 248 std::vector<int64_t>* out) { 249 DCHECK(out); 250 std::vector<jlong> temp; 251 JavaLongArrayToLongVector(env, long_array, &temp); 252 out->resize(0); 253 out->insert(out->begin(), temp.begin(), temp.end()); 254 } 255 256 void JavaLongArrayToLongVector(JNIEnv* env, 257 jlongArray long_array, 258 std::vector<jlong>* out) { 259 DCHECK(out); 260 size_t len = SafeGetArrayLength(env, long_array); 261 out->resize(len); 262 if (!len) 263 return; 264 env->GetLongArrayRegion(long_array, 0, len, out->data()); 265 } 266 267 void JavaFloatArrayToFloatVector(JNIEnv* env, 268 jfloatArray float_array, 269 std::vector<float>* out) { 270 DCHECK(out); 271 size_t len = SafeGetArrayLength(env, float_array); 272 out->resize(len); 273 if (!len) 274 return; 275 env->GetFloatArrayRegion(float_array, 0, len, out->data()); 276 } 277 278 void JavaArrayOfByteArrayToStringVector( 279 JNIEnv* env, 280 jobjectArray array, 281 std::vector<std::string>* out) { 282 DCHECK(out); 283 size_t len = SafeGetArrayLength(env, array); 284 out->resize(len); 285 for (size_t i = 0; i < len; ++i) { 286 ScopedJavaLocalRef<jbyteArray> bytes_array( 287 env, static_cast<jbyteArray>( 288 env->GetObjectArrayElement(array, i))); 289 jsize bytes_len = env->GetArrayLength(bytes_array.obj()); 290 jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), nullptr); 291 (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len); 292 env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT); 293 } 294 } 295 296 void JavaArrayOfIntArrayToIntVector( 297 JNIEnv* env, 298 jobjectArray array, 299 std::vector<std::vector<int>>* out) { 300 DCHECK(out); 301 size_t len = SafeGetArrayLength(env, array); 302 out->resize(len); 303 for (size_t i = 0; i < len; ++i) { 304 ScopedJavaLocalRef<jintArray> int_array( 305 env, static_cast<jintArray>(env->GetObjectArrayElement(array, i))); 306 JavaIntArrayToIntVector(env, int_array.obj(), &out->at(i)); 307 } 308 } 309 310 } // namespace android 311 } // namespace base 312