| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #define LOG_TAG "ANDROID_RUNTIME_LAZY" |
| #include "android_runtime/AndroidRuntime.h" |
| #include "android_os_Parcel.h" |
| #include "android_util_Binder.h" |
| |
| #include <dlfcn.h> |
| #include <mutex> |
| |
| #include <log/log.h> |
| |
| namespace android { |
| namespace { |
| |
| std::once_flag loadFlag; |
| |
| typedef JNIEnv* (*getJNIEnv_t)(); |
| |
| // android_util_Binder.h |
| typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj); |
| typedef jobject (*javaObjectForIBinder_t)(JNIEnv* env, const sp<IBinder>& val); |
| |
| // android_os_Parcel.h |
| typedef Parcel* (*parcelForJavaObject_t)(JNIEnv* env, jobject obj); |
| |
| getJNIEnv_t _getJNIEnv; |
| ibinderForJavaObject_t _ibinderForJavaObject; |
| javaObjectForIBinder_t _javaObjectForIBinder; |
| parcelForJavaObject_t _parcelForJavaObject; |
| |
| void load() { |
| std::call_once(loadFlag, []() { |
| void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY); |
| if (handle == nullptr) { |
| ALOGE("Could not open libandroid_runtime."); |
| return; |
| } |
| |
| _getJNIEnv = reinterpret_cast<getJNIEnv_t>( |
| dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv")); |
| if (_getJNIEnv == nullptr) { |
| ALOGW("Could not find getJNIEnv."); |
| // no return |
| } |
| |
| _ibinderForJavaObject = reinterpret_cast<ibinderForJavaObject_t>( |
| dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject")); |
| if (_ibinderForJavaObject == nullptr) { |
| ALOGW("Could not find ibinderForJavaObject."); |
| // no return |
| } |
| |
| _javaObjectForIBinder = reinterpret_cast<javaObjectForIBinder_t>( |
| dlsym(handle, |
| "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE")); |
| if (_javaObjectForIBinder == nullptr) { |
| ALOGW("Could not find javaObjectForIBinder."); |
| // no return |
| } |
| |
| _parcelForJavaObject = reinterpret_cast<parcelForJavaObject_t>( |
| dlsym(handle, "_ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject")); |
| if (_parcelForJavaObject == nullptr) { |
| ALOGW("Could not find parcelForJavaObject."); |
| // no return |
| } |
| }); |
| } |
| |
| } // namespace |
| |
| // exports delegate functions |
| |
| JNIEnv* AndroidRuntime::getJNIEnv() { |
| load(); |
| if (_getJNIEnv == nullptr) { |
| return nullptr; |
| } |
| return _getJNIEnv(); |
| } |
| |
| sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) { |
| load(); |
| if (_ibinderForJavaObject == nullptr) { |
| return nullptr; |
| } |
| return _ibinderForJavaObject(env, obj); |
| } |
| |
| jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { |
| load(); |
| if (_javaObjectForIBinder == nullptr) { |
| return nullptr; |
| } |
| return _javaObjectForIBinder(env, val); |
| } |
| |
| Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) { |
| load(); |
| if (_parcelForJavaObject == nullptr) { |
| return nullptr; |
| } |
| return _parcelForJavaObject(env, obj); |
| } |
| |
| } // namespace android |