Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23d77410 authored by Kiyoung Kim's avatar Kiyoung Kim Committed by Gerrit Code Review
Browse files

Merge "Add product apk support from libnativeloader"

parents 59d4c8a3 4639f694
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -36,14 +36,9 @@ extern "C" {
__attribute__((visibility("default")))
void InitializeNativeLoader();

__attribute__((visibility("default")))
jstring CreateClassLoaderNamespace(JNIEnv* env,
                                   int32_t target_sdk_version,
                                   jobject class_loader,
                                   bool is_shared,
                                   bool is_for_vendor,
                                   jstring library_path,
                                   jstring permitted_path);
__attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
    JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
    jstring library_path, jstring permitted_path);

__attribute__((visibility("default"))) void* OpenNativeLibrary(
    JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
+79 −33
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <regex>
#include <string>
#include <vector>

@@ -140,10 +141,24 @@ static constexpr const char* kApexPath = "/apex/";

#if defined(__LP64__)
static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib64";
static constexpr const char* kVendorLibPath = "/vendor/lib64";
static constexpr const char* kProductLibPath = "/product/lib64:/system/product/lib64";
#else
static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib";
static constexpr const char* kVendorLibPath = "/vendor/lib";
static constexpr const char* kProductLibPath = "/product/lib:/system/product/lib";
#endif

static const std::regex kVendorDexPathRegex("(^|:)/vendor/");
static const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");

// Define origin of APK if it is from vendor partition or product partition
typedef enum {
  APK_ORIGIN_DEFAULT = 0,
  APK_ORIGIN_VENDOR = 1,
  APK_ORIGIN_PRODUCT = 2,
} ApkOrigin;

static bool is_debuggable() {
  bool debuggable = false;
#ifdef __BIONIC__
@@ -179,7 +194,7 @@ class LibraryNamespaces {
  LibraryNamespaces() : initialized_(false) { }

  NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
                                bool is_shared, bool is_for_vendor, jstring java_library_path,
                                bool is_shared, jstring dex_path, jstring java_library_path,
                                jstring java_permitted_path, std::string* error_msg) {
    std::string library_path; // empty string by default.

@@ -188,6 +203,8 @@ class LibraryNamespaces {
      library_path = library_path_utf_chars.c_str();
    }

    ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);

    // (http://b/27588281) This is a workaround for apps using custom
    // classloaders and calling System.load() with an absolute path which
    // is outside of the classloader library search path.
@@ -234,31 +251,50 @@ class LibraryNamespaces {
    std::string system_exposed_libraries = system_public_libraries_;
    const char* namespace_name = kClassloaderNamespaceName;
    android_namespace_t* vndk_ns = nullptr;
    if (is_for_vendor && !is_shared) {
      LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture");
    if ((apk_origin == APK_ORIGIN_VENDOR ||
         (apk_origin == APK_ORIGIN_PRODUCT && target_sdk_version > 29)) &&
        !is_shared) {
      LOG_FATAL_IF(is_native_bridge,
                   "Unbundled vendor / product apk must not use translated architecture");

      // For vendor apks, give access to the vendor lib even though
      // For vendor / product apks, give access to the vendor / product lib even though
      // they are treated as unbundled; the libs and apks are still bundled
      // together in the vendor partition.
#if defined(__LP64__)
      std::string vendor_lib_path = "/vendor/lib64";
#else
      std::string vendor_lib_path = "/vendor/lib";
#endif
      library_path = library_path + ":" + vendor_lib_path.c_str();
      permitted_path = permitted_path + ":" + vendor_lib_path.c_str();
      // together in the vendor / product partition.
      const char* origin_partition;
      const char* origin_lib_path;

      switch (apk_origin) {
        case APK_ORIGIN_VENDOR:
          origin_partition = "vendor";
          origin_lib_path = kVendorLibPath;
          break;
        case APK_ORIGIN_PRODUCT:
          origin_partition = "product";
          origin_lib_path = kProductLibPath;
          break;
        default:
          origin_partition = "unknown";
          origin_lib_path = "";
      }

      LOG_FATAL_IF(is_native_bridge, "Unbundled %s apk must not use translated architecture",
                   origin_partition);

      library_path = library_path + ":" + origin_lib_path;
      permitted_path = permitted_path + ":" + origin_lib_path;

      // Also give access to LLNDK libraries since they are available to vendors
      system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str();

      // Give access to VNDK-SP libraries from the 'vndk' namespace.
      vndk_ns = android_get_exported_namespace(kVndkNamespaceName);
      LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr,
                          "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName);
      LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr, "Cannot find \"%s\" namespace for %s apks",
                          kVndkNamespaceName, origin_partition);

      // Different name is useful for debugging
      namespace_name = kVendorClassloaderNamespaceName;
      ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str());
      ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
            origin_partition, library_path.c_str());
    } else {
      // oem and product public libraries are NOT available to vendor apks, otherwise it
      // would be system->vendor violation.
@@ -660,6 +696,28 @@ class LibraryNamespaces {
    return nullptr;
  }

  ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
    ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;

    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;
      }
    }

    return apk_origin;
  }

  bool initialized_;
  std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
  std::string system_public_libraries_;
@@ -690,31 +748,20 @@ void ResetNativeLoader() {
#endif
}

jstring CreateClassLoaderNamespace(JNIEnv* env,
                                   int32_t target_sdk_version,
                                   jobject class_loader,
                                   bool is_shared,
                                   bool is_for_vendor,
                                   jstring library_path,
jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
                                   bool is_shared, jstring dex_path, jstring library_path,
                                   jstring permitted_path) {
#if defined(__ANDROID__)
  std::lock_guard<std::mutex> guard(g_namespaces_mutex);

  std::string error_msg;
  bool success = g_namespaces->Create(env,
                                      target_sdk_version,
                                      class_loader,
                                      is_shared,
                                      is_for_vendor,
                                      library_path,
                                      permitted_path,
                                      &error_msg) != nullptr;
  bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
                                      library_path, permitted_path, &error_msg) != nullptr;
  if (!success) {
    return env->NewStringUTF(error_msg.c_str());
  }
#else
  UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor,
         library_path, permitted_path);
  UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
#endif
  return nullptr;
}
@@ -779,8 +826,7 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
    // In this case we create an isolated not-shared namespace for it.
    std::string create_error_msg;
    if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
                                   false /* is_for_vendor */, library_path, nullptr,
                                   &create_error_msg)) == nullptr) {
                                   nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
      *error_msg = strdup(create_error_msg.c_str());
      return nullptr;
    }
+2 −2
Original line number Diff line number Diff line
@@ -50,10 +50,10 @@ void InitializeNativeLoader() {
}

jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
                                   bool is_shared, bool is_for_vendor, jstring library_path,
                                   bool is_shared, jstring dex_path, jstring library_path,
                                   jstring permitted_path) {
  static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
  return f(env, target_sdk_version, class_loader, is_shared, is_for_vendor, library_path,
  return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
           permitted_path);
}