121 lines
3.5 KiB
C++
121 lines
3.5 KiB
C++
/*
|
|
* 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
|