From e600cdaabffe4d622e1c2c88f6d7229fd08e6e0f Mon Sep 17 00:00:00 2001 From: Maxim Kizub Date: Tue, 29 Nov 2022 03:31:30 +0200 Subject: [PATCH] c/main,ipc/android: Deferred render target initialization for Android. --- src/xrt/compositor/main/comp_window_android.c | 15 ++++- .../org/freedesktop/monado/ipc/Client.java | 64 +++++++++++-------- .../freedesktop/monado/ipc/MonadoImpl.java | 1 + 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/xrt/compositor/main/comp_window_android.c b/src/xrt/compositor/main/comp_window_android.c index ff26da022..1b02fb426 100644 --- a/src/xrt/compositor/main/comp_window_android.c +++ b/src/xrt/compositor/main/comp_window_android.c @@ -138,8 +138,17 @@ comp_window_android_init_swapchain(struct comp_target *ct, uint32_t width, uint3 /* In process: Creating surface from activity */ window = _create_android_window(cwa); } else { - /* Out of process: Getting cached surface */ - window = (struct ANativeWindow *)android_globals_get_window(); + /* Out of process: Getting cached surface. + * This loop polls for a surface created by Client.java in blockingConnect. + * TODO: change java code to callback native code to notify Session lifecycle progress, instead of + * polling here + */ + for (int i = 0; i < 100; i++) { + window = (struct ANativeWindow *)android_globals_get_window(); + if (window) + break; + os_nanosleep(20 * U_TIME_1MS_IN_NS); + } } if (window == NULL) { @@ -215,7 +224,7 @@ struct comp_target_factory comp_target_factory_android = { .name = "Android", .identifier = "android", .requires_vulkan_for_create = false, - .is_deferred = false, + .is_deferred = true, .required_instance_extensions = instance_extensions, .required_instance_extension_count = ARRAY_SIZE(instance_extensions), .detect = detect, diff --git a/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/Client.java b/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/Client.java index 1f657c2ea..e821523df 100644 --- a/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/Client.java +++ b/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/Client.java @@ -161,40 +161,48 @@ public class Client implements ServiceConnection { return -1; } - boolean surfaceCreated = false; - Activity activity = null; - if (context_ instanceof Activity) { - activity = (Activity) context_; - } + // This block of code asynchronously create a MonadoView attached to activity and + // waits for Surface creation. Native code (comp_window_android_init_swapchain() method) + // will poll for ANativeWindow created from this Surface. + // TODO: just initiate MonadoView attachement and add callback to native code to + // notify about Surface status and pass it to OpenXR application as a Session lifecycle + // (ready ... synchronized ... visible ... focused) + new Thread(()-> { + boolean surfaceCreated = false; + Activity activity = null; + if (context_ instanceof Activity) { + activity = (Activity) context_; + } - try { - // Determine whether runtime or client should create surface - if (monado.canDrawOverOtherApps()) { - WindowManager wm = (WindowManager) context_.getSystemService(Context.WINDOW_SERVICE); - surfaceCreated = monado.createSurface(wm.getDefaultDisplay().getDisplayId(), false); - } else { - if (activity != null) { - Surface surface = attachViewAndGetSurface(activity); - surfaceCreated = (surface != null); - if (surfaceCreated) { - monado.passAppSurface(surface); + try { + // Determine whether runtime or client should create surface + if (monado.canDrawOverOtherApps()) { + WindowManager wm = (WindowManager) context_.getSystemService(Context.WINDOW_SERVICE); + surfaceCreated = monado.createSurface(wm.getDefaultDisplay().getDisplayId(), false); + } else { + if (activity != null) { + Surface surface = attachViewAndGetSurface(activity); + surfaceCreated = (surface != null); + if (surfaceCreated) { + monado.passAppSurface(surface); + } } } + } catch (RemoteException e) { + e.printStackTrace(); } - } catch (RemoteException e) { - e.printStackTrace(); - } - if (!surfaceCreated) { - Log.e(TAG, "Failed to create surface"); - handleFailure(); - return -1; - } + if (!surfaceCreated) { + Log.e(TAG, "Failed to create surface"); + handleFailure(); + return; + } - if (activity != null) { - systemUiController = new SystemUiController(activity); - systemUiController.hide(); - } + if (activity != null) { + systemUiController = new SystemUiController(activity); + systemUiController.hide(); + } + }).start(); // Create socket pair ParcelFileDescriptor theirs; diff --git a/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/MonadoImpl.java b/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/MonadoImpl.java index 5cfd1fb8c..7bb8310d0 100644 --- a/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/MonadoImpl.java +++ b/src/xrt/ipc/android/src/main/java/org/freedesktop/monado/ipc/MonadoImpl.java @@ -65,6 +65,7 @@ public class MonadoImpl extends IMonado.Stub { @Override public void connect(@NotNull ParcelFileDescriptor parcelFileDescriptor) { + nativeStartServer(); int fd = parcelFileDescriptor.getFd(); Log.i(TAG, "connect: given fd " + fd); if (nativeAddClient(fd) != 0) {