The open source OpenXR runtime
at main 3.0 kB view raw
1// Copyright 2020, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Implementation exposing Android-specific IPC client code to C. 6 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 7 * @ingroup ipc_android 8 */ 9 10#include "ipc_client_android.h" 11 12#include "org.freedesktop.monado.ipc.hpp" 13 14#include "xrt/xrt_config_android.h" 15#include "util/u_logging.h" 16 17#include "android/android_load_class.hpp" 18#include "android/android_looper.h" 19 20#include "wrap/android.app.h" 21 22using wrap::android::app::Activity; 23using wrap::org::freedesktop::monado::ipc::Client; 24using xrt::auxiliary::android::loadClassFromRuntimeApk; 25 26struct ipc_client_android 27{ 28 ipc_client_android(struct _JavaVM *vm_, jobject act) : vm(vm_), activity(act) {} 29 ~ipc_client_android(); 30 struct _JavaVM *vm; 31 32 Activity activity{}; 33 Client client{nullptr}; 34}; 35 36ipc_client_android::~ipc_client_android() 37{ 38 39 // Tell Java that native code is done with this. 40 try { 41 if (!client.isNull()) { 42 client.markAsDiscardedByNative(); 43 } 44 } catch (std::exception const &e) { 45 // Must catch and ignore any exceptions in the destructor! 46 U_LOG_E("Failure while marking IPC client as discarded: %s", e.what()); 47 } 48} 49 50struct ipc_client_android * 51ipc_client_android_create(struct _JavaVM *vm, void *activity) 52{ 53 54 jni::init(vm); 55 try { 56 auto clazz = loadClassFromRuntimeApk((jobject)activity, Client::getFullyQualifiedTypeName()); 57 if (clazz.isNull()) { 58 U_LOG_E("Could not load class '%s' from package '%s'", Client::getFullyQualifiedTypeName(), 59 XRT_ANDROID_PACKAGE); 60 return nullptr; 61 } 62 63 // Teach the wrapper our class before we start to use it. 64 Client::staticInitClass((jclass)clazz.object().getHandle()); 65 std::unique_ptr<ipc_client_android> ret = std::make_unique<ipc_client_android>(vm, (jobject)activity); 66 67 ret->client = Client::construct(ret.get()); 68 69 return ret.release(); 70 } catch (std::exception const &e) { 71 72 U_LOG_E("Could not start IPC client class: %s", e.what()); 73 return nullptr; 74 } 75} 76 77int 78ipc_client_android_blocking_connect(struct ipc_client_android *ica) 79{ 80 try { 81 // Trick to avoid deadlock on main thread: only applicable to NativeActivity with app-glue. 82 // blockingConnect will block until binder is ready, the app-glue code will deadlock without this. 83 JavaVM *vm = ica->vm; 84 android_looper_poll_until_activity_resumed(vm, ica->activity.object().getHandle()); 85 int fd = ica->client.blockingConnect(ica->activity, XRT_ANDROID_PACKAGE); 86 return fd; 87 } catch (std::exception const &e) { 88 U_LOG_E("Failure while connecting to IPC server: %s", e.what()); 89 return -1; 90 } 91} 92 93 94void 95ipc_client_android_destroy(struct ipc_client_android **ptr_ica) 96{ 97 98 if (ptr_ica == NULL) { 99 return; 100 } 101 struct ipc_client_android *ica = *ptr_ica; 102 if (ica == NULL) { 103 return; 104 } 105 try { 106 delete ica; 107 } catch (std::exception const &e) { 108 // Must catch and ignore any exceptions in the destructor! 109 U_LOG_E("Failure while destroying IPC clean: %s", e.what()); 110 } 111 *ptr_ica = NULL; 112}