• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 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 #include "examples/unityplugin/class_reference_holder.h"
11 
12 #include <utility>
13 
14 #include "sdk/android/src/jni/jni_helpers.h"
15 
16 namespace unity_plugin {
17 
18 // ClassReferenceHolder holds global reference to Java classes in app/webrtc.
19 class ClassReferenceHolder {
20  public:
21   explicit ClassReferenceHolder(JNIEnv* jni);
22   ~ClassReferenceHolder();
23 
24   void FreeReferences(JNIEnv* jni);
25   jclass GetClass(const std::string& name);
26 
27   void LoadClass(JNIEnv* jni, const std::string& name);
28 
29  private:
30   std::map<std::string, jclass> classes_;
31 };
32 
33 // Allocated in LoadGlobalClassReferenceHolder(),
34 // freed in FreeGlobalClassReferenceHolder().
35 static ClassReferenceHolder* g_class_reference_holder = nullptr;
36 
LoadGlobalClassReferenceHolder()37 void LoadGlobalClassReferenceHolder() {
38   RTC_CHECK(g_class_reference_holder == nullptr);
39   g_class_reference_holder = new ClassReferenceHolder(webrtc::jni::GetEnv());
40 }
41 
FreeGlobalClassReferenceHolder()42 void FreeGlobalClassReferenceHolder() {
43   g_class_reference_holder->FreeReferences(
44       webrtc::jni::AttachCurrentThreadIfNeeded());
45   delete g_class_reference_holder;
46   g_class_reference_holder = nullptr;
47 }
48 
ClassReferenceHolder(JNIEnv * jni)49 ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
50   LoadClass(jni, "org/webrtc/UnityUtility");
51 }
52 
~ClassReferenceHolder()53 ClassReferenceHolder::~ClassReferenceHolder() {
54   RTC_CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
55 }
56 
FreeReferences(JNIEnv * jni)57 void ClassReferenceHolder::FreeReferences(JNIEnv* jni) {
58   for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
59        it != classes_.end(); ++it) {
60     jni->DeleteGlobalRef(it->second);
61   }
62   classes_.clear();
63 }
64 
GetClass(const std::string & name)65 jclass ClassReferenceHolder::GetClass(const std::string& name) {
66   std::map<std::string, jclass>::iterator it = classes_.find(name);
67   RTC_CHECK(it != classes_.end()) << "Unexpected GetClass() call for: " << name;
68   return it->second;
69 }
70 
LoadClass(JNIEnv * jni,const std::string & name)71 void ClassReferenceHolder::LoadClass(JNIEnv* jni, const std::string& name) {
72   jclass localRef = jni->FindClass(name.c_str());
73   CHECK_EXCEPTION(jni) << "error during FindClass: " << name;
74   RTC_CHECK(localRef) << name;
75   jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
76   CHECK_EXCEPTION(jni) << "error during NewGlobalRef: " << name;
77   RTC_CHECK(globalRef) << name;
78   bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
79   RTC_CHECK(inserted) << "Duplicate class name: " << name;
80 }
81 
82 // Returns a global reference guaranteed to be valid for the lifetime of the
83 // process.
FindClass(JNIEnv * jni,const char * name)84 jclass FindClass(JNIEnv* jni, const char* name) {
85   return g_class_reference_holder->GetClass(name);
86 }
87 
88 }  // namespace unity_plugin
89