diff options
author | Jooyung Han <jooyung@google.com> | 2020-03-03 00:46:50 +0900 |
---|---|---|
committer | Treehugger Robot <treehugger-gerrit@google.com> | 2020-03-04 05:56:39 +0000 |
commit | 538f99ab285c1440969b9b3331fc0ce750c0d316 (patch) | |
tree | 018e9cbfc08ba39b3f35e457a8658fcc4cc8db75 /libnativeloader/library_namespaces.cpp | |
parent | 6fc471e510d6a4e9c31fcab6c0542e2efdf50099 (diff) |
Loading JNI libraries in an APEX
To load JNI libraries in an APEX, libnativeloader relies on
jni.config.txt file which contains available JNI libraries for
APEX namespaces:
com_android_foo libfoo_jni.so:...
com_android_bar libbar_jni.so:...
This file is generated by linkerconfig.
Bug: 143733063
Test: cuttlestone boots
(For now, no behavioral changes because jni.config.txt is empty)
Change-Id: I066de90a73875118be53972e50d076061922d762
Diffstat (limited to 'libnativeloader/library_namespaces.cpp')
-rw-r--r-- | libnativeloader/library_namespaces.cpp | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp index dfbdefd53d..44b34583a6 100644 --- a/libnativeloader/library_namespaces.cpp +++ b/libnativeloader/library_namespaces.cpp @@ -26,6 +26,7 @@ #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/properties.h> +#include <android-base/result.h> #include <android-base/strings.h> #include <nativehelper/scoped_utf_chars.h> @@ -36,6 +37,9 @@ namespace android::nativeloader { namespace { + +constexpr const char* kApexPath = "/apex/"; + // The device may be configured to have the vendor libraries loaded to a separate namespace. // For historical reasons this namespace was named sphal but effectively it is intended // to use to load vendor libraries to separate namespace with controlled interface between @@ -94,23 +98,17 @@ jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) { return env->CallObjectMethod(class_loader, get_parent); } -ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) { +ApkOrigin GetApkOriginFromDexPath(const std::string& dex_path) { ApkOrigin apk_origin = APK_ORIGIN_DEFAULT; + if (std::regex_search(dex_path, kVendorDexPathRegex)) { + apk_origin = APK_ORIGIN_VENDOR; + } + if (std::regex_search(dex_path, kProductDexPathRegex)) { + LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR, + "Dex path contains both vendor and product partition : %s", + dex_path.c_str()); - if (dex_path != nullptr) { - ScopedUtfChars dex_path_utf_chars(env, dex_path); - - if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) { - apk_origin = APK_ORIGIN_VENDOR; - } - - if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) { - LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR, - "Dex path contains both vendor and product partition : %s", - dex_path_utf_chars.c_str()); - - apk_origin = APK_ORIGIN_PRODUCT; - } + apk_origin = APK_ORIGIN_PRODUCT; } return apk_origin; } @@ -141,17 +139,23 @@ void LibraryNamespaces::Initialize() { Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, - jstring dex_path, + jstring dex_path_j, jstring java_library_path, jstring java_permitted_path) { std::string library_path; // empty string by default. + std::string dex_path; if (java_library_path != nullptr) { ScopedUtfChars library_path_utf_chars(env, java_library_path); library_path = library_path_utf_chars.c_str(); } - ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path); + if (dex_path_j != nullptr) { + ScopedUtfChars dex_path_chars(env, dex_path_j); + dex_path = dex_path_chars.c_str(); + } + + ApkOrigin apk_origin = GetApkOriginFromDexPath(dex_path); // (http://b/27588281) This is a workaround for apps using custom // classloaders and calling System.load() with an absolute path which @@ -298,6 +302,20 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } + auto apex_ns_name = FindApexNamespaceName(dex_path); + if (apex_ns_name.ok()) { + const auto& jni_libs = apex_jni_libraries(*apex_ns_name); + if (jni_libs != "") { + auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged); + if (apex_ns.ok()) { + auto link = app_ns->Link(*apex_ns, jni_libs); + if (!link.ok()) { + return linked.error(); + } + } + } + } + // TODO(b/143733063): Remove it after library path of apex module is supported. auto cronet_ns = NativeLoaderNamespace::GetExportedNamespace(kCronetNamespaceName, is_bridged); @@ -367,4 +385,21 @@ NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEn return nullptr; } +base::Result<std::string> FindApexNamespaceName(const std::string& location) { + // Lots of implicit assumptions here: we expect `location` to be of the form: + // /apex/modulename/... + // + // And we extract from it 'modulename', and then apply mangling rule to get namespace name for it. + if (android::base::StartsWith(location, kApexPath)) { + size_t start_index = strlen(kApexPath); + size_t slash_index = location.find_first_of('/', start_index); + LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos), + "Error finding namespace of apex: no slash in path %s", location.c_str()); + std::string name = location.substr(start_index, slash_index - start_index); + std::replace(name.begin(), name.end(), '.', '_'); + return name; + } + return base::Error(); +} + } // namespace android::nativeloader |