The open source OpenXR runtime

st/oxr,a/android,ipc/android: Move Android looper trick into the IPC client.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2308>

authored by

Jarvis Huang and committed by
Rylie Pavlik
9e46d56c 2685fb1d

+14 -13
+5 -8
src/xrt/auxiliary/android/android_looper.cpp
··· 9 9 10 10 #include "android_looper.h" 11 11 12 - #include "android/android_globals.h" 13 12 #include "util/u_logging.h" 14 13 #include "wrap/android.app.h" 15 14 16 15 #include <android_native_app_glue.h> 17 16 #include <android/looper.h> 18 17 19 - #include <android/log.h> 20 - 21 18 void 22 - android_looper_poll_until_activity_resumed() 19 + android_looper_poll_until_activity_resumed(struct _JavaVM *vm, void *activity) 23 20 { 24 - jni::init(android_globals_get_vm()); 25 - wrap::android::app::Activity activity{(jobject)android_globals_get_activity()}; 26 - if (!jni::env()->IsInstanceOf(activity.object().getHandle(), 21 + jni::init(vm); 22 + wrap::android::app::Activity activityObject{(jobject)activity}; 23 + if (!jni::env()->IsInstanceOf(activityObject.object().getHandle(), 27 24 jni::Class("android/app/NativeActivity").getHandle())) { 28 25 // skip if given activity is not android.app.NativeActivity 29 26 U_LOG_I("Activity is not NativeActivity, skip"); ··· 31 28 } 32 29 33 30 // Activity is in resumed state if window is active. Check Activity#onPostResume for detail. 34 - if (!activity.getWindow().isNull() && activity.getWindow().call<bool>("isActive()Z")) { 31 + if (!activityObject.getWindow().isNull() && activityObject.getWindow().call<bool>("isActive()Z")) { 35 32 // Already in resume state, skip 36 33 U_LOG_I("Activity is NativeActivity and already in resume state with window available, skip"); 37 34 return;
+3 -1
src/xrt/auxiliary/android/android_looper.h
··· 17 17 extern "C" { 18 18 #endif 19 19 20 + struct _JavaVM; 21 + 20 22 /*! 21 23 * Poll the looper until activity is in resume state. 22 24 */ 23 25 void 24 - android_looper_poll_until_activity_resumed(); 26 + android_looper_poll_until_activity_resumed(struct _JavaVM *vm, void *activity); 25 27 26 28 #ifdef __cplusplus 27 29 }
+6 -1
src/xrt/ipc/android/ipc_client_android.cpp
··· 15 15 #include "util/u_logging.h" 16 16 17 17 #include "android/android_load_class.hpp" 18 + #include "android/android_looper.h" 18 19 19 20 #include "wrap/android.app.h" 20 21 ··· 76 77 ipc_client_android_blocking_connect(struct ipc_client_android *ica) 77 78 { 78 79 try { 80 + // Trick to avoid deadlock on main thread: only applicable to NativeActivity with app-glue. 81 + // blockingConnect will block until binder is ready, the app-glue code will deadlock without this. 82 + JavaVM *vm = nullptr; 83 + jni::env()->GetJavaVM(&vm); 84 + android_looper_poll_until_activity_resumed(vm, ica->activity.object().getHandle()); 79 85 int fd = ica->client.blockingConnect(ica->activity, XRT_ANDROID_PACKAGE); 80 86 return fd; 81 87 } catch (std::exception const &e) { 82 - // Must catch and ignore any exceptions in the destructor! 83 88 U_LOG_E("Failure while connecting to IPC server: %s", e.what()); 84 89 return -1; 85 90 }
-3
src/xrt/state_trackers/oxr/oxr_instance.c
··· 27 27 28 28 #ifdef XRT_OS_ANDROID 29 29 #include "android/android_globals.h" 30 - #include "android/android_looper.h" 31 30 #endif 32 31 33 32 #include "oxr_objects.h" ··· 291 290 createInfo, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, XrInstanceCreateInfoAndroidKHR); 292 291 android_globals_store_vm_and_activity((struct _JavaVM *)create_info_android->applicationVM, 293 292 create_info_android->applicationActivity); 294 - // Trick to avoid deadlock on main thread. Only works for NativeActivity with app-glue. 295 - android_looper_poll_until_activity_resumed(); 296 293 #endif 297 294 298 295