1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "ANDROID_RUNTIME_LAZY"
17 #include "android_runtime/AndroidRuntime.h"
18 #include "android_util_Binder.h"
19
20 #include <dlfcn.h>
21 #include <mutex>
22
23 #include <log/log.h>
24
25 namespace android {
26 namespace {
27
28 std::once_flag loadFlag;
29
30 typedef JNIEnv* (*getJNIEnv_t)();
31 typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
32 typedef jobject (*javaObjectForIBinder_t)(JNIEnv* env, const sp<IBinder>& val);
33
34 getJNIEnv_t _getJNIEnv;
35 ibinderForJavaObject_t _ibinderForJavaObject;
36 javaObjectForIBinder_t _javaObjectForIBinder;
37
load()38 void load() {
39 std::call_once(loadFlag, []() {
40 void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
41 if (handle == nullptr) {
42 ALOGE("Could not open libandroid_runtime.");
43 return;
44 }
45
46 _getJNIEnv = reinterpret_cast<getJNIEnv_t>(
47 dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv"));
48 if (_getJNIEnv == nullptr) {
49 ALOGW("Could not find getJNIEnv.");
50 // no return
51 }
52
53 _ibinderForJavaObject = reinterpret_cast<ibinderForJavaObject_t>(
54 dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
55 if (_ibinderForJavaObject == nullptr) {
56 ALOGW("Could not find ibinderForJavaObject.");
57 // no return
58 }
59
60 _javaObjectForIBinder = reinterpret_cast<javaObjectForIBinder_t>(
61 dlsym(handle,
62 "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE"));
63 if (_javaObjectForIBinder == nullptr) {
64 ALOGW("Could not find javaObjectForIBinder.");
65 // no return
66 }
67 });
68 }
69
70 } // namespace
71
72 // exports delegate functions
73
getJNIEnv()74 JNIEnv* AndroidRuntime::getJNIEnv() {
75 load();
76 if (_getJNIEnv == nullptr) {
77 return nullptr;
78 }
79 return _getJNIEnv();
80 }
81
ibinderForJavaObject(JNIEnv * env,jobject obj)82 sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
83 load();
84 if (_ibinderForJavaObject == nullptr) {
85 return nullptr;
86 }
87 return _ibinderForJavaObject(env, obj);
88 }
89
javaObjectForIBinder(JNIEnv * env,const sp<IBinder> & val)90 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
91 load();
92 if (_javaObjectForIBinder == nullptr) {
93 return nullptr;
94 }
95 return _javaObjectForIBinder(env, val);
96 }
97
98 } // namespace android
99