The open source OpenXR runtime

st/oxr: Combine Android activity lifecycle with session lifecycle

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

authored by

Jarvis Huang and committed by
Rylie Pavlik
764263d1 13e02395

+72
+1
doc/changes/misc_features/mr.1655.md
··· 1 + Handle Android activity lifecycle.
+25
src/xrt/state_trackers/oxr/oxr_instance.c
··· 51 51 DEBUG_GET_ONCE_BOOL_OPTION(lifecycle_verbose, "OXR_LIFECYCLE_VERBOSE", false) 52 52 53 53 54 + #ifdef XRT_OS_ANDROID 55 + static bool 56 + on_activity_lifecycle_state_changed(struct xrt_instance_android *xinst_android, 57 + enum xrt_android_lifecycle_event event, 58 + void *userdata) 59 + { 60 + struct oxr_instance *inst = (struct oxr_instance *)userdata; 61 + inst->activity_state = event; 62 + 63 + // Return false to not be removed from the list of callbacks 64 + return false; 65 + } 66 + #endif // #ifdef XRT_OS_ANDROID 67 + 54 68 static XrResult 55 69 oxr_instance_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) 56 70 { ··· 309 323 oxr_instance_destroy(log, &inst->handle); 310 324 return ret; 311 325 } 326 + 327 + #ifdef XRT_OS_ANDROID 328 + xret = xrt_instance_android_register_activity_lifecycle_callback( 329 + inst->xinst->android_instance, on_activity_lifecycle_state_changed, 330 + XRT_ANDROID_LIVECYCLE_EVENT_ON_RESUME | XRT_ANDROID_LIVECYCLE_EVENT_ON_PAUSE, inst); 331 + // overlay application might be a service instead of an activity, so do not return error if 332 + // failed to register activity lifecycle callback. 333 + if (xret != XRT_SUCCESS) { 334 + oxr_warn(log, "Failed to register activity lifecycle callback '%i'", xret); 335 + } 336 + #endif // XRT_OS_ANDROID 312 337 313 338 struct oxr_system *sys = &inst->system; 314 339
+8
src/xrt/state_trackers/oxr/oxr_objects.h
··· 45 45 #endif // !XRT_OS_WINDOWS 46 46 #endif // XRT_FEATURE_RENDERDOC 47 47 48 + #ifdef XRT_OS_ANDROID 49 + #include "xrt/xrt_android.h" 50 + #endif // #ifdef XRT_OS_ANDROID 51 + 48 52 #ifdef __cplusplus 49 53 extern "C" { 50 54 #endif ··· 1720 1724 #ifdef XRT_FEATURE_RENDERDOC 1721 1725 RENDERDOC_API_1_4_1 *rdoc_api; 1722 1726 #endif 1727 + 1728 + #ifdef XRT_OS_ANDROID 1729 + enum xrt_android_lifecycle_event activity_state; 1730 + #endif // XRT_OS_ANDROID 1723 1731 }; 1724 1732 1725 1733 /*!
+38
src/xrt/state_trackers/oxr/oxr_session.c
··· 295 295 if (sess->exiting) { 296 296 oxr_session_change_state(log, sess, XR_SESSION_STATE_EXITING, 0); 297 297 } else { 298 + #ifndef XRT_OS_ANDROID 299 + // @todo In multi-clients scenario with a session being reused, changing session 300 + // state to XR_SESSION_STATE_READY would cause application to call xrBeginSession 301 + // immediately and this is not desired. On Android platform, runtime would 302 + // change session state to XR_SESSION_STATE_READY once application goes to 303 + // foreground again. But on other platform it's not handled yet. 298 304 oxr_session_change_state(log, sess, XR_SESSION_STATE_READY, 0); 305 + #endif // !XRT_OS_ANDROID 299 306 } 300 307 301 308 sess->has_begun = false; 309 + sess->has_ended_once = false; 302 310 303 311 return oxr_session_success_result(sess); 304 312 } ··· 354 362 if (xs == NULL) { 355 363 return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "xrt_session is null"); 356 364 } 365 + 366 + #ifdef XRT_OS_ANDROID 367 + // Most recent Android activity lifecycle event was OnPause: move toward stopping 368 + if (sess->sys->inst->activity_state == XRT_ANDROID_LIVECYCLE_EVENT_ON_PAUSE) { 369 + if (sess->state == XR_SESSION_STATE_FOCUSED) { 370 + U_LOG_I("Activity paused: changing session state FOCUSED->VISIBLE"); 371 + oxr_session_change_state(log, sess, XR_SESSION_STATE_VISIBLE, 0); 372 + } 373 + 374 + if (sess->state == XR_SESSION_STATE_VISIBLE) { 375 + U_LOG_I("Activity paused: changing session state VISIBLE->SYNCHRONIZED"); 376 + oxr_session_change_state(log, sess, XR_SESSION_STATE_SYNCHRONIZED, 0); 377 + } 378 + 379 + if (sess->state == XR_SESSION_STATE_SYNCHRONIZED) { 380 + U_LOG_I("Activity paused: changing session state SYNCHRONIZED->STOPPING"); 381 + oxr_session_change_state(log, sess, XR_SESSION_STATE_STOPPING, 0); 382 + } 383 + // TODO return here to avoid polling other events? 384 + // see https://gitlab.freedesktop.org/monado/monado/-/issues/419 385 + } 386 + 387 + // Most recent Android activity lifecycle event was OnResume: move toward ready 388 + if (sess->sys->inst->activity_state == XRT_ANDROID_LIVECYCLE_EVENT_ON_RESUME) { 389 + if (sess->state == XR_SESSION_STATE_IDLE) { 390 + U_LOG_I("Activity resumed: changing session state IDLE->READY"); 391 + oxr_session_change_state(log, sess, XR_SESSION_STATE_READY, 0); 392 + } 393 + } 394 + #endif // XRT_OS_ANDROID 357 395 358 396 bool read_more_events = true; 359 397 while (read_more_events) {