Android: Add header for generated JNI code
This header will be included from generated JNI code, and acts as a bridge between JNI types in WebRTC and Chromium. Bug: webrtc:8278 Change-Id: I88331d26315aa8b258aaaaa26d82324660d648b5 NOPRESUBMIT: True Reviewed-on: https://webrtc-review.googlesource.com/3441 Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19974}
This commit is contained in:
committed by
Commit Bot
parent
0beac583bb
commit
50da5559ce
102
sdk/android/src/jni/jni_generator_helper.cc
Normal file
102
sdk/android/src/jni/jni_generator_helper.cc
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "sdk/android/src/jni/jni_generator_helper.h"
|
||||
|
||||
#include "rtc_base/atomicops.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
// JNIEnv-helper methods that RTC_CHECK success: no Java exception thrown and
|
||||
// found object/class/method/field is non-null.
|
||||
jclass GetClass(JNIEnv* jni, const char* class_name) {
|
||||
jclass clazz = jni->FindClass(class_name);
|
||||
CHECK_EXCEPTION(jni) << "error during FindClass: " << class_name;
|
||||
RTC_CHECK(clazz) << class_name;
|
||||
return clazz;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// If |atomic_class_id| set, it'll return immediately. Otherwise, it will look
|
||||
// up the class and store it. If there's a race, we take care to only store one
|
||||
// global reference (and the duplicated effort will happen only once).
|
||||
jclass LazyGetClass(JNIEnv* env,
|
||||
const char* class_name,
|
||||
base::subtle::AtomicWord* atomic_class_id) {
|
||||
static_assert(sizeof(base::subtle::AtomicWord) >= sizeof(jclass),
|
||||
"AtomicWord can't be smaller than jclass");
|
||||
base::subtle::AtomicWord value =
|
||||
rtc::AtomicOps::AcquireLoadPtr(atomic_class_id);
|
||||
if (value)
|
||||
return reinterpret_cast<jclass>(value);
|
||||
jclass clazz =
|
||||
static_cast<jclass>(env->NewGlobalRef(GetClass(env, class_name)));
|
||||
base::subtle::AtomicWord null_aw = nullptr;
|
||||
base::subtle::AtomicWord cas_result = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
atomic_class_id, null_aw,
|
||||
reinterpret_cast<base::subtle::AtomicWord>(clazz));
|
||||
if (cas_result == null_aw) {
|
||||
// We sucessfully stored |clazz| in |atomic_class_id|, so we are
|
||||
// intentionally leaking the global ref since it's now stored there.
|
||||
return clazz;
|
||||
} else {
|
||||
// Some other thread came before us and stored a global pointer in
|
||||
// |atomic_class_id|. Relase our global ref and return the ref from the
|
||||
// other thread.
|
||||
env->DeleteGlobalRef(clazz);
|
||||
return reinterpret_cast<jclass>(cas_result);
|
||||
}
|
||||
}
|
||||
|
||||
// If |atomic_method_id| set, it'll return immediately. Otherwise, it will look
|
||||
// up the method id and store it. If there's a race, it's ok since the values
|
||||
// are the same (and the duplicated effort will happen only once).
|
||||
template <MethodID::Type type>
|
||||
jmethodID MethodID::LazyGet(JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
base::subtle::AtomicWord* atomic_method_id) {
|
||||
static_assert(sizeof(base::subtle::AtomicWord) >= sizeof(jmethodID),
|
||||
"AtomicWord can't be smaller than jMethodID");
|
||||
base::subtle::AtomicWord value =
|
||||
rtc::AtomicOps::AcquireLoadPtr(atomic_method_id);
|
||||
if (value)
|
||||
return reinterpret_cast<jmethodID>(value);
|
||||
jmethodID id =
|
||||
(type == MethodID::TYPE_STATIC)
|
||||
? webrtc::jni::GetStaticMethodID(env, clazz, method_name,
|
||||
jni_signature)
|
||||
: webrtc::jni::GetMethodID(env, clazz, method_name, jni_signature);
|
||||
rtc::AtomicOps::CompareAndSwapPtr(
|
||||
atomic_method_id, base::subtle::AtomicWord(nullptr),
|
||||
reinterpret_cast<base::subtle::AtomicWord>(id));
|
||||
return id;
|
||||
}
|
||||
|
||||
// Various template instantiations.
|
||||
template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
|
||||
JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
base::subtle::AtomicWord* atomic_method_id);
|
||||
|
||||
template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
|
||||
JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
base::subtle::AtomicWord* atomic_method_id);
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
||||
107
sdk/android/src/jni/jni_generator_helper.h
Normal file
107
sdk/android/src/jni/jni_generator_helper.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
// Do not include this file directly. It's intended to be used only by the JNI
|
||||
// generation script. We are exporting types in strange namespaces in order to
|
||||
// be compatible with the generated code targeted for Chromium. We are bypassing
|
||||
// the wrapping done by Chromium's JniIntWrapper, JavaRef, and
|
||||
// ScopedJavaLocalRef, and use raw jobjects instead.
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
|
||||
#define SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
|
||||
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
#define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
|
||||
|
||||
#define BASE_EXPORT
|
||||
#define JNI_REGISTRATION_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
namespace jni_generator {
|
||||
inline void CheckException(JNIEnv* env) {
|
||||
CHECK_EXCEPTION(env);
|
||||
}
|
||||
} // namespace jni_generator
|
||||
|
||||
namespace {
|
||||
// Bypass JniIntWrapper.
|
||||
// TODO(magjed): Start using Chromium's JniIntWrapper.
|
||||
typedef jint JniIntWrapper;
|
||||
inline jint as_jint(JniIntWrapper wrapper) {
|
||||
return wrapper;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace subtle {
|
||||
// This needs to be a type that is big enough to store a jobject/jclass.
|
||||
typedef void* AtomicWord;
|
||||
} // namespace subtle
|
||||
|
||||
namespace android {
|
||||
|
||||
// Implement JavaRef and ScopedJavaLocalRef as a shallow wrapper on top of a
|
||||
// jobject/jclass, with no scoped destruction.
|
||||
// TODO(magjed): Start using Chromium's scoped Java refs.
|
||||
template <typename T>
|
||||
class JavaRef {
|
||||
public:
|
||||
JavaRef() {}
|
||||
JavaRef(JNIEnv* env, T obj) : obj_(obj) {}
|
||||
T obj() const { return obj_; }
|
||||
|
||||
// Implicit on purpose.
|
||||
JavaRef(const T& obj) : obj_(obj) {}
|
||||
operator T() const { return obj_; }
|
||||
|
||||
private:
|
||||
T obj_;
|
||||
};
|
||||
|
||||
// TODO(magjed): This looks weird, but it is safe. We don't use DeleteLocalRef
|
||||
// in WebRTC, we use ScopedLocalRefFrame instead. We should probably switch to
|
||||
// using DeleteLocalRef though.
|
||||
template <typename T>
|
||||
using ScopedJavaLocalRef = JavaRef<T>;
|
||||
|
||||
// This function will initialize |atomic_class_id| to contain a global ref to
|
||||
// the given class, and will return that ref on subsequent calls. The caller is
|
||||
// responsible to zero-initialize |atomic_class_id|. It's fine to
|
||||
// simultaneously call this on multiple threads referencing the same
|
||||
// |atomic_method_id|.
|
||||
jclass LazyGetClass(JNIEnv* env,
|
||||
const char* class_name,
|
||||
base::subtle::AtomicWord* atomic_class_id);
|
||||
|
||||
// This class is a wrapper for JNIEnv Get(Static)MethodID.
|
||||
class MethodID {
|
||||
public:
|
||||
enum Type {
|
||||
TYPE_STATIC,
|
||||
TYPE_INSTANCE,
|
||||
};
|
||||
|
||||
// This function will initialize |atomic_method_id| to contain a ref to
|
||||
// the given method, and will return that ref on subsequent calls. The caller
|
||||
// is responsible to zero-initialize |atomic_method_id|. It's fine to
|
||||
// simultaneously call this on multiple threads referencing the same
|
||||
// |atomic_method_id|.
|
||||
template <Type type>
|
||||
static jmethodID LazyGet(JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
base::subtle::AtomicWord* atomic_method_id);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
||||
|
||||
#endif // SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
|
||||
Reference in New Issue
Block a user