monado/src/xrt/auxiliary/android/android_load_class.cpp

95 lines
2.8 KiB
C++
Raw Normal View History

// Copyright 2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
2020-10-28 16:29:15 +00:00
/*!
* @file
* @brief Implementations for loading Java code from a package.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @ingroup aux_android
*/
#include "android_load_class.h"
#include "util/u_logging.h"
#include "wrap/android.content.h"
#include "wrap/dalvik.system.h"
#include "jni.h"
using wrap::android::content::Context;
using wrap::android::content::pm::ApplicationInfo;
using wrap::android::content::pm::PackageManager;
ApplicationInfo
getAppInfo(std::string const &packageName, jobject application_context)
{
try {
auto context = Context{application_context};
auto packageManager =
PackageManager{context.getPackageManager()};
auto packageInfo = packageManager.getPackageInfo(
packageName, PackageManager::GET_META_DATA |
PackageManager::GET_SHARED_LIBRARY_FILES);
return packageInfo.getApplicationInfo();
} catch (std::exception const &e) {
U_LOG_E("Could get App Info: %s", e.what());
return {};
}
}
wrap::java::lang::Class
loadClassFromPackage(ApplicationInfo applicationInfo,
jobject application_context,
const char *clazz_name)
{
auto context = Context{application_context}.getApplicationContext();
auto pkgContext = context.createPackageContext(
applicationInfo.getPackageName(),
Context::CONTEXT_IGNORE_SECURITY | Context::CONTEXT_INCLUDE_CODE);
// Not using ClassLoader.loadClass because it expects a /-delimited
// class name, while we have a .-delimited class name.
// This does work
wrap::java::lang::ClassLoader pkgClassLoader =
pkgContext.getClassLoader();
try {
auto loadedClass =
pkgClassLoader.loadClass(std::string(clazz_name));
if (loadedClass.isNull()) {
U_LOG_E("Could not load class for name %s", clazz_name);
return wrap::java::lang::Class();
}
return loadedClass;
} catch (std::exception const &e) {
U_LOG_E("Could load class '%s' forName: %s", clazz_name,
e.what());
return wrap::java::lang::Class();
}
}
void *
android_load_class_from_package(struct _JavaVM *vm,
const char *pkgname,
void *application_context,
const char *classname)
{
jni::init(vm);
Context context((jobject)application_context);
auto info = getAppInfo(pkgname, (jobject)application_context);
if (info.isNull()) {
U_LOG_E("Could not get application info for package '%s'",
pkgname);
return nullptr;
}
auto clazz =
loadClassFromPackage(info, (jobject)application_context, classname);
if (clazz.isNull()) {
U_LOG_E("Could not load class '%s' from package '%s'",
classname, pkgname);
return nullptr;
}
return clazz.object().getHandle();
}