2020-09-08 19:31:50 +00:00
|
|
|
// Copyright 2020, Collabora, Ltd.
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
|
|
|
|
|
|
|
#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;
|
|
|
|
|
|
|
|
static 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) {
|
2020-09-25 17:13:22 +00:00
|
|
|
U_LOG_E("Could get App Info: %s", e.what());
|
2020-09-08 19:31:50 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static 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();
|
|
|
|
|
2020-09-25 17:13:22 +00:00
|
|
|
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();
|
|
|
|
}
|
2020-09-08 19:31:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|