• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
SafeGetArrayLength(JNIEnv * env,JavaArrayType jarray)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 
ToJavaByteArray(JNIEnv * env,const uint8_t * bytes,size_t len)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 
ToJavaByteArray(JNIEnv * env,const std::vector<uint8_t> & bytes)42 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
43     JNIEnv* env,
44     const std::vector<uint8_t>& bytes) {
45   return ToJavaByteArray(env, bytes.data(), bytes.size());
46 }
47 
ToJavaIntArray(JNIEnv * env,const int * ints,size_t len)48 ScopedJavaLocalRef<jintArray> ToJavaIntArray(
49     JNIEnv* env, const int* ints, size_t len) {
50   jintArray int_array = env->NewIntArray(len);
51   CheckException(env);
52   DCHECK(int_array);
53 
54   env->SetIntArrayRegion(
55       int_array, 0, len, reinterpret_cast<const jint*>(ints));
56   CheckException(env);
57 
58   return ScopedJavaLocalRef<jintArray>(env, int_array);
59 }
60 
ToJavaIntArray(JNIEnv * env,const std::vector<int> & ints)61 ScopedJavaLocalRef<jintArray> ToJavaIntArray(
62     JNIEnv* env, const std::vector<int>& ints) {
63   return ToJavaIntArray(env, ints.data(), ints.size());
64 }
65 
ToJavaLongArray(JNIEnv * env,const int64_t * longs,size_t len)66 ScopedJavaLocalRef<jlongArray> ToJavaLongArray(JNIEnv* env,
67                                                const int64_t* longs,
68                                                size_t len) {
69   jlongArray long_array = env->NewLongArray(len);
70   CheckException(env);
71   DCHECK(long_array);
72 
73   env->SetLongArrayRegion(
74       long_array, 0, len, reinterpret_cast<const jlong*>(longs));
75   CheckException(env);
76 
77   return ScopedJavaLocalRef<jlongArray>(env, long_array);
78 }
79 
80 // Returns a new Java long array converted from the given int64_t array.
ToJavaLongArray(JNIEnv * env,const std::vector<int64_t> & longs)81 BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
82     JNIEnv* env,
83     const std::vector<int64_t>& longs) {
84   return ToJavaLongArray(env, longs.data(), longs.size());
85 }
86 
87 // Returns a new Java float array converted from the given C++ float array.
ToJavaFloatArray(JNIEnv * env,const float * floats,size_t len)88 BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray(
89     JNIEnv* env, const float* floats, size_t len) {
90   jfloatArray float_array = env->NewFloatArray(len);
91   CheckException(env);
92   DCHECK(float_array);
93 
94   env->SetFloatArrayRegion(
95       float_array, 0, len, reinterpret_cast<const jfloat*>(floats));
96   CheckException(env);
97 
98   return ScopedJavaLocalRef<jfloatArray>(env, float_array);
99 }
100 
ToJavaFloatArray(JNIEnv * env,const std::vector<float> & floats)101 BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray(
102     JNIEnv* env,
103     const std::vector<float>& floats) {
104   return ToJavaFloatArray(env, floats.data(), floats.size());
105 }
106 
ToJavaArrayOfByteArray(JNIEnv * env,const std::vector<std::string> & v)107 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
108     JNIEnv* env, const std::vector<std::string>& v) {
109   ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
110   jobjectArray joa = env->NewObjectArray(v.size(),
111                                          byte_array_clazz.obj(), NULL);
112   CheckException(env);
113 
114   for (size_t i = 0; i < v.size(); ++i) {
115     ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(
116         env, reinterpret_cast<const uint8_t*>(v[i].data()), v[i].length());
117     env->SetObjectArrayElement(joa, i, byte_array.obj());
118   }
119   return ScopedJavaLocalRef<jobjectArray>(env, joa);
120 }
121 
ToJavaArrayOfStrings(JNIEnv * env,const std::vector<std::string> & v)122 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
123     JNIEnv* env, const std::vector<std::string>& v) {
124   ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
125   jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL);
126   CheckException(env);
127 
128   for (size_t i = 0; i < v.size(); ++i) {
129     ScopedJavaLocalRef<jstring> item = ConvertUTF8ToJavaString(env, v[i]);
130     env->SetObjectArrayElement(joa, i, item.obj());
131   }
132   return ScopedJavaLocalRef<jobjectArray>(env, joa);
133 }
134 
ToJavaArrayOfStrings(JNIEnv * env,const std::vector<string16> & v)135 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
136     JNIEnv* env, const std::vector<string16>& v) {
137   ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
138   jobjectArray joa = env->NewObjectArray(v.size(), string_clazz.obj(), NULL);
139   CheckException(env);
140 
141   for (size_t i = 0; i < v.size(); ++i) {
142     ScopedJavaLocalRef<jstring> item = ConvertUTF16ToJavaString(env, v[i]);
143     env->SetObjectArrayElement(joa, i, item.obj());
144   }
145   return ScopedJavaLocalRef<jobjectArray>(env, joa);
146 }
147 
AppendJavaStringArrayToStringVector(JNIEnv * env,jobjectArray array,std::vector<string16> * out)148 void AppendJavaStringArrayToStringVector(JNIEnv* env,
149                                          jobjectArray array,
150                                          std::vector<string16>* out) {
151   DCHECK(out);
152   if (!array)
153     return;
154   size_t len = SafeGetArrayLength(env, array);
155   size_t back = out->size();
156   out->resize(back + len);
157   for (size_t i = 0; i < len; ++i) {
158     ScopedJavaLocalRef<jstring> str(env,
159         static_cast<jstring>(env->GetObjectArrayElement(array, i)));
160     ConvertJavaStringToUTF16(env, str.obj(), &((*out)[back + i]));
161   }
162 }
163 
AppendJavaStringArrayToStringVector(JNIEnv * env,jobjectArray array,std::vector<std::string> * out)164 void AppendJavaStringArrayToStringVector(JNIEnv* env,
165                                          jobjectArray array,
166                                          std::vector<std::string>* out) {
167   DCHECK(out);
168   if (!array)
169     return;
170   size_t len = SafeGetArrayLength(env, array);
171   size_t back = out->size();
172   out->resize(back + len);
173   for (size_t i = 0; i < len; ++i) {
174     ScopedJavaLocalRef<jstring> str(env,
175         static_cast<jstring>(env->GetObjectArrayElement(array, i)));
176     ConvertJavaStringToUTF8(env, str.obj(), &((*out)[back + i]));
177   }
178 }
179 
AppendJavaByteArrayToByteVector(JNIEnv * env,jbyteArray byte_array,std::vector<uint8_t> * out)180 void AppendJavaByteArrayToByteVector(JNIEnv* env,
181                                      jbyteArray byte_array,
182                                      std::vector<uint8_t>* out) {
183   DCHECK(out);
184   if (!byte_array)
185     return;
186   size_t len = SafeGetArrayLength(env, byte_array);
187   if (!len)
188     return;
189   size_t back = out->size();
190   out->resize(back + len);
191   env->GetByteArrayRegion(byte_array, 0, len,
192                           reinterpret_cast<int8_t*>(&(*out)[back]));
193 }
194 
JavaByteArrayToByteVector(JNIEnv * env,jbyteArray byte_array,std::vector<uint8_t> * out)195 void JavaByteArrayToByteVector(JNIEnv* env,
196                                jbyteArray byte_array,
197                                std::vector<uint8_t>* out) {
198   DCHECK(out);
199   DCHECK(byte_array);
200   out->clear();
201   AppendJavaByteArrayToByteVector(env, byte_array, out);
202 }
203 
JavaIntArrayToIntVector(JNIEnv * env,jintArray int_array,std::vector<int> * out)204 void JavaIntArrayToIntVector(JNIEnv* env,
205                              jintArray int_array,
206                              std::vector<int>* out) {
207   DCHECK(out);
208   size_t len = SafeGetArrayLength(env, int_array);
209   out->resize(len);
210   if (!len)
211     return;
212   // TODO(jdduke): Use |out->data()| for pointer access after switch to libc++,
213   // both here and in the other conversion routines. See crbug.com/427718.
214   env->GetIntArrayRegion(int_array, 0, len, &(*out)[0]);
215 }
216 
JavaLongArrayToInt64Vector(JNIEnv * env,jlongArray long_array,std::vector<int64_t> * out)217 void JavaLongArrayToInt64Vector(JNIEnv* env,
218                                 jlongArray long_array,
219                                 std::vector<int64_t>* out) {
220   DCHECK(out);
221   std::vector<jlong> temp;
222   JavaLongArrayToLongVector(env, long_array, &temp);
223   out->resize(0);
224   out->insert(out->begin(), temp.begin(), temp.end());
225 }
226 
JavaLongArrayToLongVector(JNIEnv * env,jlongArray long_array,std::vector<jlong> * out)227 void JavaLongArrayToLongVector(JNIEnv* env,
228                                jlongArray long_array,
229                                std::vector<jlong>* out) {
230   DCHECK(out);
231   size_t len = SafeGetArrayLength(env, long_array);
232   out->resize(len);
233   if (!len)
234     return;
235   env->GetLongArrayRegion(long_array, 0, len, &(*out)[0]);
236 }
237 
JavaFloatArrayToFloatVector(JNIEnv * env,jfloatArray float_array,std::vector<float> * out)238 void JavaFloatArrayToFloatVector(JNIEnv* env,
239                                  jfloatArray float_array,
240                                  std::vector<float>* out) {
241   DCHECK(out);
242   size_t len = SafeGetArrayLength(env, float_array);
243   out->resize(len);
244   if (!len)
245     return;
246   env->GetFloatArrayRegion(float_array, 0, len, &(*out)[0]);
247 }
248 
JavaArrayOfByteArrayToStringVector(JNIEnv * env,jobjectArray array,std::vector<std::string> * out)249 void JavaArrayOfByteArrayToStringVector(
250     JNIEnv* env,
251     jobjectArray array,
252     std::vector<std::string>* out) {
253   DCHECK(out);
254   size_t len = SafeGetArrayLength(env, array);
255   out->resize(len);
256   for (size_t i = 0; i < len; ++i) {
257     ScopedJavaLocalRef<jbyteArray> bytes_array(
258         env, static_cast<jbyteArray>(
259             env->GetObjectArrayElement(array, i)));
260     jsize bytes_len = env->GetArrayLength(bytes_array.obj());
261     jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), nullptr);
262     (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len);
263     env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT);
264   }
265 }
266 
JavaArrayOfIntArrayToIntVector(JNIEnv * env,jobjectArray array,std::vector<std::vector<int>> * out)267 void JavaArrayOfIntArrayToIntVector(
268     JNIEnv* env,
269     jobjectArray array,
270     std::vector<std::vector<int>>* out) {
271   DCHECK(out);
272   size_t len = SafeGetArrayLength(env, array);
273   out->resize(len);
274   for (size_t i = 0; i < len; ++i) {
275     ScopedJavaLocalRef<jintArray> int_array(
276         env, static_cast<jintArray>(env->GetObjectArrayElement(array, i)));
277     JavaIntArrayToIntVector(env, int_array.obj(), &((*out)[i]));
278   }
279 }
280 
281 }  // namespace android
282 }  // namespace base
283