• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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/check_op.h"
10 #include "base/containers/extend.h"
11 #include "base/containers/heap_array.h"
12 #include "base/numerics/safe_conversions.h"
13 
14 namespace base::android {
15 
16 UNSAFE_BUFFER_USAGE ScopedJavaLocalRef<jbyteArray>
ToJavaByteArray(JNIEnv * env,const uint8_t * bytes,size_t len)17 ToJavaByteArray(JNIEnv* env, const uint8_t* bytes, size_t len) {
18   return ToJavaByteArray(
19       env,
20       // SAFETY: The caller must provide a valid pointer and length.
21       UNSAFE_BUFFERS(base::span(bytes, len)));
22 }
23 
ToJavaByteArray(JNIEnv * env,base::span<const uint8_t> bytes)24 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
25     JNIEnv* env,
26     base::span<const uint8_t> bytes) {
27   jbyteArray byte_array = env->NewByteArray(checked_cast<jsize>(bytes.size()));
28   CheckException(env);
29   DCHECK(byte_array);
30 
31   static_assert(sizeof(jbyte) == sizeof(uint8_t));
32   static_assert(alignof(jbyte) <= alignof(uint8_t));
33   env->SetByteArrayRegion(byte_array, jsize{0},
34                           checked_cast<jsize>(bytes.size()),
35                           reinterpret_cast<const jbyte*>(bytes.data()));
36   CheckException(env);
37 
38   return ScopedJavaLocalRef<jbyteArray>(env, byte_array);
39 }
40 
ToJavaByteArray(JNIEnv * env,std::string_view str)41 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env,
42                                                std::string_view str) {
43   return ToJavaByteArray(env, base::as_byte_span(str));
44 }
45 
ToJavaBooleanArray(JNIEnv * env,const std::vector<bool> & bools)46 ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray(
47     JNIEnv* env,
48     const std::vector<bool>& bools) {
49   // Make an actual array of types equivalent to `bool`.
50   auto actual_bools = HeapArray<bool>::Uninit(bools.size());
51   std::ranges::copy(bools, actual_bools.begin());
52   return ToJavaBooleanArray(env, actual_bools);
53 }
54 
ToJavaBooleanArray(JNIEnv * env,span<const bool> bools)55 ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray(JNIEnv* env,
56                                                      span<const bool> bools) {
57   jbooleanArray boolean_array =
58       env->NewBooleanArray(checked_cast<jsize>(bools.size()));
59   CheckException(env);
60   DCHECK(boolean_array);
61 
62   static_assert(sizeof(jboolean) == sizeof(bool));
63   static_assert(alignof(jboolean) <= alignof(bool));
64   env->SetBooleanArrayRegion(boolean_array, jsize{0},
65                              checked_cast<jsize>(bools.size()),
66                              reinterpret_cast<const jboolean*>(bools.data()));
67   CheckException(env);
68 
69   return ScopedJavaLocalRef<jbooleanArray>(env, boolean_array);
70 }
71 
ToJavaIntArray(JNIEnv * env,base::span<const int32_t> ints)72 ScopedJavaLocalRef<jintArray> ToJavaIntArray(JNIEnv* env,
73                                              base::span<const int32_t> ints) {
74   jintArray int_array = env->NewIntArray(checked_cast<jsize>(ints.size()));
75   CheckException(env);
76   DCHECK(int_array);
77 
78   static_assert(sizeof(jint) == sizeof(int32_t));
79   static_assert(alignof(jint) <= alignof(int32_t));
80   env->SetIntArrayRegion(int_array, jsize{0}, checked_cast<jsize>(ints.size()),
81                          reinterpret_cast<const jint*>(ints.data()));
82   CheckException(env);
83 
84   return ScopedJavaLocalRef<jintArray>(env, int_array);
85 }
86 
87 // Returns a new Java long array converted from the given int64_t array.
ToJavaLongArray(JNIEnv * env,base::span<const int64_t> longs)88 BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
89     JNIEnv* env,
90     base::span<const int64_t> longs) {
91   jlongArray long_array = env->NewLongArray(checked_cast<jsize>(longs.size()));
92   CheckException(env);
93   DCHECK(long_array);
94 
95   static_assert(sizeof(jlong) == sizeof(int64_t));
96   static_assert(alignof(jlong) <= alignof(int64_t));
97   env->SetLongArrayRegion(long_array, jsize{0},
98                           checked_cast<jsize>(longs.size()),
99                           reinterpret_cast<const jlong*>(longs.data()));
100   CheckException(env);
101 
102   return ScopedJavaLocalRef<jlongArray>(env, long_array);
103 }
104 
ToJavaFloatArray(JNIEnv * env,base::span<const float> floats)105 BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray(
106     JNIEnv* env,
107     base::span<const float> floats) {
108   jfloatArray float_array =
109       env->NewFloatArray(checked_cast<jsize>(floats.size()));
110   CheckException(env);
111   DCHECK(float_array);
112 
113   static_assert(sizeof(jfloat) == sizeof(float));
114   static_assert(alignof(jfloat) <= alignof(float));
115   env->SetFloatArrayRegion(float_array, jsize{0},
116                            checked_cast<jsize>(floats.size()),
117                            reinterpret_cast<const jfloat*>(floats.data()));
118   CheckException(env);
119 
120   return ScopedJavaLocalRef<jfloatArray>(env, float_array);
121 }
122 
ToJavaDoubleArray(JNIEnv * env,base::span<const double> doubles)123 BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> ToJavaDoubleArray(
124     JNIEnv* env,
125     base::span<const double> doubles) {
126   jdoubleArray double_array =
127       env->NewDoubleArray(checked_cast<jsize>(doubles.size()));
128   CheckException(env);
129   DCHECK(double_array);
130 
131   static_assert(sizeof(jdouble) == sizeof(double));
132   static_assert(alignof(jdouble) <= alignof(double));
133   env->SetDoubleArrayRegion(double_array, jsize{0},
134                             checked_cast<jsize>(doubles.size()),
135                             reinterpret_cast<const jdouble*>(doubles.data()));
136   CheckException(env);
137 
138   return ScopedJavaLocalRef<jdoubleArray>(env, double_array);
139 }
140 
ToJavaArrayOfObjects(JNIEnv * env,jclass clazz,base::span<const ScopedJavaLocalRef<jobject>> v)141 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
142     JNIEnv* env,
143     jclass clazz,
144     base::span<const ScopedJavaLocalRef<jobject>> v) {
145   jobjectArray joa =
146       env->NewObjectArray(checked_cast<jsize>(v.size()), clazz, nullptr);
147   CheckException(env);
148 
149   for (size_t i = 0; i < v.size(); ++i) {
150     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), v[i].obj());
151   }
152   return ScopedJavaLocalRef<jobjectArray>(env, joa);
153 }
154 
ToJavaArrayOfObjects(JNIEnv * env,base::span<const ScopedJavaLocalRef<jobject>> v)155 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
156     JNIEnv* env,
157     base::span<const ScopedJavaLocalRef<jobject>> v) {
158   return ToJavaArrayOfObjects(env, jni_zero::g_object_class, v);
159 }
160 
ToJavaArrayOfObjects(JNIEnv * env,base::span<const ScopedJavaGlobalRef<jobject>> v)161 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
162     JNIEnv* env,
163     base::span<const ScopedJavaGlobalRef<jobject>> v) {
164   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
165                                          jni_zero::g_object_class, nullptr);
166   CheckException(env);
167 
168   for (size_t i = 0; i < v.size(); ++i) {
169     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), v[i].obj());
170   }
171   return ScopedJavaLocalRef<jobjectArray>(env, joa);
172 }
173 
ToTypedJavaArrayOfObjects(JNIEnv * env,base::span<const ScopedJavaLocalRef<jobject>> v,jclass type)174 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
175     JNIEnv* env,
176     base::span<const ScopedJavaLocalRef<jobject>> v,
177     jclass type) {
178   jobjectArray joa =
179       env->NewObjectArray(checked_cast<jsize>(v.size()), type, nullptr);
180   CheckException(env);
181 
182   for (size_t i = 0; i < v.size(); ++i) {
183     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), v[i].obj());
184   }
185   return ScopedJavaLocalRef<jobjectArray>(env, joa);
186 }
187 
ToTypedJavaArrayOfObjects(JNIEnv * env,base::span<const ScopedJavaGlobalRef<jobject>> v,jclass type)188 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
189     JNIEnv* env,
190     base::span<const ScopedJavaGlobalRef<jobject>> v,
191     jclass type) {
192   jobjectArray joa =
193       env->NewObjectArray(checked_cast<jsize>(v.size()), type, nullptr);
194   CheckException(env);
195 
196   for (size_t i = 0; i < v.size(); ++i) {
197     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), v[i].obj());
198   }
199   return ScopedJavaLocalRef<jobjectArray>(env, joa);
200 }
201 
ToJavaArrayOfByteArray(JNIEnv * env,base::span<const std::string> v)202 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
203     JNIEnv* env,
204     base::span<const std::string> v) {
205   ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
206   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
207                                          byte_array_clazz.obj(), nullptr);
208   CheckException(env);
209 
210   for (size_t i = 0; i < v.size(); ++i) {
211     ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env, v[i]);
212     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), byte_array.obj());
213   }
214   return ScopedJavaLocalRef<jobjectArray>(env, joa);
215 }
216 
ToJavaArrayOfByteArray(JNIEnv * env,base::span<const std::vector<uint8_t>> v)217 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
218     JNIEnv* env,
219     base::span<const std::vector<uint8_t>> v) {
220   ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
221   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
222                                          byte_array_clazz.obj(), nullptr);
223   CheckException(env);
224 
225   for (size_t i = 0; i < v.size(); ++i) {
226     ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env, v[i]);
227     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), byte_array.obj());
228   }
229   return ScopedJavaLocalRef<jobjectArray>(env, joa);
230 }
231 
ToJavaArrayOfStrings(JNIEnv * env,base::span<const std::string> v)232 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
233     JNIEnv* env,
234     base::span<const std::string> v) {
235   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
236                                          jni_zero::g_string_class, nullptr);
237   CheckException(env);
238 
239   for (size_t i = 0; i < v.size(); ++i) {
240     ScopedJavaLocalRef<jstring> item = ConvertUTF8ToJavaString(env, v[i]);
241     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), item.obj());
242   }
243   return ScopedJavaLocalRef<jobjectArray>(env, joa);
244 }
245 
ToJavaArrayOfStringArray(JNIEnv * env,base::span<const std::vector<std::string>> vec_outer)246 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray(
247     JNIEnv* env,
248     base::span<const std::vector<std::string>> vec_outer) {
249   ScopedJavaLocalRef<jclass> string_array_clazz =
250       GetClass(env, "[Ljava/lang/String;");
251 
252   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(vec_outer.size()),
253                                          string_array_clazz.obj(), nullptr);
254   CheckException(env);
255 
256   for (size_t i = 0; i < vec_outer.size(); ++i) {
257     ScopedJavaLocalRef<jobjectArray> inner =
258         ToJavaArrayOfStrings(env, vec_outer[i]);
259     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), inner.obj());
260   }
261 
262   return ScopedJavaLocalRef<jobjectArray>(env, joa);
263 }
264 
ToJavaArrayOfStringArray(JNIEnv * env,base::span<const std::vector<std::u16string>> vec_outer)265 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray(
266     JNIEnv* env,
267     base::span<const std::vector<std::u16string>> vec_outer) {
268   ScopedJavaLocalRef<jclass> string_array_clazz =
269       GetClass(env, "[Ljava/lang/String;");
270 
271   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(vec_outer.size()),
272                                          string_array_clazz.obj(), nullptr);
273   CheckException(env);
274 
275   for (size_t i = 0; i < vec_outer.size(); ++i) {
276     ScopedJavaLocalRef<jobjectArray> inner =
277         ToJavaArrayOfStrings(env, vec_outer[i]);
278     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), inner.obj());
279   }
280 
281   return ScopedJavaLocalRef<jobjectArray>(env, joa);
282 }
283 
ToJavaArrayOfStrings(JNIEnv * env,base::span<const std::u16string> v)284 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
285     JNIEnv* env,
286     base::span<const std::u16string> v) {
287   jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
288                                          jni_zero::g_string_class, nullptr);
289   CheckException(env);
290 
291   for (size_t i = 0; i < v.size(); ++i) {
292     ScopedJavaLocalRef<jstring> item = ConvertUTF16ToJavaString(env, v[i]);
293     env->SetObjectArrayElement(joa, checked_cast<jsize>(i), item.obj());
294   }
295   return ScopedJavaLocalRef<jobjectArray>(env, joa);
296 }
297 
AppendJavaStringArrayToStringVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::u16string> * out)298 void AppendJavaStringArrayToStringVector(JNIEnv* env,
299                                          const JavaRef<jobjectArray>& array,
300                                          std::vector<std::u16string>* out) {
301   DCHECK(out);
302   if (!array)
303     return;
304   size_t len = SafeGetArrayLength(env, array);
305   if (!len) {
306     return;
307   }
308   out->resize(out->size() + len);
309   span<std::u16string> back = span(*out).last(len);
310   for (size_t i = 0; i < len; ++i) {
311     ScopedJavaLocalRef<jstring> str(
312         env, static_cast<jstring>(env->GetObjectArrayElement(
313                  array.obj(), checked_cast<jsize>(i))));
314     ConvertJavaStringToUTF16(env, str.obj(), &back[i]);
315   }
316 }
317 
AppendJavaStringArrayToStringVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::string> * out)318 void AppendJavaStringArrayToStringVector(JNIEnv* env,
319                                          const JavaRef<jobjectArray>& array,
320                                          std::vector<std::string>* out) {
321   DCHECK(out);
322   if (!array)
323     return;
324   size_t len = SafeGetArrayLength(env, array);
325   if (!len) {
326     return;
327   }
328   out->resize(out->size() + len);
329   span<std::string> back = span(*out).last(len);
330   for (size_t i = 0; i < len; ++i) {
331     ScopedJavaLocalRef<jstring> str(
332         env, static_cast<jstring>(env->GetObjectArrayElement(
333                  array.obj(), checked_cast<jsize>(i))));
334     ConvertJavaStringToUTF8(env, str.obj(), &back[i]);
335   }
336 }
337 
AppendJavaByteArrayToByteVector(JNIEnv * env,const JavaRef<jbyteArray> & byte_array,std::vector<uint8_t> * out)338 void AppendJavaByteArrayToByteVector(JNIEnv* env,
339                                      const JavaRef<jbyteArray>& byte_array,
340                                      std::vector<uint8_t>* out) {
341   DCHECK(out);
342   if (!byte_array)
343     return;
344   size_t len = SafeGetArrayLength(env, byte_array);
345   if (!len) {
346     return;
347   }
348   out->resize(out->size() + len);
349   span<uint8_t> back = span(*out).last(len);
350 
351   static_assert(sizeof(jbyte) == sizeof(uint8_t));
352   static_assert(alignof(jbyte) <= alignof(uint8_t));
353   env->GetByteArrayRegion(byte_array.obj(), jsize{0},
354                           checked_cast<jsize>(back.size()),
355                           reinterpret_cast<jbyte*>(back.data()));
356 }
357 
JavaByteArrayToByteVector(JNIEnv * env,const JavaRef<jbyteArray> & byte_array,std::vector<uint8_t> * out)358 void JavaByteArrayToByteVector(JNIEnv* env,
359                                const JavaRef<jbyteArray>& byte_array,
360                                std::vector<uint8_t>* out) {
361   DCHECK(out);
362   DCHECK(byte_array);
363   out->clear();
364   AppendJavaByteArrayToByteVector(env, byte_array, out);
365 }
366 
JavaByteArrayToByteSpan(JNIEnv * env,const JavaRef<jbyteArray> & byte_array,base::span<uint8_t> dest)367 size_t JavaByteArrayToByteSpan(JNIEnv* env,
368                                const JavaRef<jbyteArray>& byte_array,
369                                base::span<uint8_t> dest) {
370   CHECK(byte_array);
371   size_t len = SafeGetArrayLength(env, byte_array);
372   span<uint8_t> copy_dest = dest.first(len);
373 
374   static_assert(sizeof(jbyte) == sizeof(uint8_t));
375   static_assert(alignof(jbyte) <= alignof(uint8_t));
376   env->GetByteArrayRegion(byte_array.obj(), jsize{0},
377                           checked_cast<jsize>(copy_dest.size()),
378                           reinterpret_cast<jbyte*>(copy_dest.data()));
379   return len;
380 }
381 
JavaByteArrayToString(JNIEnv * env,const JavaRef<jbyteArray> & byte_array,std::string * out)382 void JavaByteArrayToString(JNIEnv* env,
383                            const JavaRef<jbyteArray>& byte_array,
384                            std::string* out) {
385   DCHECK(out);
386   DCHECK(byte_array);
387 
388   std::vector<uint8_t> byte_vector;
389   JavaByteArrayToByteVector(env, byte_array, &byte_vector);
390   out->assign(byte_vector.begin(), byte_vector.end());
391 }
392 
JavaBooleanArrayToBoolVector(JNIEnv * env,const JavaRef<jbooleanArray> & boolean_array,std::vector<bool> * out)393 void JavaBooleanArrayToBoolVector(JNIEnv* env,
394                                   const JavaRef<jbooleanArray>& boolean_array,
395                                   std::vector<bool>* out) {
396   DCHECK(out);
397   if (!boolean_array)
398     return;
399   size_t len = SafeGetArrayLength(env, boolean_array);
400   out->resize(len);
401   if (!len) {
402     return;
403   }
404   // SAFETY: `SafeGetArrayLength()` returns the number of elements in the
405   // `boolean_array`, though it can return 0 if the array is invalid. So we only
406   // call `GetBooleanArrayElements()` when it's positive. Then
407   // GetBooleanArrayElements() returns a buffer of the size returned from
408   // `SafeGetArrayLength()`.
409   span<jboolean> values = UNSAFE_BUFFERS(
410       span(env->GetBooleanArrayElements(boolean_array.obj(), nullptr), len));
411   for (size_t i = 0; i < values.size(); ++i) {
412     (*out)[i] = static_cast<bool>(values[i]);
413   }
414   env->ReleaseBooleanArrayElements(boolean_array.obj(), values.data(),
415                                    JNI_ABORT);
416 }
417 
JavaIntArrayToIntVector(JNIEnv * env,const JavaRef<jintArray> & int_array,std::vector<int> * out)418 void JavaIntArrayToIntVector(JNIEnv* env,
419                              const JavaRef<jintArray>& int_array,
420                              std::vector<int>* out) {
421   DCHECK(out);
422   size_t len = SafeGetArrayLength(env, int_array);
423   out->resize(len);
424   if (!len)
425     return;
426   env->GetIntArrayRegion(int_array.obj(), jsize{0}, checked_cast<jsize>(len),
427                          out->data());
428 }
429 
JavaLongArrayToInt64Vector(JNIEnv * env,const JavaRef<jlongArray> & long_array,std::vector<int64_t> * out)430 void JavaLongArrayToInt64Vector(JNIEnv* env,
431                                 const JavaRef<jlongArray>& long_array,
432                                 std::vector<int64_t>* out) {
433   DCHECK(out);
434   std::vector<jlong> temp;
435   JavaLongArrayToLongVector(env, long_array, &temp);
436   out->resize(0);
437   Extend(*out, temp);
438 }
439 
JavaLongArrayToLongVector(JNIEnv * env,const JavaRef<jlongArray> & long_array,std::vector<jlong> * out)440 void JavaLongArrayToLongVector(JNIEnv* env,
441                                const JavaRef<jlongArray>& long_array,
442                                std::vector<jlong>* out) {
443   DCHECK(out);
444   size_t len = SafeGetArrayLength(env, long_array);
445   out->resize(len);
446   if (!len)
447     return;
448   env->GetLongArrayRegion(long_array.obj(), jsize{0}, checked_cast<jsize>(len),
449                           out->data());
450 }
451 
JavaFloatArrayToFloatVector(JNIEnv * env,const JavaRef<jfloatArray> & float_array,std::vector<float> * out)452 void JavaFloatArrayToFloatVector(JNIEnv* env,
453                                  const JavaRef<jfloatArray>& float_array,
454                                  std::vector<float>* out) {
455   DCHECK(out);
456   size_t len = SafeGetArrayLength(env, float_array);
457   out->resize(len);
458   if (!len)
459     return;
460   env->GetFloatArrayRegion(float_array.obj(), jsize{0},
461                            checked_cast<jsize>(len), out->data());
462 }
463 
JavaDoubleArrayToDoubleVector(JNIEnv * env,const JavaRef<jdoubleArray> & double_array,std::vector<double> * out)464 void JavaDoubleArrayToDoubleVector(JNIEnv* env,
465                                    const JavaRef<jdoubleArray>& double_array,
466                                    std::vector<double>* out) {
467   DCHECK(out);
468   size_t len = SafeGetArrayLength(env, double_array);
469   out->resize(len);
470   if (!len)
471     return;
472   env->GetDoubleArrayRegion(double_array.obj(), jsize{0},
473                             checked_cast<jsize>(len), out->data());
474 }
475 
JavaArrayOfByteArrayToStringVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::string> * out)476 void JavaArrayOfByteArrayToStringVector(JNIEnv* env,
477                                         const JavaRef<jobjectArray>& array,
478                                         std::vector<std::string>* out) {
479   DCHECK(out);
480   size_t len = SafeGetArrayLength(env, array);
481   out->resize(len);
482   for (size_t i = 0; i < len; ++i) {
483     ScopedJavaLocalRef<jbyteArray> bytes_array(
484         env, static_cast<jbyteArray>(env->GetObjectArrayElement(
485                  array.obj(), checked_cast<jsize>(i))));
486     size_t bytes_len = SafeGetArrayLength(env, bytes_array);
487     // SAFETY: `SafeGetArrayLength()` returns the number of elements in the
488     // `boobytes_array`, though it can return 0 if the array is invalid. So we
489     // only call `GetByteArrayElements()` when it's positive. Then
490     // GetByteArrayElements() returns a buffer of the size returned from
491     // `SafeGetArrayLength()`.
492     if (!bytes_len) {
493       (*out)[i].clear();
494       continue;
495     }
496     span<jbyte> bytes = UNSAFE_BUFFERS(
497         span(env->GetByteArrayElements(bytes_array.obj(), nullptr), bytes_len));
498     (*out)[i] = base::as_string_view(base::as_bytes(bytes));
499     env->ReleaseByteArrayElements(bytes_array.obj(), bytes.data(), JNI_ABORT);
500   }
501 }
502 
JavaArrayOfByteArrayToBytesVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::vector<uint8_t>> * out)503 void JavaArrayOfByteArrayToBytesVector(JNIEnv* env,
504                                        const JavaRef<jobjectArray>& array,
505                                        std::vector<std::vector<uint8_t>>* out) {
506   DCHECK(out);
507   const size_t len = SafeGetArrayLength(env, array);
508   out->resize(len);
509   for (size_t i = 0; i < len; ++i) {
510     ScopedJavaLocalRef<jbyteArray> bytes_array(
511         env, static_cast<jbyteArray>(env->GetObjectArrayElement(
512                  array.obj(), checked_cast<jsize>(i))));
513     JavaByteArrayToByteVector(env, bytes_array, &(*out)[i]);
514   }
515 }
516 
Java2dStringArrayTo2dStringVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::vector<std::u16string>> * out)517 void Java2dStringArrayTo2dStringVector(
518     JNIEnv* env,
519     const JavaRef<jobjectArray>& array,
520     std::vector<std::vector<std::u16string>>* out) {
521   DCHECK(out);
522   size_t len = SafeGetArrayLength(env, array);
523   out->resize(len);
524   for (size_t i = 0; i < len; ++i) {
525     ScopedJavaLocalRef<jobjectArray> strings_array(
526         env, static_cast<jobjectArray>(env->GetObjectArrayElement(
527                  array.obj(), checked_cast<jsize>(i))));
528 
529     (*out)[i].clear();
530     AppendJavaStringArrayToStringVector(env, strings_array, &(*out)[i]);
531   }
532 }
533 
Java2dStringArrayTo2dStringVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::vector<std::string>> * out)534 void Java2dStringArrayTo2dStringVector(
535     JNIEnv* env,
536     const JavaRef<jobjectArray>& array,
537     std::vector<std::vector<std::string>>* out) {
538   DCHECK(out);
539   size_t len = SafeGetArrayLength(env, array);
540   out->resize(len);
541   for (size_t i = 0; i < len; ++i) {
542     ScopedJavaLocalRef<jobjectArray> strings_array(
543         env, static_cast<jobjectArray>(env->GetObjectArrayElement(
544                  array.obj(), checked_cast<jsize>(i))));
545 
546     (*out)[i].clear();
547     AppendJavaStringArrayToStringVector(env, strings_array, &(*out)[i]);
548   }
549 }
550 
JavaArrayOfIntArrayToIntVector(JNIEnv * env,const JavaRef<jobjectArray> & array,std::vector<std::vector<int>> * out)551 void JavaArrayOfIntArrayToIntVector(JNIEnv* env,
552                                     const JavaRef<jobjectArray>& array,
553                                     std::vector<std::vector<int>>* out) {
554   DCHECK(out);
555   size_t len = SafeGetArrayLength(env, array);
556   out->resize(len);
557   for (size_t i = 0; i < len; ++i) {
558     ScopedJavaLocalRef<jintArray> int_array(
559         env, static_cast<jintArray>(env->GetObjectArrayElement(
560                  array.obj(), checked_cast<jsize>(i))));
561     JavaIntArrayToIntVector(env, int_array, &(*out)[i]);
562   }
563 }
564 
565 }  // namespace base::android
566