1 /*
2  * libjingle
3  * Copyright 2015 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
29 
30 #include "talk/app/webrtc/java/jni/jni_helpers.h"
31 
32 namespace webrtc_jni {
33 
34 // ClassReferenceHolder holds global reference to Java classes in app/webrtc.
35 class ClassReferenceHolder {
36  public:
37   explicit ClassReferenceHolder(JNIEnv* jni);
38   ~ClassReferenceHolder();
39 
40   void FreeReferences(JNIEnv* jni);
41   jclass GetClass(const std::string& name);
42 
43  private:
44   void LoadClass(JNIEnv* jni, const std::string& name);
45 
46   std::map<std::string, jclass> classes_;
47 };
48 
49 // Allocated in LoadGlobalClassReferenceHolder(),
50 // freed in FreeGlobalClassReferenceHolder().
51 static ClassReferenceHolder* g_class_reference_holder = nullptr;
52 
LoadGlobalClassReferenceHolder()53 void LoadGlobalClassReferenceHolder() {
54   RTC_CHECK(g_class_reference_holder == nullptr);
55   g_class_reference_holder = new ClassReferenceHolder(GetEnv());
56 }
57 
FreeGlobalClassReferenceHolder()58 void FreeGlobalClassReferenceHolder() {
59   g_class_reference_holder->FreeReferences(AttachCurrentThreadIfNeeded());
60   delete g_class_reference_holder;
61   g_class_reference_holder = nullptr;
62 }
63 
ClassReferenceHolder(JNIEnv * jni)64 ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
65   LoadClass(jni, "java/nio/ByteBuffer");
66   LoadClass(jni, "java/util/ArrayList");
67   LoadClass(jni, "org/webrtc/AudioTrack");
68   LoadClass(jni, "org/webrtc/DataChannel");
69   LoadClass(jni, "org/webrtc/DataChannel$Buffer");
70   LoadClass(jni, "org/webrtc/DataChannel$Init");
71   LoadClass(jni, "org/webrtc/DataChannel$State");
72   LoadClass(jni, "org/webrtc/IceCandidate");
73 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
74   LoadClass(jni, "android/graphics/SurfaceTexture");
75   LoadClass(jni, "org/webrtc/CameraEnumerator");
76   LoadClass(jni, "org/webrtc/Camera2Enumerator");
77   LoadClass(jni, "org/webrtc/CameraEnumerationAndroid");
78   LoadClass(jni, "org/webrtc/VideoCapturerAndroid");
79   LoadClass(jni, "org/webrtc/VideoCapturerAndroid$NativeObserver");
80   LoadClass(jni, "org/webrtc/EglBase");
81   LoadClass(jni, "org/webrtc/EglBase$Context");
82   LoadClass(jni, "org/webrtc/EglBase14$Context");
83   LoadClass(jni, "org/webrtc/NetworkMonitor");
84   LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder");
85   LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
86   LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$VideoCodecType");
87   LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
88   LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecodedTextureBuffer");
89   LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer");
90   LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$VideoCodecType");
91   LoadClass(jni, "org/webrtc/SurfaceTextureHelper");
92 #endif
93   LoadClass(jni, "org/webrtc/MediaSource$State");
94   LoadClass(jni, "org/webrtc/MediaStream");
95   LoadClass(jni, "org/webrtc/MediaStreamTrack$State");
96   LoadClass(jni, "org/webrtc/PeerConnectionFactory");
97   LoadClass(jni, "org/webrtc/PeerConnection$BundlePolicy");
98   LoadClass(jni, "org/webrtc/PeerConnection$ContinualGatheringPolicy");
99   LoadClass(jni, "org/webrtc/PeerConnection$RtcpMuxPolicy");
100   LoadClass(jni, "org/webrtc/PeerConnection$IceConnectionState");
101   LoadClass(jni, "org/webrtc/PeerConnection$IceGatheringState");
102   LoadClass(jni, "org/webrtc/PeerConnection$IceTransportsType");
103   LoadClass(jni, "org/webrtc/PeerConnection$TcpCandidatePolicy");
104   LoadClass(jni, "org/webrtc/PeerConnection$KeyType");
105   LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
106   LoadClass(jni, "org/webrtc/RtpReceiver");
107   LoadClass(jni, "org/webrtc/RtpSender");
108   LoadClass(jni, "org/webrtc/SessionDescription");
109   LoadClass(jni, "org/webrtc/SessionDescription$Type");
110   LoadClass(jni, "org/webrtc/StatsReport");
111   LoadClass(jni, "org/webrtc/StatsReport$Value");
112   LoadClass(jni, "org/webrtc/VideoRenderer$I420Frame");
113   LoadClass(jni, "org/webrtc/VideoCapturer");
114   LoadClass(jni, "org/webrtc/VideoTrack");
115 }
116 
~ClassReferenceHolder()117 ClassReferenceHolder::~ClassReferenceHolder() {
118   RTC_CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
119 }
120 
FreeReferences(JNIEnv * jni)121 void ClassReferenceHolder::FreeReferences(JNIEnv* jni) {
122   for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
123       it != classes_.end(); ++it) {
124     jni->DeleteGlobalRef(it->second);
125   }
126   classes_.clear();
127 }
128 
GetClass(const std::string & name)129 jclass ClassReferenceHolder::GetClass(const std::string& name) {
130   std::map<std::string, jclass>::iterator it = classes_.find(name);
131   RTC_CHECK(it != classes_.end()) << "Unexpected GetClass() call for: " << name;
132   return it->second;
133 }
134 
LoadClass(JNIEnv * jni,const std::string & name)135 void ClassReferenceHolder::LoadClass(JNIEnv* jni, const std::string& name) {
136   jclass localRef = jni->FindClass(name.c_str());
137   CHECK_EXCEPTION(jni) << "error during FindClass: " << name;
138   RTC_CHECK(localRef) << name;
139   jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
140   CHECK_EXCEPTION(jni) << "error during NewGlobalRef: " << name;
141   RTC_CHECK(globalRef) << name;
142   bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
143   RTC_CHECK(inserted) << "Duplicate class name: " << name;
144 }
145 
146 // Returns a global reference guaranteed to be valid for the lifetime of the
147 // process.
FindClass(JNIEnv * jni,const char * name)148 jclass FindClass(JNIEnv* jni, const char* name) {
149   return g_class_reference_holder->GetClass(name);
150 }
151 
152 }  // namespace webrtc_jni
153