inform Java about apk path; allow specifying port for jdwp debugging with JDWP_LISTEN env; hackily work around onWindowFocusChanged being called at a time where it causes some apps to crash

This commit is contained in:
Mis012
2022-11-24 16:09:42 +01:00
parent 75187b01d5
commit 894f7b99c3
2 changed files with 35 additions and 7 deletions

View File

@@ -7,8 +7,8 @@
// these macros are a bit hacky, since they deliberately assume that env exists and refers to the JNI env // these macros are a bit hacky, since they deliberately assume that env exists and refers to the JNI env
#define _PTR(ptr)((void*)(intptr_t)ptr) #define _PTR(ptr)((void*)(intptr_t)(ptr))
#define _INTPTR(ptr)((jlong)(intptr_t)ptr) #define _INTPTR(ptr)((jlong)(intptr_t)(ptr))
#define _REF(obj)((*env)->NewGlobalRef(env, obj)) #define _REF(obj)((*env)->NewGlobalRef(env, obj))
#define _CLASS(object) ((*env)->GetObjectClass(env, object)) #define _CLASS(object) ((*env)->GetObjectClass(env, object))
#define _SUPER(object) ((*env)->GetSuperclass(env, object)) #define _SUPER(object) ((*env)->GetSuperclass(env, object))
@@ -24,6 +24,7 @@
#define _GET_LONG_FIELD(object, field) ((*env)->GetLongField(env, object, _FIELD_ID(_CLASS(object), field, "J"))) #define _GET_LONG_FIELD(object, field) ((*env)->GetLongField(env, object, _FIELD_ID(_CLASS(object), field, "J")))
#define _SET_INT_FIELD(object, field, value) ((*env)->SetIntField(env, object, _FIELD_ID(_CLASS(object), field, "I"), value)) #define _SET_INT_FIELD(object, field, value) ((*env)->SetIntField(env, object, _FIELD_ID(_CLASS(object), field, "I"), value))
#define _SET_STATIC_INT_FIELD(class, field, value) ((*env)->SetStaticIntField(env, class, _STATIC_FIELD_ID(class, field, "I"), value)) #define _SET_STATIC_INT_FIELD(class, field, value) ((*env)->SetStaticIntField(env, class, _STATIC_FIELD_ID(class, field, "I"), value))
#define _SET_STATIC_OBJ_FIELD(class, field, type, value) ((*env)->SetStaticObjectField(env, class, _STATIC_FIELD_ID(class, field, type), value))
#define _GET_INT_FIELD(object, field) ((*env)->GetIntField(env, object, _FIELD_ID(_CLASS(object), field, "I"))) #define _GET_INT_FIELD(object, field) ((*env)->GetIntField(env, object, _FIELD_ID(_CLASS(object), field, "I")))
#define _GET_BYTE_ARRAY_ELEMENTS(b_array) ((*env)->GetByteArrayElements(env, b_array, NULL)) #define _GET_BYTE_ARRAY_ELEMENTS(b_array) ((*env)->GetByteArrayElements(env, b_array, NULL))
#define _RELEASE_BYTE_ARRAY_ELEMENTS(b_array, buffer_ptr) ((*env)->ReleaseByteArrayElements(env, b_array, buffer_ptr, 0)) #define _RELEASE_BYTE_ARRAY_ELEMENTS(b_array, buffer_ptr) ((*env)->ReleaseByteArrayElements(env, b_array, buffer_ptr, 0))

View File

