• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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