blob: 00ca772e760a343fd5ab48e273112ea10e0e60dd [file] [log] [blame]
qiangchen42f96d52017-08-09 00:08:031/*
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 */
Steve Anton10542f22019-01-11 17:11:0010#include "examples/unityplugin/class_reference_holder.h"
qiangchen42f96d52017-08-09 00:08:0311
12#include <utility>
13
Mirko Bonadei92ea95e2017-09-15 04:47:3114#include "sdk/android/src/jni/jni_helpers.h"
qiangchen42f96d52017-08-09 00:08:0315
16namespace unity_plugin {
17
18// ClassReferenceHolder holds global reference to Java classes in app/webrtc.
19class 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().
35static ClassReferenceHolder* g_class_reference_holder = nullptr;
36
37void LoadGlobalClassReferenceHolder() {
38 RTC_CHECK(g_class_reference_holder == nullptr);
magjeda3d4f682017-08-28 23:24:0639 g_class_reference_holder = new ClassReferenceHolder(webrtc::jni::GetEnv());
qiangchen42f96d52017-08-09 00:08:0340}
41
42void FreeGlobalClassReferenceHolder() {
43 g_class_reference_holder->FreeReferences(
magjeda3d4f682017-08-28 23:24:0644 webrtc::jni::AttachCurrentThreadIfNeeded());
qiangchen42f96d52017-08-09 00:08:0345 delete g_class_reference_holder;
46 g_class_reference_holder = nullptr;
47}
48
49ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
50 LoadClass(jni, "org/webrtc/UnityUtility");
51}
52
53ClassReferenceHolder::~ClassReferenceHolder() {
54 RTC_CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
55}
56
57void 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
65jclass 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
71void 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.
84jclass FindClass(JNIEnv* jni, const char* name) {
85 return g_class_reference_holder->GetClass(name);
86}
87
88} // namespace unity_plugin