1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. The Android Open Source
7 * Project designates this particular file as subject to the "Classpath"
8 * exception as provided by The Android Open Source Project in the LICENSE
9 * file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #define LOG_TAG "JniConstants"
23
24 #include "JniConstants.h"
25
26 #include <atomic>
27 #include <mutex>
28
29 #include <log/log.h>
30 #include <nativehelper/ScopedLocalRef.h>
31
32 namespace {
33
findClass(JNIEnv * env,const char * name)34 jclass findClass(JNIEnv* env, const char* name) {
35 ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
36 jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
37 if (result == NULL) {
38 ALOGE("failed to find class '%s'", name);
39 abort();
40 }
41 return result;
42 }
43
44 // Mutex protecting static variables
45 static std::mutex g_constants_mutex;
46
47 // Flag indicating whether cached constants are valid
48 static bool g_constants_valid = false;
49
50 // Constants
51 jclass g_socket_tagger_class;
52
53 // EnsureJniConstantsInitialized initializes cache constants. It should be
54 // called before returning a heap object from the cache to ensure cache is
55 // initialized. This pattern is only necessary because if a process finishes one
56 // runtime and starts another then JNI_OnLoad may not be called.
EnsureJniConstantsInitialized(JNIEnv * env)57 void EnsureJniConstantsInitialized(JNIEnv* env) {
58 if (g_constants_valid) {
59 return;
60 }
61
62 std::lock_guard guard(g_constants_mutex);
63 if (g_constants_valid) {
64 return;
65 }
66
67 g_socket_tagger_class = findClass(env, "dalvik/system/SocketTagger");
68 g_constants_valid = true;
69 }
70
71 } // namespace
72
Initialize(JNIEnv * env)73 void JniConstants::Initialize(JNIEnv* env) {
74 EnsureJniConstantsInitialized(env);
75 }
76
Invalidate()77 void JniConstants::Invalidate() {
78 std::lock_guard guard(g_constants_mutex);
79 g_constants_valid = false;
80 }
81
GetSocketTaggerClass(JNIEnv * env)82 jclass JniConstants::GetSocketTaggerClass(JNIEnv* env) {
83 EnsureJniConstantsInitialized(env);
84 return g_socket_tagger_class;
85 }
86