[core] Update JNI helper (#440)

This commit is contained in:
LoveSy 2021-04-01 18:17:39 +08:00 committed by GitHub
parent eecef24179
commit a384697655
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 188 additions and 129 deletions

View File

@ -91,20 +91,14 @@ public class LogsActivity extends BaseActivity {
e.printStackTrace();
}
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
try {
OutputStream os = getContentResolver().openOutputStream(uri);
if (os == null) {
return;
}
try (var os = getContentResolver().openOutputStream(uri)) {
ParcelFileDescriptor parcelFileDescriptor = ConfigManager.getLogs(verbose);
if (parcelFileDescriptor == null) {
os.close();
return;
}
InputStream is = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
FileUtils.copy(is, os);
os.close();
is.close();
try (var is = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
FileUtils.copy(is, os);
}
} catch (Exception e) {
Snackbar.make(binding.snackbar, getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
}
@ -252,9 +246,7 @@ public class LogsActivity extends BaseActivity {
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
File cacheFile = new File(getCacheDir(), filename);
try {
OutputStream os = new FileOutputStream(cacheFile);
InputStream is = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
try (var os = new FileOutputStream(cacheFile); var is = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
FileUtils.copy(is, os);
} catch (IOException e) {
e.printStackTrace();

View File

@ -44,7 +44,7 @@ val androidTargetSdkVersion by extra(30)
val androidMinSdkVersion by extra(27)
val androidBuildToolsVersion by extra("30.0.3")
val androidCompileSdkVersion by extra(30)
val androidCompileNdkVersion by extra("22.0.7026061")
val androidCompileNdkVersion by extra("22.1.7171670")
val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
val apiCode by extra(93)

View File

@ -27,107 +27,6 @@
#define JNI_START JNIEnv *env, [[maybe_unused]] jclass clazz
ALWAYS_INLINE static void JNIExceptionClear(JNIEnv *env) {
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
}
ALWAYS_INLINE static bool JNIExceptionCheck(JNIEnv *env) {
if (env->ExceptionCheck()) {
jthrowable e = env->ExceptionOccurred();
env->Throw(e);
env->DeleteLocalRef(e);
return true;
}
return false;
}
ALWAYS_INLINE static void JNIExceptionClearAndDescribe(JNIEnv *env) {
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
}
ALWAYS_INLINE static int ClearException(JNIEnv *env) {
jthrowable exception = env->ExceptionOccurred();
if (exception != nullptr) {
env->ExceptionDescribe();
env->ExceptionClear();
return true;
}
return false;
}
#define JNI_FindClass(env, name) \
env->FindClass(name); \
if (ClearException(env)) LOGE("FindClass " #name)
#define JNI_GetObjectClass(env, obj) \
env->GetObjectClass(obj); \
if (ClearException(env)) LOGE("GetObjectClass " #obj)
#define JNI_GetFieldID(env, class, name, sig) \
env->GetFieldID(class, name, sig); \
if (ClearException(env)) LOGE("GetFieldID " #name)
#define JNI_GetObjectField(env, class, fieldId) \
env->GetObjectField(class, fieldId); \
if (ClearException(env)) LOGE("GetObjectField " #fieldId)
#define JNI_GetMethodID(env, class, name, sig) \
env->GetMethodID(class, name, sig); \
//if (ClearException(env)) LOGE("GetMethodID " #name)
#define JNI_CallObjectMethod(env, obj, ...) \
env->CallObjectMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallObjectMethod " #obj " " #__VA_ARGS__)
#define JNI_CallVoidMethod(env, obj, ...) \
env->CallVoidMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
#define JNI_CallBooleanMethod(env, obj, ...) \
env->CallBooleanMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
#define JNI_GetStaticFieldID(env, class, name, sig) \
env->GetStaticFieldID(class, name, sig); \
if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig)
#define JNI_GetStaticObjectField(env, class, fieldId) \
env->GetStaticObjectField(class, fieldId); \
if (ClearException(env)) LOGE("GetStaticObjectField " #fieldId)
#define JNI_GetStaticMethodID(env, class, name, sig) \
env->GetStaticMethodID(class, name, sig); \
if (ClearException(env)) LOGE("GetStaticMethodID " #name)
#define JNI_CallStaticVoidMethod(env, obj, ...) \
env->CallStaticVoidMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__)
#define JNI_CallStaticObjectMethod(env, obj, ...) \
env->CallStaticObjectMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallStaticObjectMethod " #obj " " #__VA_ARGS__)
#define JNI_CallStaticIntMethod(env, obj, ...) \
env->CallStaticIntMethod(obj, __VA_ARGS__); \
if (ClearException(env)) LOGE("CallStaticIntMethod " #obj " " #__VA_ARGS__)
#define JNI_GetArrayLength(env, array) \
env->GetArrayLength(array); \
if (ClearException(env)) LOGE("GetArrayLength " #array)
#define JNI_NewObject(env, class, ...) \
env->NewObject(class, __VA_ARGS__); \
if (ClearException(env)) LOGE("NewObject " #class " " #__VA_ARGS__)
#define JNI_RegisterNatives(env, class, methods, size) \
env->RegisterNatives(class, methods, size); \
if (ClearException(env)) LOGE("RegisterNatives " #class)
class JUTFString {
public:
inline JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) {
@ -181,15 +80,19 @@ private:
template<typename T>
class ScopedLocalRef {
public:
ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
ScopedLocalRef(JNIEnv *env, T localRef) : mEnv(env), mLocalRef(localRef) {
}
ScopedLocalRef(ScopedLocalRef&& s) noexcept : mEnv(s.mEnv), mLocalRef(s.release()) {
ScopedLocalRef(ScopedLocalRef &&s) noexcept: mEnv(s.mEnv), mLocalRef(s.release()) {
}
explicit ScopedLocalRef(JNIEnv* env) : mEnv(env), mLocalRef(nullptr) {
explicit ScopedLocalRef(JNIEnv *env) : mEnv(env), mLocalRef(nullptr) {
}
~ScopedLocalRef() {
reset();
}
void reset(T ptr = NULL) {
if (ptr != mLocalRef) {
if (mLocalRef != NULL) {
@ -198,34 +101,198 @@ public:
mLocalRef = ptr;
}
}
T release() __attribute__((warn_unused_result)) {
T localRef = mLocalRef;
mLocalRef = NULL;
return localRef;
}
T get() const {
return mLocalRef;
}
// We do not expose an empty constructor as it can easily lead to errors
// using common idioms, e.g.:
// ScopedLocalRef<...> ref;
// ref.reset(...);
// Move assignment operator.
ScopedLocalRef& operator=(ScopedLocalRef&& s) noexcept {
ScopedLocalRef &operator=(ScopedLocalRef &&s) noexcept {
reset(s.release());
mEnv = s.mEnv;
return *this;
}
// Allows "if (scoped_ref == nullptr)"
bool operator==(std::nullptr_t) const {
return mLocalRef == nullptr;
}
// Allows "if (scoped_ref != nullptr)"
bool operator!=(std::nullptr_t) const {
return mLocalRef != nullptr;
}
private:
JNIEnv* mEnv;
JNIEnv *mEnv;
T mLocalRef;
DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef);
};
[[maybe_unused]]
inline void JNIExceptionClear(JNIEnv *env) {
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
}
[[maybe_unused]]
inline bool JNIExceptionCheck(JNIEnv *env) {
if (env->ExceptionCheck()) {
jthrowable e = env->ExceptionOccurred();
env->Throw(e);
env->DeleteLocalRef(e);
return true;
}
return false;
}
[[maybe_unused]]
inline void JNIExceptionClearAndDescribe(JNIEnv *env) {
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
}
inline jstring ClearException(JNIEnv *env) {
static jmethodID toString = env->GetMethodID(env->FindClass("java/lang/Object"), "toString",
"()Ljava/lang/String;");
if (auto exception = env->ExceptionOccurred()) {
env->ExceptionClear();
return (jstring) env->CallObjectMethod(exception, toString);
}
return nullptr;
}
template<typename T>
[[maybe_unused]]
inline auto unwrap_sv(T &&x) {
if constexpr (std::is_same_v<std::decay_t<T>, std::string_view>) return x.data();
else return std::forward<T>(x);
}
template<typename Func, typename ...Args>
[[maybe_unused]]
inline auto JNI_SafeInvoke(JNIEnv *env, Func f, Args &&... args) {
static_assert(std::is_member_function_pointer_v<Func>);
struct finally {
finally(JNIEnv *env) : env_(env) {}
~finally() {
if (auto exception = ClearException(env_)) {
LOGE("%s", JUTFString(env_, exception).get());
}
}
JNIEnv *env_;
} _(env);
return (env->*f)(unwrap_sv(std::forward<Args>(args))...);
}
[[maybe_unused]]
inline auto JNI_FindClass(JNIEnv *env, std::string_view name) {
return JNI_SafeInvoke(env, &JNIEnv::FindClass, name);
}
[[maybe_unused]]
inline auto JNI_GetObjectClass(JNIEnv *env, jobject obj) {
return JNI_SafeInvoke(env, &JNIEnv::GetObjectClass, obj);
}
[[maybe_unused]]
inline auto JNI_GetFieldID(JNIEnv *env, jclass clazz, std::string_view name, std::string_view sig) {
return JNI_SafeInvoke(env, &JNIEnv::GetFieldID, clazz, name, sig);
}
[[maybe_unused]]
inline auto JNI_GetObjectField(JNIEnv *env, jclass clazz, jfieldID fieldId) {
return JNI_SafeInvoke(env, &JNIEnv::GetObjectField, clazz, fieldId);
}
[[maybe_unused]]
inline auto
JNI_GetMethodID(JNIEnv *env, jclass clazz, std::string_view name, std::string_view sig) {
return JNI_SafeInvoke(env, &JNIEnv::GetMethodID, clazz, name, sig);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallObjectMethod(JNIEnv *env, jobject obj, Args &&... args) {
return JNI_SafeInvoke(env, &JNIEnv::CallObjectMethod, obj, std::forward<Args>(args)...);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallVoidMethod(JNIEnv *env, jobject obj, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::CallVoidMethod, obj, std::forward<Args>(args)...);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallBooleanMethod(JNIEnv *env, jobject obj, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::CallBooleanMethod, obj, std::forward<Args>(args)...);
}
[[maybe_unused]]
inline auto
JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, std::string_view name, std::string_view sig) {
return JNI_SafeInvoke(env, &JNIEnv::GetStaticFieldID, clazz, name, sig);
}
[[maybe_unused]]
inline auto JNI_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldId) {
return JNI_SafeInvoke(env, &JNIEnv::GetStaticObjectField, clazz, fieldId);
}
[[maybe_unused]]
inline auto
JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, std::string_view name, std::string_view sig) {
return JNI_SafeInvoke(env, &JNIEnv::GetStaticMethodID, clazz, name, sig);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::CallStaticVoidMethod, clazz, std::forward<Args>(args)...);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::CallStaticObjectMethod, clazz, std::forward<Args>(args)...);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_CallStaticIntMethod(JNIEnv *env, jclass clazz, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::CallStaticIntMethod, clazz, std::forward<Args>(args)...);
}
[[maybe_unused]]
inline auto JNI_GetArrayLength(JNIEnv *env, jarray array) {
return JNI_SafeInvoke(env, &JNIEnv::GetArrayLength, array);
}
template<typename ...Args>
[[maybe_unused]]
inline auto JNI_NewObject(JNIEnv *env, jclass clazz, Args &&...args) {
return JNI_SafeInvoke(env, &JNIEnv::NewObject, clazz, std::forward<Args>(args)...);
}
[[maybe_unused]]
inline auto
JNI_RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint size) {
return JNI_SafeInvoke(env, &JNIEnv::RegisterNatives, clazz, methods, size);
}

View File

@ -35,14 +35,15 @@ namespace lspd {
const JNINativeMethod *methods,
jint method_count) {
ScopedLocalRef<jclass> clazz(env,
Context::GetInstance()->FindClassFromCurrentLoader(env, class_name));
ScopedLocalRef clazz(env,
Context::GetInstance()->FindClassFromCurrentLoader(env, class_name));
if (clazz.get() == nullptr) {
LOGF("Couldn't find class: %s", class_name);
return false;
}
return JNI_RegisterNatives(env, clazz.get(), methods, method_count);
}
#if defined(__cplusplus)
#define _NATIVEHELPER_JNI_MACRO_CAST(to) \
reinterpret_cast<to>
@ -60,7 +61,7 @@ namespace lspd {
#endif
#ifndef LSP_DEF_NATIVE_METHOD
#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \
#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \
extern "C" ret Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName (JNI_START, ## __VA_ARGS__)
#endif

View File

@ -130,7 +130,7 @@ namespace lspd {
return;
}
ScopedLocalRef<jclass> binderClass(env, env->FindClass("android/os/Binder"));
ScopedLocalRef binderClass(env, env->FindClass("android/os/Binder"));
exec_transact_backup_methodID_ = JNI_GetMethodID(env, binderClass.get(), "execTransact",
"(IJJI)Z");
auto set_table_override = reinterpret_cast<void (*)(
@ -183,10 +183,8 @@ namespace lspd {
jobject service = nullptr;
if (res) {
env->CallVoidMethod(reply, read_exception_method_);
if (!ClearException(env)) {
service = JNI_CallObjectMethod(env, reply, read_strong_binder_method_);
}
JNI_CallVoidMethod(env, reply, read_exception_method_);
service = JNI_CallObjectMethod(env, reply, read_strong_binder_method_);
}
JNI_CallVoidMethod(env, data, recycleMethod_);
JNI_CallVoidMethod(env, reply, recycleMethod_);

View File

@ -265,7 +265,8 @@ public class BridgeService {
try {
String processName = data.readString();
IBinder heartBeat = data.readStrongBinder();
binder = service.requestApplicationService(Binder.getCallingUid(), Binder.getCallingPid(), processName, heartBeat).asBinder();
var applicationService = service.requestApplicationService(Binder.getCallingUid(), Binder.getCallingPid(), processName, heartBeat);
if (applicationService != null) binder = service.asBinder();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}