mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
Migrate webrtc to stop using its own JniZero mirror classes
Bug: chromium:325408567 Change-Id: I2eb33b077148bf89223f1f69b07339fc9f2d948e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/347921 Reviewed-by: Jeremy Leconte <jleconte@google.com> Commit-Queue: Jeremy Leconte <jleconte@google.com> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42151}
This commit is contained in:
parent
454d65196e
commit
bc5c5e9d66
21 changed files with 75 additions and 492 deletions
|
@ -185,7 +185,8 @@ void AndroidVoipClient::GetSupportedCodecs(JNIEnv* env) {
|
|||
webrtc::ScopedJavaLocalRef<jstring> (*convert_function)(
|
||||
JNIEnv*, const std::string&) = &webrtc::NativeToJavaString;
|
||||
Java_VoipClient_onGetSupportedCodecsCompleted(
|
||||
env_, j_voip_client_, NativeToJavaList(env_, names, convert_function));
|
||||
env_, j_voip_client_,
|
||||
webrtc::NativeToJavaList(env_, names, convert_function));
|
||||
}
|
||||
|
||||
void AndroidVoipClient::GetLocalIPAddress(JNIEnv* env) {
|
||||
|
|
|
@ -141,6 +141,7 @@ if (is_android) {
|
|||
":video_egl_jni",
|
||||
"../../pc:libjingle_peerconnection",
|
||||
"../../rtc_base:ssl",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
output_extension = "so"
|
||||
}
|
||||
|
@ -936,7 +937,6 @@ if (current_os == "linux" || is_android) {
|
|||
"native_api/jni/class_loader.cc",
|
||||
"native_api/jni/java_types.cc",
|
||||
"native_api/jni/jvm.cc",
|
||||
"src/jni/jni_generator_helper.cc",
|
||||
"src/jni/jni_generator_helper.h",
|
||||
]
|
||||
|
||||
|
@ -956,6 +956,7 @@ if (current_os == "linux" || is_android) {
|
|||
"../../api:sequence_checker",
|
||||
"//api:array_view",
|
||||
"//rtc_base:checks",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
|
@ -1116,7 +1117,10 @@ if (current_os == "linux" || is_android) {
|
|||
"src/jni/jvm.h",
|
||||
]
|
||||
|
||||
deps = [ "../../rtc_base:checks" ]
|
||||
deps = [
|
||||
"../../rtc_base:checks",
|
||||
"//third_party/jni_zero",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("videoframe_jni") {
|
||||
|
|
|
@ -23,7 +23,7 @@ JNI_FUNCTION_DECLARATION(void,
|
|||
jclass,
|
||||
jstring j_message) {
|
||||
std::string message =
|
||||
JavaToNativeString(jni, JavaParamRef<jstring>(j_message));
|
||||
JavaToNativeString(jni, JavaParamRef<jstring>(jni, j_message));
|
||||
RTC_LOG(LS_INFO) << message;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ JNI_FUNCTION_DECLARATION(jint,
|
|||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject video_frame_buffer) {
|
||||
const JavaParamRef<jobject> j_video_frame_buffer(video_frame_buffer);
|
||||
const JavaParamRef<jobject> j_video_frame_buffer(jni, video_frame_buffer);
|
||||
rtc::scoped_refptr<VideoFrameBuffer> buffer =
|
||||
JavaToNativeFrameBuffer(jni, j_video_frame_buffer);
|
||||
return static_cast<jint>(buffer->type());
|
||||
|
@ -32,7 +32,7 @@ JNI_FUNCTION_DECLARATION(jobject,
|
|||
JNIEnv* jni,
|
||||
jclass,
|
||||
jobject i420_buffer) {
|
||||
const JavaParamRef<jobject> j_i420_buffer(i420_buffer);
|
||||
const JavaParamRef<jobject> j_i420_buffer(jni, i420_buffer);
|
||||
rtc::scoped_refptr<VideoFrameBuffer> buffer =
|
||||
JavaToNativeFrameBuffer(jni, j_i420_buffer);
|
||||
const I420BufferInterface* inputBuffer = buffer->GetI420();
|
||||
|
|
|
@ -2,4 +2,5 @@ include_rules = [
|
|||
"+modules/audio_device/include/audio_device.h",
|
||||
"+modules/utility/include/jvm_android.h",
|
||||
"+system_wrappers/include",
|
||||
"+third_party/jni_zero",
|
||||
]
|
||||
|
|
|
@ -40,7 +40,7 @@ void GetDefaultAudioParameters(JNIEnv* env,
|
|||
jobject application_context,
|
||||
AudioParameters* input_parameters,
|
||||
AudioParameters* output_parameters) {
|
||||
const JavaParamRef<jobject> j_context(application_context);
|
||||
const JavaParamRef<jobject> j_context(env, application_context);
|
||||
const ScopedJavaLocalRef<jobject> j_audio_manager =
|
||||
jni::GetAudioManager(env, j_context);
|
||||
const int input_sample_rate = jni::GetDefaultSampleRate(env, j_audio_manager);
|
||||
|
@ -78,7 +78,7 @@ CreateJavaInputAndAAudioOutputAudioDeviceModule(JNIEnv* env,
|
|||
jobject application_context) {
|
||||
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
||||
// Get default audio input/output parameters.
|
||||
const JavaParamRef<jobject> j_context(application_context);
|
||||
const JavaParamRef<jobject> j_context(env, application_context);
|
||||
const ScopedJavaLocalRef<jobject> j_audio_manager =
|
||||
jni::GetAudioManager(env, j_context);
|
||||
AudioParameters input_parameters;
|
||||
|
@ -104,7 +104,7 @@ rtc::scoped_refptr<AudioDeviceModule> CreateJavaAudioDeviceModule(
|
|||
jobject application_context) {
|
||||
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
||||
// Get default audio input/output parameters.
|
||||
const JavaParamRef<jobject> j_context(application_context);
|
||||
const JavaParamRef<jobject> j_context(env, application_context);
|
||||
const ScopedJavaLocalRef<jobject> j_audio_manager =
|
||||
jni::GetAudioManager(env, j_context);
|
||||
AudioParameters input_parameters;
|
||||
|
@ -155,7 +155,7 @@ CreateJavaInputAndOpenSLESOutputAudioDeviceModule(JNIEnv* env,
|
|||
jobject application_context) {
|
||||
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
||||
// Get default audio input/output parameters.
|
||||
const JavaParamRef<jobject> j_context(application_context);
|
||||
const JavaParamRef<jobject> j_context(env, application_context);
|
||||
const ScopedJavaLocalRef<jobject> j_audio_manager =
|
||||
jni::GetAudioManager(env, j_context);
|
||||
AudioParameters input_parameters;
|
||||
|
|
|
@ -21,29 +21,29 @@
|
|||
namespace webrtc {
|
||||
|
||||
SdpVideoFormat JavaToNativeVideoCodecInfo(JNIEnv* jni, jobject codec_info) {
|
||||
return jni::VideoCodecInfoToSdpVideoFormat(jni,
|
||||
JavaParamRef<jobject>(codec_info));
|
||||
return jni::VideoCodecInfoToSdpVideoFormat(
|
||||
jni, JavaParamRef<jobject>(jni, codec_info));
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoDecoderFactory> JavaToNativeVideoDecoderFactory(
|
||||
JNIEnv* jni,
|
||||
jobject decoder_factory) {
|
||||
return std::make_unique<jni::VideoDecoderFactoryWrapper>(
|
||||
jni, JavaParamRef<jobject>(decoder_factory));
|
||||
jni, JavaParamRef<jobject>(jni, decoder_factory));
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoEncoderFactory> JavaToNativeVideoEncoderFactory(
|
||||
JNIEnv* jni,
|
||||
jobject encoder_factory) {
|
||||
return std::make_unique<jni::VideoEncoderFactoryWrapper>(
|
||||
jni, JavaParamRef<jobject>(encoder_factory));
|
||||
jni, JavaParamRef<jobject>(jni, encoder_factory));
|
||||
}
|
||||
|
||||
std::vector<VideoEncoder::ResolutionBitrateLimits>
|
||||
JavaToNativeResolutionBitrateLimits(JNIEnv* jni,
|
||||
const jobjectArray j_bitrate_limits_array) {
|
||||
return jni::JavaToNativeResolutionBitrateLimits(
|
||||
jni, JavaParamRef<jobjectArray>(j_bitrate_limits_array));
|
||||
jni, JavaParamRef<jobjectArray>(jni, j_bitrate_limits_array));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_native_api_jni/WebRtcClassLoader_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
// Abort the process if `jni` has a Java exception pending. This macros uses the
|
||||
// comma operator to execute ExceptionDescribe and ExceptionClear ignoring their
|
||||
|
@ -62,11 +62,18 @@ class ClassLoader {
|
|||
|
||||
static ClassLoader* g_class_loader = nullptr;
|
||||
|
||||
jclass GetClass(JNIEnv* env, const char* class_name, const char* unused) {
|
||||
RTC_CHECK(g_class_loader);
|
||||
return static_cast<jclass>(
|
||||
g_class_loader->FindClass(env, class_name).Release());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void InitClassLoader(JNIEnv* env) {
|
||||
RTC_CHECK(g_class_loader == nullptr);
|
||||
g_class_loader = new ClassLoader(env);
|
||||
jni_zero::SetClassResolver(&GetClass);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* c_name) {
|
||||
|
|
|
@ -393,7 +393,7 @@ std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
|
|||
if (!list.is_null()) {
|
||||
for (const JavaRef<jobject>& str : Iterable(jni, list)) {
|
||||
converted_list.push_back(JavaToStdString(
|
||||
jni, JavaParamRef<jstring>(static_cast<jstring>(str.obj()))));
|
||||
jni, JavaParamRef<jstring>(jni, static_cast<jstring>(str.obj()))));
|
||||
}
|
||||
}
|
||||
return converted_list;
|
||||
|
|
|
@ -340,7 +340,7 @@ inline std::string JavaToStdString(JNIEnv* jni,
|
|||
|
||||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
|
||||
return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
|
||||
return JavaToStdString(jni, JavaParamRef<jstring>(jni, j_string));
|
||||
}
|
||||
|
||||
// Deprecated. Use JavaListToNativeVector<std::string, jstring> instead.
|
||||
|
@ -360,7 +360,7 @@ inline std::map<std::string, std::string> JavaToStdMapStrings(
|
|||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
|
||||
jobject j_map) {
|
||||
return JavaToStdMapStrings(jni, JavaParamRef<jobject>(j_map));
|
||||
return JavaToStdMapStrings(jni, JavaParamRef<jobject>(jni, j_map));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -8,56 +8,10 @@
|
|||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Originally this class is from Chromium.
|
||||
// https://cs.chromium.org/chromium/src/base/android/jni_int_wrapper.h.
|
||||
|
||||
#ifndef SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
|
||||
#define SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Wrapper used to receive int when calling Java from native. The wrapper
|
||||
// disallows automatic conversion of anything besides int32_t to a jint.
|
||||
// Checking is only done in debugging builds.
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
typedef jint JniIntWrapper;
|
||||
|
||||
// This inline is sufficiently trivial that it does not change the
|
||||
// final code generated by g++.
|
||||
inline jint as_jint(JniIntWrapper wrapper) {
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class JniIntWrapper {
|
||||
public:
|
||||
JniIntWrapper() : i_(0) {}
|
||||
JniIntWrapper(int32_t i) : i_(i) {} // NOLINT(runtime/explicit)
|
||||
explicit JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {}
|
||||
|
||||
jint as_jint() const { return i_; }
|
||||
|
||||
// If you get an "invokes a deleted function" error at the lines below it is
|
||||
// because you used an implicit conversion to convert e.g. a long to an
|
||||
// int32_t when calling Java. We disallow this. If you want a lossy
|
||||
// conversion, please use an explicit conversion in your C++ code.
|
||||
JniIntWrapper(uint32_t) = delete; // NOLINT(runtime/explicit)
|
||||
JniIntWrapper(uint64_t) = delete; // NOLINT(runtime/explicit)
|
||||
JniIntWrapper(int64_t) = delete; // NOLINT(runtime/explicit)
|
||||
|
||||
private:
|
||||
const jint i_;
|
||||
};
|
||||
|
||||
inline jint as_jint(const JniIntWrapper& wrapper) {
|
||||
return wrapper.as_jint();
|
||||
}
|
||||
|
||||
#endif // NDEBUG
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
#endif // SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
|
||||
|
|
|
@ -19,200 +19,13 @@
|
|||
#include <utility>
|
||||
|
||||
#include "sdk/android/native_api/jni/jvm.h"
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
|
||||
// for allowing functions to accept a reference without having to mandate
|
||||
// whether it is a local or global type.
|
||||
template <typename T>
|
||||
class JavaRef;
|
||||
|
||||
// Template specialization of JavaRef, which acts as the base class for all
|
||||
// other JavaRef<> template types. This allows you to e.g. pass JavaRef<jstring>
|
||||
// into a function taking const JavaRef<jobject>&.
|
||||
template <>
|
||||
class JavaRef<jobject> {
|
||||
public:
|
||||
JavaRef(const JavaRef&) = delete;
|
||||
JavaRef& operator=(const JavaRef&) = delete;
|
||||
|
||||
jobject obj() const { return obj_; }
|
||||
bool is_null() const {
|
||||
// This is not valid for weak references. For weak references you need to
|
||||
// use env->IsSameObject(objc_, nullptr), but that should be avoided anyway
|
||||
// since it does not prevent the object from being freed immediately
|
||||
// thereafter. Consequently, programmers should not use this check on weak
|
||||
// references anyway and should first make a ScopedJavaLocalRef or
|
||||
// ScopedJavaGlobalRef before checking if it is null.
|
||||
return obj_ == nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr JavaRef() : obj_(nullptr) {}
|
||||
explicit JavaRef(jobject obj) : obj_(obj) {}
|
||||
jobject obj_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JavaRef : public JavaRef<jobject> {
|
||||
public:
|
||||
JavaRef(const JavaRef&) = delete;
|
||||
JavaRef& operator=(const JavaRef&) = delete;
|
||||
|
||||
T obj() const { return static_cast<T>(obj_); }
|
||||
|
||||
protected:
|
||||
JavaRef() : JavaRef<jobject>(nullptr) {}
|
||||
explicit JavaRef(T obj) : JavaRef<jobject>(obj) {}
|
||||
};
|
||||
|
||||
// Holds a local reference to a JNI method parameter.
|
||||
// Method parameters should not be deleted, and so this class exists purely to
|
||||
// wrap them as a JavaRef<T> in the JNI binding generator. Do not create
|
||||
// instances manually.
|
||||
template <typename T>
|
||||
class JavaParamRef : public JavaRef<T> {
|
||||
public:
|
||||
// Assumes that `obj` is a parameter passed to a JNI method from Java.
|
||||
// Does not assume ownership as parameters should not be deleted.
|
||||
explicit JavaParamRef(T obj) : JavaRef<T>(obj) {}
|
||||
JavaParamRef(JNIEnv*, T obj) : JavaRef<T>(obj) {}
|
||||
|
||||
JavaParamRef(const JavaParamRef&) = delete;
|
||||
JavaParamRef& operator=(const JavaParamRef&) = delete;
|
||||
};
|
||||
|
||||
// Holds a local reference to a Java object. The local reference is scoped
|
||||
// to the lifetime of this object.
|
||||
// Instances of this class may hold onto any JNIEnv passed into it until
|
||||
// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
|
||||
// thread, objects of this class must be created, used, and destroyed, on a
|
||||
// single thread.
|
||||
// Therefore, this class should only be used as a stack-based object and from a
|
||||
// single thread. If you wish to have the reference outlive the current
|
||||
// callstack (e.g. as a class member) or you wish to pass it across threads,
|
||||
// use a ScopedJavaGlobalRef instead.
|
||||
template <typename T>
|
||||
class ScopedJavaLocalRef : public JavaRef<T> {
|
||||
public:
|
||||
ScopedJavaLocalRef() = default;
|
||||
ScopedJavaLocalRef(std::nullptr_t) {} // NOLINT(runtime/explicit)
|
||||
|
||||
ScopedJavaLocalRef(JNIEnv* env, const JavaRef<T>& other) : env_(env) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
// Allow constructing e.g. ScopedJavaLocalRef<jobject> from
|
||||
// ScopedJavaLocalRef<jstring>.
|
||||
template <typename G>
|
||||
ScopedJavaLocalRef(ScopedJavaLocalRef<G>&& other) : env_(other.env()) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
|
||||
// Assumes that `obj` is a reference to a Java object and takes
|
||||
// ownership of this reference. This should preferably not be used
|
||||
// outside of JNI helper functions.
|
||||
ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(obj), env_(env) {}
|
||||
|
||||
~ScopedJavaLocalRef() {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
}
|
||||
|
||||
void operator=(const ScopedJavaLocalRef& other) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
void operator=(ScopedJavaLocalRef&& other) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JNIEnv* env() const { return env_; }
|
||||
|
||||
private:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
enum OwnershipPolicy {
|
||||
// The scoped object takes ownership of an object by taking over an existing
|
||||
// ownership claim.
|
||||
ADOPT,
|
||||
// The scoped object will retain the the object and any initial ownership is
|
||||
// not changed.
|
||||
RETAIN
|
||||
};
|
||||
|
||||
void Reset(T obj, OwnershipPolicy policy) {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
obj_ = (obj != nullptr && policy == OwnershipPolicy::RETAIN)
|
||||
? env_->NewLocalRef(obj)
|
||||
: obj;
|
||||
}
|
||||
|
||||
JNIEnv* const env_ = AttachCurrentThreadIfNeeded();
|
||||
};
|
||||
|
||||
// Holds a global reference to a Java object. The global reference is scoped
|
||||
// to the lifetime of this object. This class does not hold onto any JNIEnv*
|
||||
// passed to it, hence it is safe to use across threads (within the constraints
|
||||
// imposed by the underlying Java object that it references).
|
||||
template <typename T>
|
||||
class ScopedJavaGlobalRef : public JavaRef<T> {
|
||||
public:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
ScopedJavaGlobalRef() = default;
|
||||
explicit constexpr ScopedJavaGlobalRef(std::nullptr_t) {}
|
||||
ScopedJavaGlobalRef(JNIEnv* env, const JavaRef<T>& other)
|
||||
: JavaRef<T>(static_cast<T>(env->NewGlobalRef(other.obj()))) {}
|
||||
explicit ScopedJavaGlobalRef(const ScopedJavaLocalRef<T>& other)
|
||||
: ScopedJavaGlobalRef(other.env(), other) {}
|
||||
ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other)
|
||||
: JavaRef<T>(other.Release()) {}
|
||||
|
||||
~ScopedJavaGlobalRef() {
|
||||
if (obj_ != nullptr)
|
||||
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
|
||||
}
|
||||
|
||||
ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete;
|
||||
ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef&) = delete;
|
||||
|
||||
void operator=(const JavaRef<T>& other) {
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
if (obj_ != nullptr) {
|
||||
env->DeleteGlobalRef(obj_);
|
||||
}
|
||||
obj_ = other.is_null() ? nullptr : env->NewGlobalRef(other.obj());
|
||||
}
|
||||
|
||||
void operator=(std::nullptr_t) {
|
||||
if (obj_ != nullptr) {
|
||||
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
|
||||
}
|
||||
obj_ = nullptr;
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
using jni_zero::JavaParamRef;
|
||||
using jni_zero::JavaRef;
|
||||
using jni_zero::ScopedJavaGlobalRef;
|
||||
using jni_zero::ScopedJavaLocalRef;
|
||||
|
||||
template <typename T>
|
||||
inline ScopedJavaLocalRef<T> static_java_ref_cast(JNIEnv* env,
|
||||
|
|
|
@ -20,7 +20,7 @@ std::unique_ptr<rtc::NetworkMonitorFactory> CreateAndroidNetworkMonitorFactory(
|
|||
JNIEnv* env,
|
||||
jobject application_context) {
|
||||
return std::make_unique<jni::AndroidNetworkMonitorFactory>(
|
||||
env, JavaParamRef<jobject>(application_context));
|
||||
env, JavaParamRef<jobject>(env, application_context));
|
||||
}
|
||||
|
||||
std::unique_ptr<rtc::NetworkMonitorFactory>
|
||||
|
|
|
@ -22,7 +22,7 @@ std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> JavaToNativeVideoSink(
|
|||
JNIEnv* jni,
|
||||
jobject video_sink) {
|
||||
return std::make_unique<jni::VideoSinkWrapper>(
|
||||
jni, JavaParamRef<jobject>(video_sink));
|
||||
jni, JavaParamRef<jobject>(jni, video_sink));
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaVideoFrame(JNIEnv* jni,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
include_rules = [
|
||||
"+third_party/libyuv",
|
||||
"+third_party/jni_zero",
|
||||
"+call/callfactoryinterface.h",
|
||||
"+common_video",
|
||||
"+logging/rtc_event_log/rtc_event_log_factory.h",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_video_jni/JavaI420Buffer_jni.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* 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 "sdk/android/native_api/jni/class_loader.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// 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,
|
||||
std::atomic<jclass>* atomic_class_id) {
|
||||
const jclass value = std::atomic_load(atomic_class_id);
|
||||
if (value)
|
||||
return value;
|
||||
webrtc::ScopedJavaGlobalRef<jclass> clazz(webrtc::GetClass(env, class_name));
|
||||
RTC_CHECK(!clazz.is_null()) << class_name;
|
||||
jclass cas_result = nullptr;
|
||||
if (std::atomic_compare_exchange_strong(atomic_class_id, &cas_result,
|
||||
clazz.obj())) {
|
||||
// We sucessfully stored `clazz` in `atomic_class_id`, so we are
|
||||
// intentionally leaking the global ref since it's now stored there.
|
||||
return clazz.Release();
|
||||
} 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.
|
||||
return 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,
|
||||
std::atomic<jmethodID>* atomic_method_id) {
|
||||
const jmethodID value = std::atomic_load(atomic_method_id);
|
||||
if (value)
|
||||
return value;
|
||||
auto get_method_ptr = type == MethodID::TYPE_STATIC
|
||||
? &JNIEnv::GetStaticMethodID
|
||||
: &JNIEnv::GetMethodID;
|
||||
jmethodID id = (env->*get_method_ptr)(clazz, method_name, jni_signature);
|
||||
CHECK_EXCEPTION(env) << "error during GetMethodID: " << method_name << ", "
|
||||
<< jni_signature;
|
||||
RTC_CHECK(id) << method_name << ", " << jni_signature;
|
||||
std::atomic_store(atomic_method_id, 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,
|
||||
std::atomic<jmethodID>* atomic_method_id);
|
||||
|
||||
template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
|
||||
JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
std::atomic<jmethodID>* atomic_method_id);
|
||||
|
||||
} // namespace webrtc
|
|
@ -18,15 +18,8 @@
|
|||
|
||||
#include <atomic>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/native_api/jni/jni_int_wrapper.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
#include "third_party/jni_zero/jni_zero_internal.h"
|
||||
|
||||
#define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
|
||||
#define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \
|
||||
RTC_DCHECK(native_ptr) << method_name;
|
||||
|
||||
#define BASE_EXPORT
|
||||
#define JNI_REGISTRATION_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86)
|
||||
|
@ -39,130 +32,22 @@
|
|||
#define JNI_GENERATOR_EXPORT extern "C" JNIEXPORT JNICALL
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86)
|
||||
// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
|
||||
// x86 - use force_align_arg_pointer to realign the stack at the JNI
|
||||
// boundary. crbug.com/655248
|
||||
#define JNI_BOUNDARY_EXPORT \
|
||||
extern "C" __attribute__((visibility("default"), force_align_arg_pointer))
|
||||
#else
|
||||
#define JNI_BOUNDARY_EXPORT extern "C" __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#if defined(COMPONENT_BUILD)
|
||||
#define JNI_ZERO_COMPONENT_BUILD_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define JNI_ZERO_COMPONENT_BUILD_EXPORT
|
||||
#endif
|
||||
|
||||
#define CHECK_EXCEPTION(jni) \
|
||||
RTC_CHECK(!jni->ExceptionCheck()) \
|
||||
<< (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// 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,
|
||||
std::atomic<jclass>* 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,
|
||||
std::atomic<jmethodID>* atomic_method_id);
|
||||
};
|
||||
|
||||
using jni_zero::JavaParamRef;
|
||||
using jni_zero::JavaRef;
|
||||
using jni_zero::ScopedJavaGlobalRef;
|
||||
using jni_zero::ScopedJavaLocalRef;
|
||||
} // namespace webrtc
|
||||
|
||||
namespace jni_zero {
|
||||
// Re-export relevant classes into the namespaces the script expects.
|
||||
using webrtc::JavaParamRef;
|
||||
using webrtc::JavaRef;
|
||||
using webrtc::LazyGetClass;
|
||||
using webrtc::MethodID;
|
||||
using webrtc::ScopedJavaLocalRef;
|
||||
|
||||
inline void CheckException(JNIEnv* env) {
|
||||
CHECK_EXCEPTION(env);
|
||||
}
|
||||
|
||||
// A 32 bit number could be an address on stack. Random 64 bit marker on the
|
||||
// stack is much less likely to be present on stack.
|
||||
constexpr uint64_t kJniStackMarkerValue = 0xbdbdef1bebcade1b;
|
||||
|
||||
// Context about the JNI call with exception checked to be stored in stack.
|
||||
template <bool checked>
|
||||
struct BASE_EXPORT JniJavaCallContext {
|
||||
public:
|
||||
inline JniJavaCallContext() {
|
||||
// TODO(ssid): Implement for other architectures.
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
// This assumes that this method does not increment the stack pointer.
|
||||
asm volatile("mov %0, sp" : "=r"(sp));
|
||||
#else
|
||||
sp = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Force no inline to reduce code size.
|
||||
template <jni_zero::MethodID::Type type>
|
||||
void Init(JNIEnv* env,
|
||||
jclass clazz,
|
||||
const char* method_name,
|
||||
const char* jni_signature,
|
||||
std::atomic<jmethodID>* atomic_method_id) {
|
||||
env_ = env;
|
||||
|
||||
// Make sure compiler doesn't optimize out the assignment.
|
||||
memcpy(&marker, &kJniStackMarkerValue, sizeof(kJniStackMarkerValue));
|
||||
// Gets PC of the calling function.
|
||||
pc = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
|
||||
|
||||
method_id_ = jni_zero::MethodID::LazyGet<type>(
|
||||
env, clazz, method_name, jni_signature, atomic_method_id);
|
||||
}
|
||||
|
||||
~JniJavaCallContext() {
|
||||
// Reset so that spurious marker finds are avoided.
|
||||
memset(&marker, 0, sizeof(marker));
|
||||
if (checked) {
|
||||
jni_zero::CheckException(env_);
|
||||
}
|
||||
}
|
||||
|
||||
jmethodID method_id() { return method_id_; }
|
||||
|
||||
private:
|
||||
uint64_t marker;
|
||||
uintptr_t sp;
|
||||
uintptr_t pc;
|
||||
|
||||
JNIEnv* env_;
|
||||
jmethodID method_id_;
|
||||
};
|
||||
// Re-export helpers in the old jni_generator namespace.
|
||||
// TODO(b/319078685): Remove once all uses of the jni_generator has been
|
||||
// updated.
|
||||
namespace jni_generator {
|
||||
using jni_zero::internal::kJniStackMarkerValue;
|
||||
|
||||
// TODO(b/319078685): Remove JniJavaCallContextUnchecked once all uses of the
|
||||
// jni_generator has been updated.
|
||||
struct BASE_EXPORT JniJavaCallContextUnchecked {
|
||||
struct JniJavaCallContextUnchecked {
|
||||
inline JniJavaCallContextUnchecked() {
|
||||
// TODO(ssid): Implement for other architectures.
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
|
@ -207,7 +92,7 @@ struct BASE_EXPORT JniJavaCallContextUnchecked {
|
|||
// TODO(b/319078685): Remove JniJavaCallContextChecked once all uses of the
|
||||
// jni_generator has been updated.
|
||||
// Context about the JNI call with exception unchecked to be stored in stack.
|
||||
struct BASE_EXPORT JniJavaCallContextChecked {
|
||||
struct JniJavaCallContextChecked {
|
||||
// Force no inline to reduce code size.
|
||||
template <jni_zero::MethodID::Type type>
|
||||
void Init(JNIEnv* env,
|
||||
|
@ -229,24 +114,6 @@ static_assert(sizeof(JniJavaCallContextChecked) ==
|
|||
sizeof(JniJavaCallContextUnchecked),
|
||||
"Stack unwinder cannot work with structs of different sizes.");
|
||||
|
||||
} // namespace jni_zero
|
||||
|
||||
namespace jni_zero {
|
||||
namespace internal {
|
||||
using jni_zero::JniJavaCallContext;
|
||||
using jni_zero::JniJavaCallContextChecked;
|
||||
using jni_zero::JniJavaCallContextUnchecked;
|
||||
using webrtc::LazyGetClass;
|
||||
} // namespace internal
|
||||
} // namespace jni_zero
|
||||
|
||||
// Re-export helpers in the old jni_generator namespace.
|
||||
// TODO(b/319078685): Remove once all uses of the jni_generator has been
|
||||
// updated.
|
||||
namespace jni_generator {
|
||||
using jni_zero::JniJavaCallContext;
|
||||
using jni_zero::JniJavaCallContextChecked;
|
||||
using jni_zero::JniJavaCallContextUnchecked;
|
||||
} // namespace jni_generator
|
||||
|
||||
// Re-export helpers in the namespaces that the old jni_generator script
|
||||
|
@ -255,11 +122,11 @@ using jni_zero::JniJavaCallContextUnchecked;
|
|||
// updated.
|
||||
namespace base {
|
||||
namespace android {
|
||||
using webrtc::JavaParamRef;
|
||||
using webrtc::JavaRef;
|
||||
using webrtc::LazyGetClass;
|
||||
using webrtc::MethodID;
|
||||
using webrtc::ScopedJavaLocalRef;
|
||||
using jni_zero::JavaParamRef;
|
||||
using jni_zero::JavaRef;
|
||||
using jni_zero::MethodID;
|
||||
using jni_zero::ScopedJavaLocalRef;
|
||||
using jni_zero::internal::LazyGetClass;
|
||||
} // namespace android
|
||||
} // namespace base
|
||||
#endif // SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "third_party/jni_zero/jni_zero.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
@ -70,11 +71,18 @@ static void CreateJNIPtrKey() {
|
|||
<< "pthread_key_create";
|
||||
}
|
||||
|
||||
void HandleException(JNIEnv* env) {
|
||||
RTC_CHECK(false) << (env->ExceptionDescribe(), env->ExceptionClear(), "");
|
||||
}
|
||||
|
||||
jint InitGlobalJniVariables(JavaVM* jvm) {
|
||||
RTC_CHECK(!g_jvm) << "InitGlobalJniVariables!";
|
||||
g_jvm = jvm;
|
||||
RTC_CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?";
|
||||
|
||||
jni_zero::SetExceptionHandler(&HandleException);
|
||||
jni_zero::InitVM(jvm);
|
||||
|
||||
RTC_CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
|
||||
|
||||
JNIEnv* jni = nullptr;
|
||||
|
|
|
@ -50,8 +50,9 @@ JNI_FUNCTION_DECLARATION(void,
|
|||
jint j_severity,
|
||||
jstring j_tag,
|
||||
jstring j_message) {
|
||||
std::string message = JavaToStdString(jni, JavaParamRef<jstring>(j_message));
|
||||
std::string tag = JavaToStdString(jni, JavaParamRef<jstring>(j_tag));
|
||||
std::string message =
|
||||
JavaToStdString(jni, JavaParamRef<jstring>(jni, j_message));
|
||||
std::string tag = JavaToStdString(jni, JavaParamRef<jstring>(jni, j_tag));
|
||||
RTC_LOG_TAG(static_cast<rtc::LoggingSeverity>(j_severity), tag.c_str())
|
||||
<< message;
|
||||
}
|
||||
|
|
|
@ -10,8 +10,13 @@
|
|||
|
||||
#include "sdk/android/src/jni/scoped_java_ref_counted.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_base_jni/RefCounted_jni.h"
|
||||
|
||||
#define CHECK_EXCEPTION(jni) \
|
||||
RTC_CHECK(!jni->ExceptionCheck()) \
|
||||
<< (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
|
|
Loading…
Reference in a new issue