Define product public libraries
When /product is unbundled from the /system, /product/etc/ may not
have 'public.libraries-<companyname>.txt' to extend public libraries.
Instead, /product/etc/public.library.txt can provide public libraries
from /product.
Bug: 186055799
Test: atest libnativeloader_test
Change-Id: I8994649826657f59ac1dac655205b9704a2c67c9
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
index 8b87338..585e98a 100644
--- a/libnativeloader/library_namespaces.cpp
+++ b/libnativeloader/library_namespaces.cpp
@@ -47,7 +47,12 @@
// to use to load vendor libraries to separate namespace with controlled interface between
// vendor and system namespaces.
constexpr const char* kVendorNamespaceName = "sphal";
+// Similar to sphal namespace, product namespace provides some product libraries.
+constexpr const char* kProductNamespaceName = "product";
+
+// vndk namespace for unbundled vendor apps
constexpr const char* kVndkNamespaceName = "vndk";
+// vndk_product namespace for unbundled product apps
constexpr const char* kVndkProductNamespaceName = "vndk_product";
// classloader-namespace is a linker namespace that is created for the loaded
@@ -374,6 +379,27 @@
}
}
+ auto product_libs = filter_public_libraries(target_sdk_version, uses_libraries,
+ product_public_libraries());
+ if (!product_libs.empty()) {
+ auto target_ns = system_ns;
+ if (is_product_vndk_version_defined()) {
+ // If ro.product.vndk.version is defined, product namespace provides the product libraries.
+ target_ns = NativeLoaderNamespace::GetExportedNamespace(kProductNamespaceName, is_bridged);
+ }
+ if (target_ns.ok()) {
+ linked = app_ns->Link(&target_ns.value(), product_libs);
+ if (!linked.ok()) {
+ return linked.error();
+ }
+ } else {
+ // The linkerconfig must have a problem on defining the product namespace in the system
+ // section. Skip linking product namespace. This will not affect most of the apps. Only the
+ // apps that requires the product public libraries will fail.
+ ALOGW("Namespace for product libs not found: %s", target_ns.error().message().c_str());
+ }
+ }
+
auto& emplaced = namespaces_.emplace_back(
std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
if (is_main_classloader) {
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
index c1dd4aa..878b9f8 100644
--- a/libnativeloader/native_loader_test.cpp
+++ b/libnativeloader/native_loader_test.cpp
@@ -190,6 +190,7 @@
bool expected_link_with_i18n_ns = true;
bool expected_link_with_conscrypt_ns = false;
bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
+ bool expected_link_with_product_ns = !product_public_libraries().empty();
bool expected_link_with_vndk_ns = false;
bool expected_link_with_vndk_product_ns = false;
bool expected_link_with_default_ns = false;
@@ -199,6 +200,7 @@
std::string expected_shared_libs_to_i18n_ns = apex_public_libraries().at("com_android_i18n");
std::string expected_shared_libs_to_conscrypt_ns = apex_jni_libraries("com_android_conscrypt");
std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
+ std::string expected_shared_libs_to_product_ns = product_public_libraries();
std::string expected_shared_libs_to_vndk_ns = vndksp_libraries_vendor();
std::string expected_shared_libs_to_vndk_product_ns = vndksp_libraries_product();
std::string expected_shared_libs_to_default_ns = default_public_libraries();
@@ -237,6 +239,11 @@
StrEq(expected_shared_libs_to_sphal_ns)))
.WillOnce(Return(true));
}
+ if (expected_link_with_product_ns) {
+ EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("product"),
+ StrEq(expected_shared_libs_to_product_ns)))
+ .WillOnce(Return(true));
+ }
if (expected_link_with_vndk_ns) {
EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk"),
StrEq(expected_shared_libs_to_vndk_ns)))
diff --git a/libnativeloader/native_loader_test.h b/libnativeloader/native_loader_test.h
index 09c56e5..5c51f00 100644
--- a/libnativeloader/native_loader_test.h
+++ b/libnativeloader/native_loader_test.h
@@ -87,6 +87,7 @@
NAMESPACE_ENTRY("default"),
NAMESPACE_ENTRY("sphal"),
+ NAMESPACE_ENTRY("product"),
NAMESPACE_ENTRY("system"),
NAMESPACE_ENTRY("vndk"),
NAMESPACE_ENTRY("vndk_product"),
diff --git a/libnativeloader/public_libraries.cpp b/libnativeloader/public_libraries.cpp
index 9d7124f..5571416 100644
--- a/libnativeloader/public_libraries.cpp
+++ b/libnativeloader/public_libraries.cpp
@@ -55,6 +55,7 @@
constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
constexpr const char* kApexLibrariesConfigFile = "/linkerconfig/apex.libraries.config.txt";
constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
+constexpr const char* kProductPublicLibrariesFile = "/product/etc/public.libraries.txt";
constexpr const char* kLlndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt";
constexpr const char* kVndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt";
@@ -185,6 +186,15 @@
return android::base::Join(*sonames, ':');
}
+static std::string InitProductPublicLibraries() {
+ // This file is optional, quietly ignore if the file does not exist.
+ auto sonames = ReadConfig(kProductPublicLibrariesFile, always_true);
+ if (!sonames.ok()) {
+ return "";
+ }
+ return android::base::Join(*sonames, ':');
+}
+
// read /system/etc/public.libraries-<companyname>.txt,
// /system_ext/etc/public.libraries-<companyname>.txt and
// /product/etc/public.libraries-<companyname>.txt which contain partner defined
@@ -194,7 +204,9 @@
std::vector<std::string> sonames;
ReadExtensionLibraries("/system/etc", &sonames);
ReadExtensionLibraries("/system_ext/etc", &sonames);
- ReadExtensionLibraries("/product/etc", &sonames);
+ if (!is_product_vndk_version_defined()) {
+ ReadExtensionLibraries("/product/etc", &sonames);
+ }
return android::base::Join(sonames, ':');
}
@@ -305,6 +317,11 @@
return list;
}
+const std::string& product_public_libraries() {
+ static std::string list = InitProductPublicLibraries();
+ return list;
+}
+
const std::string& extended_public_libraries() {
static std::string list = InitExtendedPublicLibraries();
return list;
diff --git a/libnativeloader/public_libraries.h b/libnativeloader/public_libraries.h
index 71c1b8f..6f5a13c 100644
--- a/libnativeloader/public_libraries.h
+++ b/libnativeloader/public_libraries.h
@@ -33,6 +33,7 @@
const std::string& preloadable_public_libraries();
const std::string& default_public_libraries();
const std::string& vendor_public_libraries();
+const std::string& product_public_libraries();
const std::string& extended_public_libraries();
const std::string& llndk_libraries_product();
const std::string& llndk_libraries_vendor();