1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "sdk/android/native_api/jni/java_types.h"
12
13 #include <memory>
14 #include <string>
15 #include <utility>
16
17 #include "sdk/android/generated_external_classes_jni/ArrayList_jni.h"
18 #include "sdk/android/generated_external_classes_jni/Boolean_jni.h"
19 #include "sdk/android/generated_external_classes_jni/Double_jni.h"
20 #include "sdk/android/generated_external_classes_jni/Enum_jni.h"
21 #include "sdk/android/generated_external_classes_jni/Integer_jni.h"
22 #include "sdk/android/generated_external_classes_jni/Iterable_jni.h"
23 #include "sdk/android/generated_external_classes_jni/Iterator_jni.h"
24 #include "sdk/android/generated_external_classes_jni/LinkedHashMap_jni.h"
25 #include "sdk/android/generated_external_classes_jni/Long_jni.h"
26 #include "sdk/android/generated_external_classes_jni/Map_jni.h"
27 #include "sdk/android/generated_native_api_jni/JniHelper_jni.h"
28
29 namespace webrtc {
30
Iterable(JNIEnv * jni,const JavaRef<jobject> & iterable)31 Iterable::Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable)
32 : jni_(jni), iterable_(jni, iterable) {}
33
34 Iterable::Iterable(Iterable&& other) = default;
35
36 Iterable::~Iterable() = default;
37
38 // Creates an iterator representing the end of any collection.
39 Iterable::Iterator::Iterator() = default;
40
41 // Creates an iterator pointing to the beginning of the specified collection.
Iterator(JNIEnv * jni,const JavaRef<jobject> & iterable)42 Iterable::Iterator::Iterator(JNIEnv* jni, const JavaRef<jobject>& iterable)
43 : jni_(jni) {
44 iterator_ = JNI_Iterable::Java_Iterable_iterator(jni, iterable);
45 RTC_CHECK(!iterator_.is_null());
46 // Start at the first element in the collection.
47 ++(*this);
48 }
49
50 // Move constructor - necessary to be able to return iterator types from
51 // functions.
Iterator(Iterator && other)52 Iterable::Iterator::Iterator(Iterator&& other)
53 : jni_(std::move(other.jni_)),
54 iterator_(std::move(other.iterator_)),
55 value_(std::move(other.value_)) {
56 RTC_DCHECK_RUN_ON(&thread_checker_);
57 }
58
59 Iterable::Iterator::~Iterator() = default;
60
61 // Advances the iterator one step.
operator ++()62 Iterable::Iterator& Iterable::Iterator::operator++() {
63 RTC_DCHECK_RUN_ON(&thread_checker_);
64 if (AtEnd()) {
65 // Can't move past the end.
66 return *this;
67 }
68 bool has_next = JNI_Iterator::Java_Iterator_hasNext(jni_, iterator_);
69 if (!has_next) {
70 iterator_ = nullptr;
71 value_ = nullptr;
72 return *this;
73 }
74
75 value_ = JNI_Iterator::Java_Iterator_next(jni_, iterator_);
76 return *this;
77 }
78
Remove()79 void Iterable::Iterator::Remove() {
80 JNI_Iterator::Java_Iterator_remove(jni_, iterator_);
81 }
82
83 // Provides a way to compare the iterator with itself and with the end iterator.
84 // Note: all other comparison results are undefined, just like for C++ input
85 // iterators.
operator ==(const Iterable::Iterator & other)86 bool Iterable::Iterator::operator==(const Iterable::Iterator& other) {
87 // Two different active iterators should never be compared.
88 RTC_DCHECK(this == &other || AtEnd() || other.AtEnd());
89 return AtEnd() == other.AtEnd();
90 }
91
operator *()92 ScopedJavaLocalRef<jobject>& Iterable::Iterator::operator*() {
93 RTC_CHECK(!AtEnd());
94 return value_;
95 }
96
AtEnd() const97 bool Iterable::Iterator::AtEnd() const {
98 RTC_DCHECK_RUN_ON(&thread_checker_);
99 return jni_ == nullptr || IsNull(jni_, iterator_);
100 }
101
IsNull(JNIEnv * jni,const JavaRef<jobject> & obj)102 bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj) {
103 return jni->IsSameObject(obj.obj(), nullptr);
104 }
105
GetJavaEnumName(JNIEnv * jni,const JavaRef<jobject> & j_enum)106 std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum) {
107 return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum));
108 }
109
GetJavaMapEntrySet(JNIEnv * jni,const JavaRef<jobject> & j_map)110 Iterable GetJavaMapEntrySet(JNIEnv* jni, const JavaRef<jobject>& j_map) {
111 return Iterable(jni, JNI_Map::Java_Map_entrySet(jni, j_map));
112 }
113
GetJavaMapEntryKey(JNIEnv * jni,const JavaRef<jobject> & j_entry)114 ScopedJavaLocalRef<jobject> GetJavaMapEntryKey(
115 JNIEnv* jni,
116 const JavaRef<jobject>& j_entry) {
117 return jni::Java_JniHelper_getKey(jni, j_entry);
118 }
119
GetJavaMapEntryValue(JNIEnv * jni,const JavaRef<jobject> & j_entry)120 ScopedJavaLocalRef<jobject> GetJavaMapEntryValue(
121 JNIEnv* jni,
122 const JavaRef<jobject>& j_entry) {
123 return jni::Java_JniHelper_getValue(jni, j_entry);
124 }
125
JavaToNativeLong(JNIEnv * env,const JavaRef<jobject> & j_long)126 int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long) {
127 return JNI_Long::Java_Long_longValue(env, j_long);
128 }
129
JavaToNativeOptionalBool(JNIEnv * jni,const JavaRef<jobject> & boolean)130 absl::optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
131 const JavaRef<jobject>& boolean) {
132 if (IsNull(jni, boolean))
133 return absl::nullopt;
134 return JNI_Boolean::Java_Boolean_booleanValue(jni, boolean);
135 }
136
JavaToNativeOptionalDouble(JNIEnv * jni,const JavaRef<jobject> & j_double)137 absl::optional<double> JavaToNativeOptionalDouble(
138 JNIEnv* jni,
139 const JavaRef<jobject>& j_double) {
140 if (IsNull(jni, j_double))
141 return absl::nullopt;
142 return JNI_Double::Java_Double_doubleValue(jni, j_double);
143 }
144
JavaToNativeOptionalInt(JNIEnv * jni,const JavaRef<jobject> & integer)145 absl::optional<int32_t> JavaToNativeOptionalInt(
146 JNIEnv* jni,
147 const JavaRef<jobject>& integer) {
148 if (IsNull(jni, integer))
149 return absl::nullopt;
150 return JNI_Integer::Java_Integer_intValue(jni, integer);
151 }
152
153 // Given a jstring, reinterprets it to a new native string.
JavaToNativeString(JNIEnv * jni,const JavaRef<jstring> & j_string)154 std::string JavaToNativeString(JNIEnv* jni, const JavaRef<jstring>& j_string) {
155 const ScopedJavaLocalRef<jbyteArray> j_byte_array =
156 jni::Java_JniHelper_getStringBytes(jni, j_string);
157
158 const size_t len = jni->GetArrayLength(j_byte_array.obj());
159 CHECK_EXCEPTION(jni) << "error during GetArrayLength";
160 std::string str(len, '\0');
161 jni->GetByteArrayRegion(j_byte_array.obj(), 0, len,
162 reinterpret_cast<jbyte*>(&str[0]));
163 CHECK_EXCEPTION(jni) << "error during GetByteArrayRegion";
164 return str;
165 }
166
JavaToNativeStringMap(JNIEnv * jni,const JavaRef<jobject> & j_map)167 std::map<std::string, std::string> JavaToNativeStringMap(
168 JNIEnv* jni,
169 const JavaRef<jobject>& j_map) {
170 return JavaToNativeMap<std::string, std::string>(
171 jni, j_map,
172 [](JNIEnv* env, JavaRef<jobject> const& key,
173 JavaRef<jobject> const& value) {
174 return std::make_pair(
175 JavaToNativeString(env, static_java_ref_cast<jstring>(env, key)),
176 JavaToNativeString(env, static_java_ref_cast<jstring>(env, value)));
177 });
178 }
179
NativeToJavaBoolean(JNIEnv * env,bool b)180 ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b) {
181 return JNI_Boolean::Java_Boolean_ConstructorJLB_Z(env, b);
182 }
183
NativeToJavaDouble(JNIEnv * env,double d)184 ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d) {
185 return JNI_Double::Java_Double_ConstructorJLD_D(env, d);
186 }
187
NativeToJavaInteger(JNIEnv * jni,int32_t i)188 ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i) {
189 return JNI_Integer::Java_Integer_ConstructorJLI_I(jni, i);
190 }
191
NativeToJavaLong(JNIEnv * env,int64_t u)192 ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u) {
193 return JNI_Long::Java_Long_ConstructorJLLO_J(env, u);
194 }
195
NativeToJavaString(JNIEnv * env,const char * str)196 ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* env, const char* str) {
197 jstring j_str = env->NewStringUTF(str);
198 CHECK_EXCEPTION(env) << "error during NewStringUTF";
199 return ScopedJavaLocalRef<jstring>(env, j_str);
200 }
201
NativeToJavaString(JNIEnv * jni,const std::string & str)202 ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
203 const std::string& str) {
204 return NativeToJavaString(jni, str.c_str());
205 }
206
NativeToJavaDouble(JNIEnv * jni,const absl::optional<double> & optional_double)207 ScopedJavaLocalRef<jobject> NativeToJavaDouble(
208 JNIEnv* jni,
209 const absl::optional<double>& optional_double) {
210 return optional_double ? NativeToJavaDouble(jni, *optional_double) : nullptr;
211 }
212
NativeToJavaInteger(JNIEnv * jni,const absl::optional<int32_t> & optional_int)213 ScopedJavaLocalRef<jobject> NativeToJavaInteger(
214 JNIEnv* jni,
215 const absl::optional<int32_t>& optional_int) {
216 return optional_int ? NativeToJavaInteger(jni, *optional_int) : nullptr;
217 }
218
NativeToJavaString(JNIEnv * jni,const absl::optional<std::string> & str)219 ScopedJavaLocalRef<jstring> NativeToJavaString(
220 JNIEnv* jni,
221 const absl::optional<std::string>& str) {
222 return str ? NativeToJavaString(jni, *str) : nullptr;
223 }
224
NativeToJavaByteArray(JNIEnv * env,rtc::ArrayView<int8_t> container)225 ScopedJavaLocalRef<jbyteArray> NativeToJavaByteArray(
226 JNIEnv* env,
227 rtc::ArrayView<int8_t> container) {
228 ScopedJavaLocalRef<jbyteArray> jarray(env,
229 env->NewByteArray(container.size()));
230 int8_t* array_ptr =
231 env->GetByteArrayElements(jarray.obj(), /*isCopy=*/nullptr);
232 memcpy(array_ptr, container.data(), container.size() * sizeof(int8_t));
233 env->ReleaseByteArrayElements(jarray.obj(), array_ptr, /*mode=*/0);
234 return jarray;
235 }
236
NativeToJavaIntArray(JNIEnv * env,rtc::ArrayView<int32_t> container)237 ScopedJavaLocalRef<jintArray> NativeToJavaIntArray(
238 JNIEnv* env,
239 rtc::ArrayView<int32_t> container) {
240 ScopedJavaLocalRef<jintArray> jarray(env, env->NewIntArray(container.size()));
241 int32_t* array_ptr =
242 env->GetIntArrayElements(jarray.obj(), /*isCopy=*/nullptr);
243 memcpy(array_ptr, container.data(), container.size() * sizeof(int32_t));
244 env->ReleaseIntArrayElements(jarray.obj(), array_ptr, /*mode=*/0);
245 return jarray;
246 }
247
JavaToNativeByteArray(JNIEnv * env,const JavaRef<jbyteArray> & jarray)248 std::vector<int8_t> JavaToNativeByteArray(JNIEnv* env,
249 const JavaRef<jbyteArray>& jarray) {
250 int8_t* array_ptr =
251 env->GetByteArrayElements(jarray.obj(), /*isCopy=*/nullptr);
252 size_t array_length = env->GetArrayLength(jarray.obj());
253 std::vector<int8_t> container(array_ptr, array_ptr + array_length);
254 env->ReleaseByteArrayElements(jarray.obj(), array_ptr, /*mode=*/JNI_ABORT);
255 return container;
256 }
257
JavaToNativeIntArray(JNIEnv * env,const JavaRef<jintArray> & jarray)258 std::vector<int32_t> JavaToNativeIntArray(JNIEnv* env,
259 const JavaRef<jintArray>& jarray) {
260 int32_t* array_ptr =
261 env->GetIntArrayElements(jarray.obj(), /*isCopy=*/nullptr);
262 size_t array_length = env->GetArrayLength(jarray.obj());
263 std::vector<int32_t> container(array_ptr, array_ptr + array_length);
264 env->ReleaseIntArrayElements(jarray.obj(), array_ptr, /*mode=*/JNI_ABORT);
265 return container;
266 }
267
NativeToJavaBooleanArray(JNIEnv * env,const std::vector<bool> & container)268 ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
269 JNIEnv* env,
270 const std::vector<bool>& container) {
271 return NativeToJavaObjectArray(env, container, java_lang_Boolean_clazz(env),
272 &NativeToJavaBoolean);
273 }
274
NativeToJavaDoubleArray(JNIEnv * env,const std::vector<double> & container)275 ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
276 JNIEnv* env,
277 const std::vector<double>& container) {
278 ScopedJavaLocalRef<jobject> (*convert_function)(JNIEnv*, double) =
279 &NativeToJavaDouble;
280 return NativeToJavaObjectArray(env, container, java_lang_Double_clazz(env),
281 convert_function);
282 }
283
NativeToJavaIntegerArray(JNIEnv * env,const std::vector<int32_t> & container)284 ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
285 JNIEnv* env,
286 const std::vector<int32_t>& container) {
287 ScopedJavaLocalRef<jobject> (*convert_function)(JNIEnv*, int32_t) =
288 &NativeToJavaInteger;
289 return NativeToJavaObjectArray(env, container, java_lang_Integer_clazz(env),
290 convert_function);
291 }
292
NativeToJavaLongArray(JNIEnv * env,const std::vector<int64_t> & container)293 ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
294 JNIEnv* env,
295 const std::vector<int64_t>& container) {
296 return NativeToJavaObjectArray(env, container, java_lang_Long_clazz(env),
297 &NativeToJavaLong);
298 }
299
NativeToJavaStringArray(JNIEnv * env,const std::vector<std::string> & container)300 ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
301 JNIEnv* env,
302 const std::vector<std::string>& container) {
303 ScopedJavaLocalRef<jstring> (*convert_function)(JNIEnv*, const std::string&) =
304 &NativeToJavaString;
305 return NativeToJavaObjectArray(
306 env, container,
307 static_cast<jclass>(jni::Java_JniHelper_getStringClass(env).obj()),
308 convert_function);
309 }
310
JavaListBuilder(JNIEnv * env)311 JavaListBuilder::JavaListBuilder(JNIEnv* env)
312 : env_(env), j_list_(JNI_ArrayList::Java_ArrayList_ConstructorJUALI(env)) {}
313
314 JavaListBuilder::~JavaListBuilder() = default;
315
add(const JavaRef<jobject> & element)316 void JavaListBuilder::add(const JavaRef<jobject>& element) {
317 JNI_ArrayList::Java_ArrayList_addZ_JUE(env_, j_list_, element);
318 }
319
JavaMapBuilder(JNIEnv * env)320 JavaMapBuilder::JavaMapBuilder(JNIEnv* env)
321 : env_(env),
322 j_map_(JNI_LinkedHashMap::Java_LinkedHashMap_ConstructorJULIHM(env)) {}
323
324 JavaMapBuilder::~JavaMapBuilder() = default;
325
put(const JavaRef<jobject> & key,const JavaRef<jobject> & value)326 void JavaMapBuilder::put(const JavaRef<jobject>& key,
327 const JavaRef<jobject>& value) {
328 JNI_Map::Java_Map_put(env_, j_map_, key, value);
329 }
330
NativeToJavaPointer(void * ptr)331 jlong NativeToJavaPointer(void* ptr) {
332 static_assert(sizeof(intptr_t) <= sizeof(jlong),
333 "Time to rethink the use of jlongs");
334 // Going through intptr_t to be obvious about the definedness of the
335 // conversion from pointer to integral type. intptr_t to jlong is a standard
336 // widening by the static_assert above.
337 jlong ret = reinterpret_cast<intptr_t>(ptr);
338 RTC_DCHECK(reinterpret_cast<void*>(ret) == ptr);
339 return ret;
340 }
341
342 // Given a list of jstrings, reinterprets it to a new vector of native strings.
JavaToStdVectorStrings(JNIEnv * jni,const JavaRef<jobject> & list)343 std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
344 const JavaRef<jobject>& list) {
345 std::vector<std::string> converted_list;
346 if (!list.is_null()) {
347 for (const JavaRef<jobject>& str : Iterable(jni, list)) {
348 converted_list.push_back(JavaToStdString(
349 jni, JavaParamRef<jstring>(static_cast<jstring>(str.obj()))));
350 }
351 }
352 return converted_list;
353 }
354
355 } // namespace webrtc
356