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_os_Parcel.h"
19 #include "android_util_Binder.h"
20
21 #include <dlfcn.h>
22 #include <mutex>
23
24 #include <log/log.h>
25
26 namespace android {
27 namespace {
28
29 std::once_flag loadFlag;
30
31 typedef JNIEnv* (*getJNIEnv_t)();
32
33 // android_util_Binder.h
34 typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
35 typedef jobject (*javaObjectForIBinder_t)(JNIEnv* env, const sp<IBinder>& val);
36
37 // android_os_Parcel.h
38 typedef Parcel* (*parcelForJavaObject_t)(JNIEnv* env, jobject obj);
39
40 getJNIEnv_t _getJNIEnv;
41 ibinderForJavaObject_t _ibinderForJavaObject;
42 javaObjectForIBinder_t _javaObjectForIBinder;
43 parcelForJavaObject_t _parcelForJavaObject;
44
load()45 void load() {
46 std::call_once(loadFlag, []() {
47 void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
48 if (handle == nullptr) {
49 ALOGE("Could not open libandroid_runtime.");
50 return;
51 }
52
53 _getJNIEnv = reinterpret_cast<getJNIEnv_t>(
54 dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv"));
55 if (_getJNIEnv == nullptr) {
56 ALOGW("Could not find getJNIEnv.");
57 // no return
58 }
59
60 _ibinderForJavaObject = reinterpret_cast<ibinderForJavaObject_t>(
61 dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
62 if (_ibinderForJavaObject == nullptr) {
63 ALOGW("Could not find ibinderForJavaObject.");
64 // no return
65 }
66
67 _javaObjectForIBinder = reinterpret_cast<javaObjectForIBinder_t>(
68 dlsym(handle,
69 "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE"));
70 if (_javaObjectForIBinder == nullptr) {
71 ALOGW("Could not find javaObjectForIBinder.");
72 // no return
73 }
74
75 _parcelForJavaObject = reinterpret_cast<parcelForJavaObject_t>(
76 dlsym(handle, "_ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject"));
77 if (_parcelForJavaObject == nullptr) {
78 ALOGW("Could not find parcelForJavaObject.");
79 // no return
80 }
81 });
82 }
83
84 } // namespace
85
86 // exports delegate functions
87
getJNIEnv()88 JNIEnv* AndroidRuntime::getJNIEnv() {
89 load();
90 if (_getJNIEnv == nullptr) {
91 return nullptr;
92 }
93 return _getJNIEnv();
94 }
95
ibinderForJavaObject(JNIEnv * env,jobject obj)96 sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
97 load();
98 if (_ibinderForJavaObject == nullptr) {
99 return nullptr;
100 }
101 return _ibinderForJavaObject(env, obj);
102 }
103
javaObjectForIBinder(JNIEnv * env,const sp<IBinder> & val)104 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
105 load();
106 if (_javaObjectForIBinder == nullptr) {
107 return nullptr;
108 }
109 return _javaObjectForIBinder(env, val);
110 }
111
parcelForJavaObject(JNIEnv * env,jobject obj)112 Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) {
113 load();
114 if (_parcelForJavaObject == nullptr) {
115 return nullptr;
116 }
117 return _parcelForJavaObject(env, obj);
118 }
119
120 } // namespace android
121