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