mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-02-14 17:50:06 +00:00
aux/android: Using DexClassLoader to load class
This commit is contained in:
parent
dfd37bba78
commit
25e96a508c
src
external/android-jni-wrap/wrap
xrt
auxiliary/android
ipc/android
|
@ -10,6 +10,8 @@ DexClassLoader::Meta::Meta()
|
|||
: MetaBase(DexClassLoader::getTypeName()),
|
||||
init(classRef().getMethod("<init>",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/"
|
||||
"lang/String;Ljava/lang/ClassLoader;)V")) {}
|
||||
"lang/String;Ljava/lang/ClassLoader;)V")),
|
||||
loadClass(classRef().getMethod("loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;")) {}
|
||||
} // namespace dalvik::system
|
||||
} // namespace wrap
|
||||
|
|
|
@ -12,6 +12,7 @@ class DexClassLoader;
|
|||
} // namespace dalvik::system
|
||||
|
||||
namespace java::lang {
|
||||
class Class;
|
||||
class ClassLoader;
|
||||
} // namespace java::lang
|
||||
|
||||
|
@ -44,11 +45,24 @@ class DexClassLoader : public ObjectWrapperBase {
|
|||
std::string const &nativeSearchPath,
|
||||
jni::Object parentClassLoader);
|
||||
|
||||
/*!
|
||||
* Wrapper for the loadClass method
|
||||
*
|
||||
* Java prototype:
|
||||
* `public java.lang.Class<?> loadClass(java.lang.String) throws
|
||||
* java.lang.ClassNotFoundException;`
|
||||
*
|
||||
* JNI signature: (Ljava/lang/String;)Ljava/lang/Class;
|
||||
*
|
||||
*/
|
||||
java::lang::Class loadClass(std::string const &name);
|
||||
|
||||
/*!
|
||||
* Class metadata
|
||||
*/
|
||||
struct Meta : public MetaBase {
|
||||
jni::method_t init;
|
||||
jni::method_t loadClass;
|
||||
|
||||
/*!
|
||||
* Singleton accessor
|
||||
|
|
|
@ -19,5 +19,11 @@ DexClassLoader::construct(std::string const &searchPath,
|
|||
nativeSearchPath, parentClassLoader)};
|
||||
}
|
||||
|
||||
inline java::lang::Class
|
||||
DexClassLoader::loadClass(const std::string &name) {
|
||||
assert(!isNull());
|
||||
return java::lang::Class{object().call<jni::Object>(Meta::data().loadClass, name)};
|
||||
}
|
||||
|
||||
} // namespace dalvik::system
|
||||
} // namespace wrap
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
using wrap::android::app::Activity;
|
||||
using wrap::android::view::SurfaceHolder;
|
||||
using wrap::org::freedesktop::monado::auxiliary::MonadoView;
|
||||
using xrt::auxiliary::android::getAppInfo;
|
||||
using xrt::auxiliary::android::loadClassFromPackage;
|
||||
using xrt::auxiliary::android::loadClassFromRuntimeApk;
|
||||
|
||||
|
||||
struct android_custom_surface
|
||||
|
@ -53,24 +52,14 @@ android_custom_surface::~android_custom_surface()
|
|||
}
|
||||
}
|
||||
|
||||
constexpr auto FULLY_QUALIFIED_CLASSNAME = "org.freedesktop.monado.auxiliary.MonadoView";
|
||||
|
||||
struct android_custom_surface *
|
||||
android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
||||
{
|
||||
jni::init(vm);
|
||||
try {
|
||||
auto info = getAppInfo(XRT_ANDROID_PACKAGE, (jobject)activity);
|
||||
if (info.isNull()) {
|
||||
U_LOG_E("Could not get application info for package '%s'",
|
||||
"org.freedesktop.monado.openxr_runtime");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto clazz = loadClassFromPackage(info, (jobject)activity, FULLY_QUALIFIED_CLASSNAME);
|
||||
|
||||
auto clazz = loadClassFromRuntimeApk((jobject)activity, MonadoView::getFullyQualifiedTypeName());
|
||||
if (clazz.isNull()) {
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", FULLY_QUALIFIED_CLASSNAME,
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", MonadoView::getFullyQualifiedTypeName(),
|
||||
XRT_ANDROID_PACKAGE);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -90,7 +79,7 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
|
|||
}
|
||||
|
||||
std::string clazz_name = ret->monadoViewClass.getName();
|
||||
if (clazz_name != FULLY_QUALIFIED_CLASSNAME) {
|
||||
if (clazz_name != MonadoView::getFullyQualifiedTypeName()) {
|
||||
U_LOG_E("Unexpected class name: %s", clazz_name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -156,17 +145,9 @@ android_custom_surface_get_display_metrics(struct _JavaVM *vm,
|
|||
{
|
||||
jni::init(vm);
|
||||
try {
|
||||
auto info = getAppInfo(XRT_ANDROID_PACKAGE, (jobject)activity);
|
||||
if (info.isNull()) {
|
||||
U_LOG_E("Could not get application info for package '%s'",
|
||||
"org.freedesktop.monado.openxr_runtime");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto clazz = loadClassFromPackage(info, (jobject)activity, FULLY_QUALIFIED_CLASSNAME);
|
||||
|
||||
auto clazz = loadClassFromRuntimeApk((jobject)activity, MonadoView::getFullyQualifiedTypeName());
|
||||
if (clazz.isNull()) {
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", FULLY_QUALIFIED_CLASSNAME,
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", MonadoView::getFullyQualifiedTypeName(),
|
||||
XRT_ANDROID_PACKAGE);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,15 +12,37 @@
|
|||
#include "util/u_logging.h"
|
||||
|
||||
#include "wrap/android.content.h"
|
||||
#include "wrap/dalvik.system.h"
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
using wrap::android::content::Context;
|
||||
using wrap::android::content::pm::ApplicationInfo;
|
||||
using wrap::android::content::pm::PackageManager;
|
||||
using wrap::dalvik::system::DexClassLoader;
|
||||
|
||||
namespace xrt::auxiliary::android {
|
||||
|
||||
/*!
|
||||
* Hacky way to retrieve runtime source dir.
|
||||
*/
|
||||
static std::string
|
||||
getRuntimeSourceDir()
|
||||
{
|
||||
Dl_info info{};
|
||||
std::string dir;
|
||||
if (dladdr((void *)&getRuntimeSourceDir, &info)) {
|
||||
// dli_filename is full path of the library contains the symbol. For example:
|
||||
// /data/app/~~sha27MVNR46wLF-96zA_LQ==/org.freedesktop.monado.openxr_runtime.out_of_process-cqs8L2Co3WfHGgvDwF12JA==/lib/arm64/libopenxr_monado.so
|
||||
dir = info.dli_fname;
|
||||
dir = dir.substr(0, dir.find("/lib/"));
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
ApplicationInfo
|
||||
getAppInfo(std::string const &packageName, jobject application_context)
|
||||
{
|
||||
|
@ -50,7 +72,7 @@ getAppInfo(std::string const &packageName, jobject application_context)
|
|||
}
|
||||
return packageInfo.getApplicationInfo();
|
||||
} catch (std::exception const &e) {
|
||||
U_LOG_E("Could get App Info: %s", e.what());
|
||||
U_LOG_E("Could not get App Info: %s", e.what());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -76,10 +98,42 @@ loadClassFromPackage(ApplicationInfo applicationInfo, jobject application_contex
|
|||
|
||||
return loadedClass;
|
||||
} catch (std::exception const &e) {
|
||||
U_LOG_E("Could load class '%s' forName: %s", clazz_name, e.what());
|
||||
U_LOG_E("Could not load class '%s' forName: %s", clazz_name, e.what());
|
||||
return wrap::java::lang::Class();
|
||||
}
|
||||
}
|
||||
|
||||
wrap::java::lang::Class
|
||||
loadClassFromApk(jobject application_context, const char *apk_path, const char *clazz_name)
|
||||
{
|
||||
Context context = Context{application_context}.getApplicationContext();
|
||||
DexClassLoader classLoader = DexClassLoader::construct(apk_path, "", context.getClassLoader().object());
|
||||
try {
|
||||
auto loadedClass = classLoader.loadClass(std::string(clazz_name));
|
||||
if (loadedClass.isNull()) {
|
||||
U_LOG_E("Could not load class for name %s from %s", clazz_name, apk_path);
|
||||
return wrap::java::lang::Class();
|
||||
}
|
||||
|
||||
return loadedClass;
|
||||
} catch (std::exception const &e) {
|
||||
U_LOG_E("Could not load class '%s' from '%s' forName: %s", clazz_name, apk_path, e.what());
|
||||
return wrap::java::lang::Class();
|
||||
}
|
||||
}
|
||||
|
||||
wrap::java::lang::Class
|
||||
loadClassFromRuntimeApk(jobject application_context, const char *clazz_name)
|
||||
{
|
||||
if (!application_context) {
|
||||
U_LOG_E("Could not load class %s, invalid context", clazz_name);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string runtimeApkPath = getRuntimeSourceDir() + "/base.apk";
|
||||
return loadClassFromApk(application_context, runtimeApkPath.c_str(), clazz_name);
|
||||
}
|
||||
|
||||
} // namespace xrt::auxiliary::android
|
||||
|
||||
|
||||
|
|
|
@ -20,12 +20,43 @@ namespace xrt::auxiliary::android {
|
|||
|
||||
using wrap::android::content::pm::ApplicationInfo;
|
||||
|
||||
/*!
|
||||
* @note Starting from Android 11, NameNotFoundException exception is thrown if application doesn't
|
||||
* specify either <queries> or "android.permission.QUERY_ALL_PACKAGES".
|
||||
* See https://developer.android.com/training/package-visibility for detail.
|
||||
*/
|
||||
ApplicationInfo
|
||||
getAppInfo(std::string const &packageName, jobject application_context);
|
||||
|
||||
/*!
|
||||
* @note Starting from Android 11, NameNotFoundException exception is thrown if application doesn't
|
||||
* specify either <queries> or "android.permission.QUERY_ALL_PACKAGES".
|
||||
* See https://developer.android.com/training/package-visibility for detail.
|
||||
*/
|
||||
wrap::java::lang::Class
|
||||
loadClassFromPackage(ApplicationInfo applicationInfo, jobject application_context, const char *clazz_name);
|
||||
|
||||
/*!
|
||||
* Loading class from given apk path.
|
||||
*
|
||||
* @param application_context Context.
|
||||
* @param apk_path Path to apk.
|
||||
* @param clazz_name Name of class to be loaded.
|
||||
* @return Class object.
|
||||
*/
|
||||
wrap::java::lang::Class
|
||||
loadClassFromApk(jobject application_context, const char *apk_path, const char *clazz_name);
|
||||
|
||||
/*!
|
||||
* Loading class from runtime apk.
|
||||
*
|
||||
* @param application_context Context.
|
||||
* @param clazz_name Name of class to be loaded.
|
||||
* @return Class object.
|
||||
*/
|
||||
wrap::java::lang::Class
|
||||
loadClassFromRuntimeApk(jobject application_context, const char *clazz_name);
|
||||
|
||||
} // namespace xrt::auxiliary::android
|
||||
|
||||
#endif // XRT_OS_ANDROID
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
using wrap::android::app::Activity;
|
||||
using wrap::org::freedesktop::monado::ipc::Client;
|
||||
using xrt::auxiliary::android::getAppInfo;
|
||||
using xrt::auxiliary::android::loadClassFromPackage;
|
||||
using xrt::auxiliary::android::loadClassFromRuntimeApk;
|
||||
|
||||
struct ipc_client_android
|
||||
{
|
||||
|
@ -52,15 +51,7 @@ ipc_client_android_create(struct _JavaVM *vm, void *activity)
|
|||
|
||||
jni::init(vm);
|
||||
try {
|
||||
auto info = getAppInfo(XRT_ANDROID_PACKAGE, (jobject)activity);
|
||||
if (info.isNull()) {
|
||||
U_LOG_E("Could not get application info for package '%s'",
|
||||
"org.freedesktop.monado.openxr_runtime");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto clazz = loadClassFromPackage(info, (jobject)activity, Client::getFullyQualifiedTypeName());
|
||||
|
||||
auto clazz = loadClassFromRuntimeApk((jobject)activity, Client::getFullyQualifiedTypeName());
|
||||
if (clazz.isNull()) {
|
||||
U_LOG_E("Could not load class '%s' from package '%s'", Client::getFullyQualifiedTypeName(),
|
||||
XRT_ANDROID_PACKAGE);
|
||||
|
|
Loading…
Reference in a new issue