1 /*
2 * Copyright 2017 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 // Do not include this file directly. It's intended to be used only by the JNI
11 // generation script. We are exporting types in strange namespaces in order to
12 // be compatible with the generated code targeted for Chromium.
13
14 #ifndef SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
15 #define SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
16
17 #include <jni.h>
18 #include <atomic>
19
20 #include "rtc_base/checks.h"
21 #include "sdk/android/native_api/jni/jni_int_wrapper.h"
22 #include "sdk/android/native_api/jni/scoped_java_ref.h"
23
24 #define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
25 #define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \
26 RTC_DCHECK(native_ptr) << method_name;
27
28 #define BASE_EXPORT
29 #define JNI_REGISTRATION_EXPORT __attribute__((visibility("default")))
30
31 #if defined(WEBRTC_ARCH_X86)
32 // Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
33 // x86 - use force_align_arg_pointer to realign the stack at the JNI
34 // boundary. crbug.com/655248
35 #define JNI_GENERATOR_EXPORT \
36 __attribute__((force_align_arg_pointer)) extern "C" JNIEXPORT JNICALL
37 #else
38 #define JNI_GENERATOR_EXPORT extern "C" JNIEXPORT JNICALL
39 #endif
40
41 #define CHECK_EXCEPTION(jni) \
42 RTC_CHECK(!jni->ExceptionCheck()) \
43 << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
44
45 namespace webrtc {
46
47 // This function will initialize `atomic_class_id` to contain a global ref to
48 // the given class, and will return that ref on subsequent calls. The caller is
49 // responsible to zero-initialize `atomic_class_id`. It's fine to
50 // simultaneously call this on multiple threads referencing the same
51 // `atomic_method_id`.
52 jclass LazyGetClass(JNIEnv* env,
53 const char* class_name,
54 std::atomic<jclass>* atomic_class_id);
55
56 // This class is a wrapper for JNIEnv Get(Static)MethodID.
57 class MethodID {
58 public:
59 enum Type {
60 TYPE_STATIC,
61 TYPE_INSTANCE,
62 };
63
64 // This function will initialize `atomic_method_id` to contain a ref to
65 // the given method, and will return that ref on subsequent calls. The caller
66 // is responsible to zero-initialize `atomic_method_id`. It's fine to
67 // simultaneously call this on multiple threads referencing the same
68 // `atomic_method_id`.
69 template <Type type>
70 static jmethodID LazyGet(JNIEnv* env,
71 jclass clazz,
72 const char* method_name,
73 const char* jni_signature,
74 std::atomic<jmethodID>* atomic_method_id);
75 };
76
77 } // namespace webrtc
78
79 // Re-export relevant classes into the namespaces the script expects.
80 namespace base {
81 namespace android {
82
83 using webrtc::JavaParamRef;
84 using webrtc::JavaRef;
85 using webrtc::ScopedJavaLocalRef;
86 using webrtc::LazyGetClass;
87 using webrtc::MethodID;
88
89 } // namespace android
90 } // namespace base
91
92 namespace jni_generator {
CheckException(JNIEnv * env)93 inline void CheckException(JNIEnv* env) {
94 CHECK_EXCEPTION(env);
95 }
96
97 // A 32 bit number could be an address on stack. Random 64 bit marker on the
98 // stack is much less likely to be present on stack.
99 constexpr uint64_t kJniStackMarkerValue = 0xbdbdef1bebcade1b;
100
101 // Context about the JNI call with exception checked to be stored in stack.
102 struct BASE_EXPORT JniJavaCallContextUnchecked {
JniJavaCallContextUncheckedJniJavaCallContextUnchecked103 inline JniJavaCallContextUnchecked() {
104 // TODO(ssid): Implement for other architectures.
105 #if defined(__arm__) || defined(__aarch64__)
106 // This assumes that this method does not increment the stack pointer.
107 asm volatile("mov %0, sp" : "=r"(sp));
108 #else
109 sp = 0;
110 #endif
111 }
112
113 // Force no inline to reduce code size.
114 template <base::android::MethodID::Type type>
InitJniJavaCallContextUnchecked115 void Init(JNIEnv* env,
116 jclass clazz,
117 const char* method_name,
118 const char* jni_signature,
119 std::atomic<jmethodID>* atomic_method_id) {
120 env1 = env;
121
122 // Make sure compiler doesn't optimize out the assignment.
123 memcpy(&marker, &kJniStackMarkerValue, sizeof(kJniStackMarkerValue));
124 // Gets PC of the calling function.
125 pc = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
126
127 method_id = base::android::MethodID::LazyGet<type>(
128 env, clazz, method_name, jni_signature, atomic_method_id);
129 }
130
~JniJavaCallContextUncheckedJniJavaCallContextUnchecked131 ~JniJavaCallContextUnchecked() {
132 // Reset so that spurious marker finds are avoided.
133 memset(&marker, 0, sizeof(marker));
134 }
135
136 uint64_t marker;
137 uintptr_t sp;
138 uintptr_t pc;
139
140 JNIEnv* env1;
141 jmethodID method_id;
142 };
143
144 // Context about the JNI call with exception unchecked to be stored in stack.
145 struct BASE_EXPORT JniJavaCallContextChecked {
146 // Force no inline to reduce code size.
147 template <base::android::MethodID::Type type>
InitJniJavaCallContextChecked148 void Init(JNIEnv* env,
149 jclass clazz,
150 const char* method_name,
151 const char* jni_signature,
152 std::atomic<jmethodID>* atomic_method_id) {
153 base.Init<type>(env, clazz, method_name, jni_signature, atomic_method_id);
154 // Reset `pc` to correct caller.
155 base.pc = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
156 }
157
~JniJavaCallContextCheckedJniJavaCallContextChecked158 ~JniJavaCallContextChecked() { jni_generator::CheckException(base.env1); }
159
160 JniJavaCallContextUnchecked base;
161 };
162
163 static_assert(sizeof(JniJavaCallContextChecked) ==
164 sizeof(JniJavaCallContextUnchecked),
165 "Stack unwinder cannot work with structs of different sizes.");
166 } // namespace jni_generator
167
168 #endif // SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
169