From 27550ffa39cdd1db6fa6d2c9ab203a91b0fd4901 Mon Sep 17 00:00:00 2001 From: Jarvis Huang Date: Tue, 30 Nov 2021 20:49:58 +0800 Subject: [PATCH] aux/android: Looper trick for NativeActivity with app-glue --- src/xrt/auxiliary/CMakeLists.txt | 2 +- src/xrt/auxiliary/android/android_looper.c | 32 ------------ src/xrt/auxiliary/android/android_looper.cpp | 51 ++++++++++++++++++++ src/xrt/auxiliary/android/android_looper.h | 2 + src/xrt/ipc/android/ipc_client_android.cpp | 5 -- src/xrt/state_trackers/oxr/oxr_instance.c | 3 ++ 6 files changed, 57 insertions(+), 38 deletions(-) delete mode 100644 src/xrt/auxiliary/android/android_looper.c create mode 100644 src/xrt/auxiliary/android/android_looper.cpp diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 9b26113ec..bf33ecf2d 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -290,7 +290,7 @@ if(ANDROID) android/android_globals.h android/android_load_class.cpp android/android_load_class.hpp - android/android_looper.c + android/android_looper.cpp android/android_looper.h android/org.freedesktop.monado.auxiliary.cpp android/org.freedesktop.monado.auxiliary.hpp diff --git a/src/xrt/auxiliary/android/android_looper.c b/src/xrt/auxiliary/android/android_looper.c deleted file mode 100644 index 7dce50d95..000000000 --- a/src/xrt/auxiliary/android/android_looper.c +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2021, Qualcomm Innovation Center, Inc. -// SPDX-License-Identifier: BSL-1.0 -/*! - * @file - * @brief Implementation of android looper functions. - * @author Jarvis Huang - * @ingroup aux_android - */ - -#include "android_looper.h" - -#include "util/u_logging.h" - -#include -#include - -void -android_looper_poll_until_activity_resumed() -{ - struct android_poll_source *source; - // Can we assume that activity already resumed if polling is failed? - while (ALooper_pollAll(-1, NULL, NULL, (void **)&source) == LOOPER_ID_MAIN) { - if (source) { - // Let callback owner handle the event - source->process(source->app, source); - if (source->app->activityState == APP_CMD_RESUME && source->app->window) { - U_LOG_I("Activity is in resume state and window is ready now"); - break; - } - } - } -} diff --git a/src/xrt/auxiliary/android/android_looper.cpp b/src/xrt/auxiliary/android/android_looper.cpp new file mode 100644 index 000000000..1cdb46f88 --- /dev/null +++ b/src/xrt/auxiliary/android/android_looper.cpp @@ -0,0 +1,51 @@ +// Copyright 2021, Qualcomm Innovation Center, Inc. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Implementation of android looper functions. + * @author Jarvis Huang + * @ingroup aux_android + */ + +#include "android_looper.h" + +#include "android/android_globals.h" +#include "util/u_logging.h" +#include "wrap/android.app.h" + +#include +#include + +#include + +void +android_looper_poll_until_activity_resumed() +{ + jni::init(android_globals_get_vm()); + wrap::android::app::Activity activity{(jobject)android_globals_get_activity()}; + if (!jni::env()->IsInstanceOf(activity.object().getHandle(), + jni::Class("android/app/NativeActivity").getHandle())) { + // skip if given activity is not android.app.NativeActivity + U_LOG_I("Activity is not NativeActivity, skip"); + return; + } + + // Activity is in resumed state if window is active. Check Activity#onPostResume for detail. + if (!activity.getWindow().isNull() && activity.getWindow().call("isActive()Z")) { + // Already in resume state, skip + U_LOG_I("Activity is NativeActivity and already in resume state with window available, skip"); + return; + } + + struct android_poll_source *source; + while (ALooper_pollAll(1000, NULL, NULL, (void **)&source) >= 0) { + if (source) { + // Let callback owner handle the event + source->process(source->app, source); + if (source->app->activityState == APP_CMD_RESUME && source->app->window) { + U_LOG_I("Activity is in resume state with window available now"); + break; + } + } + } +} diff --git a/src/xrt/auxiliary/android/android_looper.h b/src/xrt/auxiliary/android/android_looper.h index 9267e79a3..1b241e255 100644 --- a/src/xrt/auxiliary/android/android_looper.h +++ b/src/xrt/auxiliary/android/android_looper.h @@ -9,6 +9,8 @@ #pragma once +#include + #ifdef XRT_OS_ANDROID #ifdef __cplusplus diff --git a/src/xrt/ipc/android/ipc_client_android.cpp b/src/xrt/ipc/android/ipc_client_android.cpp index 73dba8d13..7f642740d 100644 --- a/src/xrt/ipc/android/ipc_client_android.cpp +++ b/src/xrt/ipc/android/ipc_client_android.cpp @@ -15,7 +15,6 @@ #include "util/u_logging.h" #include "android/android_load_class.hpp" -#include "android/android_looper.h" #include "wrap/android.app.h" @@ -85,10 +84,6 @@ ipc_client_android_create(struct _JavaVM *vm, void *activity) int ipc_client_android_blocking_connect(struct ipc_client_android *ica) { - // To avoid deadlock on main thread, force client entering resume state - // before setting up IPC/surface - android_looper_poll_until_activity_resumed(); - try { int fd = ica->client.blockingConnect(ica->activity, XRT_ANDROID_PACKAGE); return fd; diff --git a/src/xrt/state_trackers/oxr/oxr_instance.c b/src/xrt/state_trackers/oxr/oxr_instance.c index 2a0874c82..3792bc9d8 100644 --- a/src/xrt/state_trackers/oxr/oxr_instance.c +++ b/src/xrt/state_trackers/oxr/oxr_instance.c @@ -20,6 +20,7 @@ #ifdef XRT_OS_ANDROID #include "android/android_globals.h" +#include "android/android_looper.h" #endif #include "oxr_objects.h" @@ -263,6 +264,8 @@ oxr_instance_create(struct oxr_logger *log, const XrInstanceCreateInfo *createIn createInfo, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, XrInstanceCreateInfoAndroidKHR); android_globals_store_vm_and_activity((struct _JavaVM *)create_info_android->applicationVM, create_info_android->applicationActivity); + // Trick to avoid deadlock on main thread. Only works for NativeActivity with app-glue. + android_looper_poll_until_activity_resumed(); #endif xinst_ret = xrt_instance_create(&i_info, &inst->xinst);