@@ -59,13 +59,20 @@ char *construct_classpath(char *prefix, char **cp_array, size_t len)
return result; return result;
} }
#define JDWP_ARG "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address="
JNIEnv* create_vm(char *api_impl_jar, char *apk_classpath, char *microg_apk, char *api_impl_natives_dir, char *app_lib_dir) { JNIEnv* create_vm(char *api_impl_jar, char *apk_classpath, char *microg_apk, char *api_impl_natives_dir, char *app_lib_dir) {
JavaVM* jvm; JavaVM* jvm;
JNIEnv* env; JNIEnv* env;
JavaVMInitArgs args; JavaVMInitArgs args;
JavaVMOption options[3]; JavaVMOption options[4];
args.version = JNI_VERSION_1_6; args.version = JNI_VERSION_1_6;
args.nOptions = 3; args.nOptions = 3;
char jdwp_option_string[sizeof(JDWP_ARG) + 5] = JDWP_ARG;// 5 chars for port number, NULL byte is counted by sizeof
const char* jdwp_port = getenv("JDWP_LISTEN");
if(jdwp_port)
args.nOptions += 1;
if(getenv("RUN_FROM_BUILDDIR")) { if(getenv("RUN_FROM_BUILDDIR")) {
options[0].optionString = construct_classpath("-Djava.library.path=", (char *[]){"./", app_lib_dir}, 2); options[0].optionString = construct_classpath("-Djava.library.path=", (char *[]){"./", app_lib_dir}, 2);
@@ -78,6 +85,10 @@ JNIEnv* create_vm(char *api_impl_jar, char *apk_classpath, char *microg_apk, cha
// TODO: request resources.arsc from concrete apk instead of taking the first one in classpath // TODO: request resources.arsc from concrete apk instead of taking the first one in classpath
options[1].optionString = construct_classpath("-Djava.class.path=", (char *[]){api_impl_jar, apk_classpath, microg_apk}, 3); options[1].optionString = construct_classpath("-Djava.class.path=", (char *[]){api_impl_jar, apk_classpath, microg_apk}, 3);
options[2].optionString = "-verbose:jni"; options[2].optionString = "-verbose:jni";
if(jdwp_port) {
strncat(jdwp_option_string, jdwp_port, 5); // 5 chars is enough for a port number, and won't overflow our array
options[3].optionString = jdwp_option_string;
}
args.options = options; args.options = options;
args.ignoreUnrecognized = JNI_FALSE; args.ignoreUnrecognized = JNI_FALSE;
@@ -91,6 +102,19 @@ JNIEnv* create_vm(char *api_impl_jar, char *apk_classpath, char *microg_apk, cha
return env; return env;
} }
gboolean hacky_on_window_focus_changed_callback(JNIEnv *env)
{
if(gtk_widget_get_width(window) != 0) {
(*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.onWindowFocusChanged, true);
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
return G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
}
// this is exported by the shim bionic linker // this is exported by the shim bionic linker
void dl_parse_library_path(const char *path, char *delim); void dl_parse_library_path(const char *path, char *delim);
@@ -259,10 +283,14 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
_SET_STATIC_INT_FIELD(display_class, "window_width", d->window_width); _SET_STATIC_INT_FIELD(display_class, "window_width", d->window_width);
_SET_STATIC_INT_FIELD(display_class, "window_height", d->window_height); _SET_STATIC_INT_FIELD(display_class, "window_height", d->window_height);
// some apps need the apk path since they directly read their apk
jclass context_class = (*env)->FindClass(env, "android/content/Context");
_SET_STATIC_OBJ_FIELD(context_class, "apk_path", "java/lang/String", _JSTRING(apk_classpath));
FIXME__WIDTH = d->window_width; FIXME__WIDTH = d->window_width;
FIXME__HEIGHT = d->window_height; FIXME__HEIGHT = d->window_height;
window = gtk_application_window_new (app); window = gtk_application_window_new(app);
(*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.set_window, _INTPTR(window)); (*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.set_window, _INTPTR(window));
if((*env)->ExceptionCheck(env)) if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env); (*env)->ExceptionDescribe(env);
@@ -306,9 +334,8 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
if((*env)->ExceptionCheck(env)) if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env); (*env)->ExceptionDescribe(env);
(*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.onWindowFocusChanged, true); g_timeout_add(10, G_SOURCE_FUNC(hacky_on_window_focus_changed_callback), env);
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
jobject input_queue_callback = g_object_get_data(G_OBJECT(window), "input_queue_callback"); jobject input_queue_callback = g_object_get_data(G_OBJECT(window), "input_queue_callback");
if(input_queue_callback) { if(input_queue_callback) {