The open source OpenXR runtime
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 Ryan Pavlik <ryan.pavlik@collabora.com>
7 * @ingroup ipc_android
8 */
9
10#include "ipc_client_android.h"
11
12#include "org.freedesktop.monado.ipc.hpp"
13#include "wrap/android.app.h"
14
15
16#include "xrt/xrt_config_android.h"
17#include "android/android_load_class.hpp"
18#include "util/u_logging.h"
19
20using wrap::android::app::Activity;
21using wrap::org::freedesktop::monado::ipc::Client;
22
23struct ipc_client_android
24{
25 ipc_client_android(jobject act) : activity(act) {}
26 ~ipc_client_android();
27
28 Activity activity{};
29 Client client{nullptr};
30};
31
32ipc_client_android::~ipc_client_android()
33{
34
35 // Tell Java that native code is done with this.
36 try {
37 if (!client.isNull()) {
38 client.markAsDiscardedByNative();
39 }
40 } catch (std::exception const &e) {
41 // Must catch and ignore any exceptions in the destructor!
42 U_LOG_E("Failure while marking IPC client as discarded: %s", e.what());
43 }
44}
45
46struct ipc_client_android *
47ipc_client_android_create(struct _JavaVM *vm, void *activity)
48{
49
50 jni::init(vm);
51 try {
52 auto info = getAppInfo(XRT_ANDROID_PACKAGE, (jobject)activity);
53 if (info.isNull()) {
54 U_LOG_E("Could not get application info for package '%s'",
55 "org.freedesktop.monado.openxr_runtime");
56 return nullptr;
57 }
58
59 auto clazz = loadClassFromPackage(info, (jobject)activity, Client::getFullyQualifiedTypeName());
60
61 if (clazz.isNull()) {
62 U_LOG_E("Could not load class '%s' from package '%s'", Client::getFullyQualifiedTypeName(),
63 XRT_ANDROID_PACKAGE);
64 return nullptr;
65 }
66
67 // Teach the wrapper our class before we start to use it.
68 Client::staticInitClass((jclass)clazz.object().getHandle());
69 std::unique_ptr<ipc_client_android> ret = std::make_unique<ipc_client_android>((jobject)activity);
70
71 ret->client = Client::construct(ret.get());
72
73 return ret.release();
74 } catch (std::exception const &e) {
75
76 U_LOG_E("Could not start IPC client class: %s", e.what());
77 return nullptr;
78 }
79}
80
81int
82ipc_client_android_blocking_connect(struct ipc_client_android *ica)
83{
84 try {
85 int fd = ica->client.blockingConnect(ica->activity, XRT_ANDROID_PACKAGE);
86 return fd;
87 } catch (std::exception const &e) {
88 // Must catch and ignore any exceptions in the destructor!
89 U_LOG_E("Failure while connecting to IPC server: %s", e.what());
90 return -1;
91 }
92}
93
94
95void
96ipc_client_android_destroy(struct ipc_client_android **ptr_ica)
97{
98
99 if (ptr_ica == NULL) {
100 return;
101 }
102 struct ipc_client_android *ica = *ptr_ica;
103 if (ica == NULL) {
104 return;
105 }
106 delete ica;
107 *ptr_ica = NULL;
108}