Home | History | Annotate | Download | only in android
      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