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