xref: /aosp_15_r20/external/webrtc/modules/utility/include/jvm_android.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
12*d9f75844SAndroid Build Coastguard Worker #define MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <jni.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/utility/include/helpers_android.h"
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker // RAII JavaVM AttachCurrentThread/DetachCurrentThread object.
25*d9f75844SAndroid Build Coastguard Worker //
26*d9f75844SAndroid Build Coastguard Worker // The JNI interface pointer (JNIEnv) is valid only in the current thread.
27*d9f75844SAndroid Build Coastguard Worker // Should another thread need to access the Java VM, it must first call
28*d9f75844SAndroid Build Coastguard Worker // AttachCurrentThread() to attach itself to the VM and obtain a JNI interface
29*d9f75844SAndroid Build Coastguard Worker // pointer. The native thread remains attached to the VM until it calls
30*d9f75844SAndroid Build Coastguard Worker // DetachCurrentThread() to detach.
31*d9f75844SAndroid Build Coastguard Worker class JvmThreadConnector {
32*d9f75844SAndroid Build Coastguard Worker  public:
33*d9f75844SAndroid Build Coastguard Worker   JvmThreadConnector();
34*d9f75844SAndroid Build Coastguard Worker   ~JvmThreadConnector();
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker  private:
37*d9f75844SAndroid Build Coastguard Worker   SequenceChecker thread_checker_;
38*d9f75844SAndroid Build Coastguard Worker   bool attached_;
39*d9f75844SAndroid Build Coastguard Worker };
40*d9f75844SAndroid Build Coastguard Worker 
41*d9f75844SAndroid Build Coastguard Worker // This class is created by the NativeRegistration class and is used to wrap
42*d9f75844SAndroid Build Coastguard Worker // the actual Java object handle (jobject) on which we can call methods from
43*d9f75844SAndroid Build Coastguard Worker // C++ in to Java. See example in JVM for more details.
44*d9f75844SAndroid Build Coastguard Worker // TODO(henrika): extend support for type of function calls.
45*d9f75844SAndroid Build Coastguard Worker class GlobalRef {
46*d9f75844SAndroid Build Coastguard Worker  public:
47*d9f75844SAndroid Build Coastguard Worker   GlobalRef(JNIEnv* jni, jobject object);
48*d9f75844SAndroid Build Coastguard Worker   ~GlobalRef();
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker   jboolean CallBooleanMethod(jmethodID methodID, ...);
51*d9f75844SAndroid Build Coastguard Worker   jint CallIntMethod(jmethodID methodID, ...);
52*d9f75844SAndroid Build Coastguard Worker   void CallVoidMethod(jmethodID methodID, ...);
53*d9f75844SAndroid Build Coastguard Worker 
54*d9f75844SAndroid Build Coastguard Worker  private:
55*d9f75844SAndroid Build Coastguard Worker   JNIEnv* const jni_;
56*d9f75844SAndroid Build Coastguard Worker   const jobject j_object_;
57*d9f75844SAndroid Build Coastguard Worker };
58*d9f75844SAndroid Build Coastguard Worker 
59*d9f75844SAndroid Build Coastguard Worker // Wraps the jclass object on which we can call GetMethodId() functions to
60*d9f75844SAndroid Build Coastguard Worker // query method IDs.
61*d9f75844SAndroid Build Coastguard Worker class JavaClass {
62*d9f75844SAndroid Build Coastguard Worker  public:
JavaClass(JNIEnv * jni,jclass clazz)63*d9f75844SAndroid Build Coastguard Worker   JavaClass(JNIEnv* jni, jclass clazz) : jni_(jni), j_class_(clazz) {}
~JavaClass()64*d9f75844SAndroid Build Coastguard Worker   ~JavaClass() {}
65*d9f75844SAndroid Build Coastguard Worker 
66*d9f75844SAndroid Build Coastguard Worker   jmethodID GetMethodId(const char* name, const char* signature);
67*d9f75844SAndroid Build Coastguard Worker   jmethodID GetStaticMethodId(const char* name, const char* signature);
68*d9f75844SAndroid Build Coastguard Worker   jobject CallStaticObjectMethod(jmethodID methodID, ...);
69*d9f75844SAndroid Build Coastguard Worker   jint CallStaticIntMethod(jmethodID methodID, ...);
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker  protected:
72*d9f75844SAndroid Build Coastguard Worker   JNIEnv* const jni_;
73*d9f75844SAndroid Build Coastguard Worker   jclass const j_class_;
74*d9f75844SAndroid Build Coastguard Worker };
75*d9f75844SAndroid Build Coastguard Worker 
76*d9f75844SAndroid Build Coastguard Worker // Adds support of the NewObject factory method to the JavaClass class.
77*d9f75844SAndroid Build Coastguard Worker // See example in JVM for more details on how to use it.
78*d9f75844SAndroid Build Coastguard Worker class NativeRegistration : public JavaClass {
79*d9f75844SAndroid Build Coastguard Worker  public:
80*d9f75844SAndroid Build Coastguard Worker   NativeRegistration(JNIEnv* jni, jclass clazz);
81*d9f75844SAndroid Build Coastguard Worker   ~NativeRegistration();
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<GlobalRef> NewObject(const char* name,
84*d9f75844SAndroid Build Coastguard Worker                                        const char* signature,
85*d9f75844SAndroid Build Coastguard Worker                                        ...);
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker  private:
88*d9f75844SAndroid Build Coastguard Worker   JNIEnv* const jni_;
89*d9f75844SAndroid Build Coastguard Worker };
90*d9f75844SAndroid Build Coastguard Worker 
91*d9f75844SAndroid Build Coastguard Worker // This class is created by the JVM class and is used to expose methods that
92*d9f75844SAndroid Build Coastguard Worker // needs the JNI interface pointer but its main purpose is to create a
93*d9f75844SAndroid Build Coastguard Worker // NativeRegistration object given name of a Java class and a list of native
94*d9f75844SAndroid Build Coastguard Worker // methods. See example in JVM for more details.
95*d9f75844SAndroid Build Coastguard Worker class JNIEnvironment {
96*d9f75844SAndroid Build Coastguard Worker  public:
97*d9f75844SAndroid Build Coastguard Worker   explicit JNIEnvironment(JNIEnv* jni);
98*d9f75844SAndroid Build Coastguard Worker   ~JNIEnvironment();
99*d9f75844SAndroid Build Coastguard Worker 
100*d9f75844SAndroid Build Coastguard Worker   // Registers native methods with the Java class specified by `name`.
101*d9f75844SAndroid Build Coastguard Worker   // Note that the class name must be one of the names in the static
102*d9f75844SAndroid Build Coastguard Worker   // `loaded_classes` array defined in jvm_android.cc.
103*d9f75844SAndroid Build Coastguard Worker   // This method must be called on the construction thread.
104*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<NativeRegistration> RegisterNatives(
105*d9f75844SAndroid Build Coastguard Worker       const char* name,
106*d9f75844SAndroid Build Coastguard Worker       const JNINativeMethod* methods,
107*d9f75844SAndroid Build Coastguard Worker       int num_methods);
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   // Converts from Java string to std::string.
110*d9f75844SAndroid Build Coastguard Worker   // This method must be called on the construction thread.
111*d9f75844SAndroid Build Coastguard Worker   std::string JavaToStdString(const jstring& j_string);
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker  private:
114*d9f75844SAndroid Build Coastguard Worker   SequenceChecker thread_checker_;
115*d9f75844SAndroid Build Coastguard Worker   JNIEnv* const jni_;
116*d9f75844SAndroid Build Coastguard Worker };
117*d9f75844SAndroid Build Coastguard Worker 
118*d9f75844SAndroid Build Coastguard Worker // Main class for working with Java from C++ using JNI in WebRTC.
119*d9f75844SAndroid Build Coastguard Worker //
120*d9f75844SAndroid Build Coastguard Worker // Example usage:
121*d9f75844SAndroid Build Coastguard Worker //
122*d9f75844SAndroid Build Coastguard Worker //   // At initialization (e.g. in JNI_OnLoad), call JVM::Initialize.
123*d9f75844SAndroid Build Coastguard Worker //   JNIEnv* jni = ::base::android::AttachCurrentThread();
124*d9f75844SAndroid Build Coastguard Worker //   JavaVM* jvm = NULL;
125*d9f75844SAndroid Build Coastguard Worker //   jni->GetJavaVM(&jvm);
126*d9f75844SAndroid Build Coastguard Worker //   webrtc::JVM::Initialize(jvm);
127*d9f75844SAndroid Build Coastguard Worker //
128*d9f75844SAndroid Build Coastguard Worker //   // Header (.h) file of example class called User.
129*d9f75844SAndroid Build Coastguard Worker //   std::unique_ptr<JNIEnvironment> env;
130*d9f75844SAndroid Build Coastguard Worker //   std::unique_ptr<NativeRegistration> reg;
131*d9f75844SAndroid Build Coastguard Worker //   std::unique_ptr<GlobalRef> obj;
132*d9f75844SAndroid Build Coastguard Worker //
133*d9f75844SAndroid Build Coastguard Worker //   // Construction (in .cc file) of User class.
134*d9f75844SAndroid Build Coastguard Worker //   User::User() {
135*d9f75844SAndroid Build Coastguard Worker //     // Calling thread must be attached to the JVM.
136*d9f75844SAndroid Build Coastguard Worker //     env = JVM::GetInstance()->environment();
137*d9f75844SAndroid Build Coastguard Worker //     reg = env->RegisterNatives("org/webrtc/WebRtcTest", ,);
138*d9f75844SAndroid Build Coastguard Worker //     obj = reg->NewObject("<init>", ,);
139*d9f75844SAndroid Build Coastguard Worker //   }
140*d9f75844SAndroid Build Coastguard Worker //
141*d9f75844SAndroid Build Coastguard Worker //   // Each User method can now use `reg` and `obj` and call Java functions
142*d9f75844SAndroid Build Coastguard Worker //   // in WebRtcTest.java, e.g. boolean init() {}.
143*d9f75844SAndroid Build Coastguard Worker //   bool User::Foo() {
144*d9f75844SAndroid Build Coastguard Worker //     jmethodID id = reg->GetMethodId("init", "()Z");
145*d9f75844SAndroid Build Coastguard Worker //     return obj->CallBooleanMethod(id);
146*d9f75844SAndroid Build Coastguard Worker //   }
147*d9f75844SAndroid Build Coastguard Worker //
148*d9f75844SAndroid Build Coastguard Worker //   // And finally, e.g. in JNI_OnUnLoad, call JVM::Uninitialize.
149*d9f75844SAndroid Build Coastguard Worker //   JVM::Uninitialize();
150*d9f75844SAndroid Build Coastguard Worker class JVM {
151*d9f75844SAndroid Build Coastguard Worker  public:
152*d9f75844SAndroid Build Coastguard Worker   // Stores global handles to the Java VM interface.
153*d9f75844SAndroid Build Coastguard Worker   // Should be called once on a thread that is attached to the JVM.
154*d9f75844SAndroid Build Coastguard Worker   static void Initialize(JavaVM* jvm);
155*d9f75844SAndroid Build Coastguard Worker   // Like the method above but also passes the context to the ContextUtils
156*d9f75844SAndroid Build Coastguard Worker   // class. This method should be used by pure-C++ Android users that can't call
157*d9f75844SAndroid Build Coastguard Worker   // ContextUtils.initialize directly.
158*d9f75844SAndroid Build Coastguard Worker   static void Initialize(JavaVM* jvm, jobject context);
159*d9f75844SAndroid Build Coastguard Worker   // Clears handles stored in Initialize(). Must be called on same thread as
160*d9f75844SAndroid Build Coastguard Worker   // Initialize().
161*d9f75844SAndroid Build Coastguard Worker   static void Uninitialize();
162*d9f75844SAndroid Build Coastguard Worker   // Gives access to the global Java VM interface pointer, which then can be
163*d9f75844SAndroid Build Coastguard Worker   // used to create a valid JNIEnvironment object or to get a JavaClass object.
164*d9f75844SAndroid Build Coastguard Worker   static JVM* GetInstance();
165*d9f75844SAndroid Build Coastguard Worker 
166*d9f75844SAndroid Build Coastguard Worker   // Creates a JNIEnvironment object.
167*d9f75844SAndroid Build Coastguard Worker   // This method returns a NULL pointer if AttachCurrentThread() has not been
168*d9f75844SAndroid Build Coastguard Worker   // called successfully. Use the AttachCurrentThreadIfNeeded class if needed.
169*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<JNIEnvironment> environment();
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker   // Returns a JavaClass object given class `name`.
172*d9f75844SAndroid Build Coastguard Worker   // Note that the class name must be one of the names in the static
173*d9f75844SAndroid Build Coastguard Worker   // `loaded_classes` array defined in jvm_android.cc.
174*d9f75844SAndroid Build Coastguard Worker   // This method must be called on the construction thread.
175*d9f75844SAndroid Build Coastguard Worker   JavaClass GetClass(const char* name);
176*d9f75844SAndroid Build Coastguard Worker 
177*d9f75844SAndroid Build Coastguard Worker   // TODO(henrika): can we make these private?
jvm()178*d9f75844SAndroid Build Coastguard Worker   JavaVM* jvm() const { return jvm_; }
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker  protected:
181*d9f75844SAndroid Build Coastguard Worker   JVM(JavaVM* jvm);
182*d9f75844SAndroid Build Coastguard Worker   ~JVM();
183*d9f75844SAndroid Build Coastguard Worker 
184*d9f75844SAndroid Build Coastguard Worker  private:
jni()185*d9f75844SAndroid Build Coastguard Worker   JNIEnv* jni() const { return GetEnv(jvm_); }
186*d9f75844SAndroid Build Coastguard Worker 
187*d9f75844SAndroid Build Coastguard Worker   SequenceChecker thread_checker_;
188*d9f75844SAndroid Build Coastguard Worker   JavaVM* const jvm_;
189*d9f75844SAndroid Build Coastguard Worker };
190*d9f75844SAndroid Build Coastguard Worker 
191*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
192*d9f75844SAndroid Build Coastguard Worker 
193*d9f75844SAndroid Build Coastguard Worker #endif  // MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
194