Support product-specific libraries
Product-specific libraries in /product/lib can be exposed to Android apps by adding the list of the libs into /product/etc/public.libraries-<companyname>.txt. The libs MUST be named as lib<name>.<companyname>.so. Bug: 73095206 Test: with taimen mma -j and runtest.sh. The libs are all loaded in system, but not in vendor. After reinstalling app using adb -r and reopening app, only libraries listed in .txt are loaded Change-Id: I7c386813c72a7b225a7f244b6c5fec4ac0660fd3
This commit is contained in:
parent
a3d95cf2f8
commit
67cb05654c
|
@ -46,6 +46,8 @@
|
|||
"%s:%d: %s CHECK '" #predicate "' failed.",\
|
||||
__FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace android {
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
@ -236,10 +238,15 @@ class LibraryNamespaces {
|
|||
// Different name is useful for debugging
|
||||
namespace_name = kVendorClassloaderNamespaceName;
|
||||
ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str());
|
||||
} else if (!oem_public_libraries_.empty()) {
|
||||
// oem_public_libraries are NOT available to vendor apks, otherwise it
|
||||
} else {
|
||||
// oem and product public libraries are NOT available to vendor apks, otherwise it
|
||||
// would be system->vendor violation.
|
||||
system_exposed_libraries = system_exposed_libraries + ":" + oem_public_libraries_.c_str();
|
||||
if (!oem_public_libraries_.empty()) {
|
||||
system_exposed_libraries = system_exposed_libraries + ':' + oem_public_libraries_;
|
||||
}
|
||||
if (!product_public_libraries_.empty()) {
|
||||
system_exposed_libraries = system_exposed_libraries + ':' + product_public_libraries_;
|
||||
}
|
||||
}
|
||||
|
||||
NativeLoaderNamespace native_loader_ns;
|
||||
|
@ -351,6 +358,8 @@ class LibraryNamespaces {
|
|||
std::string vndksp_native_libraries_system_config =
|
||||
root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot;
|
||||
|
||||
std::string product_public_native_libraries_dir = "/product/etc";
|
||||
|
||||
std::string error_msg;
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
!ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg),
|
||||
|
@ -373,7 +382,7 @@ class LibraryNamespaces {
|
|||
//
|
||||
// TODO(dimitry): this is a bit misleading since we do not know
|
||||
// if the vendor public library is going to be opened from /vendor/lib
|
||||
// we might as well end up loading them from /system/lib
|
||||
// we might as well end up loading them from /system/lib or /product/lib
|
||||
// For now we rely on CTS test to catch things like this but
|
||||
// it should probably be addressed in the future.
|
||||
for (const auto& soname : sonames) {
|
||||
|
@ -387,48 +396,15 @@ class LibraryNamespaces {
|
|||
// system libs that are exposed to apps. The libs in the txt files must be
|
||||
// named as lib<name>.<companyname>.so.
|
||||
sonames.clear();
|
||||
std::string dirname = base::Dirname(public_native_libraries_system_config);
|
||||
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname.c_str()), closedir);
|
||||
if (dir != nullptr) {
|
||||
// Failing to opening the dir is not an error, which can happen in
|
||||
// webview_zygote.
|
||||
struct dirent* ent;
|
||||
while ((ent = readdir(dir.get())) != nullptr) {
|
||||
if (ent->d_type != DT_REG && ent->d_type != DT_LNK) {
|
||||
continue;
|
||||
}
|
||||
const std::string filename(ent->d_name);
|
||||
if (android::base::StartsWith(filename, kPublicNativeLibrariesExtensionConfigPrefix) &&
|
||||
android::base::EndsWith(filename, kPublicNativeLibrariesExtensionConfigSuffix)) {
|
||||
const size_t start = kPublicNativeLibrariesExtensionConfigPrefixLen;
|
||||
const size_t end = filename.size() - kPublicNativeLibrariesExtensionConfigSuffixLen;
|
||||
const std::string company_name = filename.substr(start, end - start);
|
||||
const std::string config_file_path = dirname + "/" + filename;
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
company_name.empty(),
|
||||
"Error extracting company name from public native library list file path \"%s\"",
|
||||
config_file_path.c_str());
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
!ReadConfig(
|
||||
config_file_path, &sonames,
|
||||
[&company_name](const std::string& soname, std::string* error_msg) {
|
||||
if (android::base::StartsWith(soname, "lib") &&
|
||||
android::base::EndsWith(soname, "." + company_name + ".so")) {
|
||||
return true;
|
||||
} else {
|
||||
*error_msg = "Library name \"" + soname +
|
||||
"\" does not end with the company name: " + company_name + ".";
|
||||
return false;
|
||||
}
|
||||
},
|
||||
&error_msg),
|
||||
"Error reading public native library list from \"%s\": %s", config_file_path.c_str(),
|
||||
error_msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
ReadExtensionLibraries(base::Dirname(public_native_libraries_system_config).c_str(), &sonames);
|
||||
oem_public_libraries_ = base::Join(sonames, ':');
|
||||
|
||||
// read /product/etc/public.libraries-<companyname>.txt which contain partner defined
|
||||
// product libs that are exposed to apps.
|
||||
sonames.clear();
|
||||
ReadExtensionLibraries(product_public_native_libraries_dir.c_str(), &sonames);
|
||||
product_public_libraries_ = base::Join(sonames, ':');
|
||||
|
||||
// Insert VNDK version to llndk and vndksp config file names.
|
||||
insert_vndk_version_str(&llndk_native_libraries_system_config);
|
||||
insert_vndk_version_str(&vndksp_native_libraries_system_config);
|
||||
|
@ -448,11 +424,54 @@ class LibraryNamespaces {
|
|||
vendor_public_libraries_ = base::Join(sonames, ':');
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
namespaces_.clear();
|
||||
}
|
||||
void Reset() { namespaces_.clear(); }
|
||||
|
||||
private:
|
||||
void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
|
||||
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
|
||||
if (dir != nullptr) {
|
||||
// Failing to opening the dir is not an error, which can happen in
|
||||
// webview_zygote.
|
||||
while (struct dirent* ent = readdir(dir.get())) {
|
||||
if (ent->d_type != DT_REG && ent->d_type != DT_LNK) {
|
||||
continue;
|
||||
}
|
||||
const std::string filename(ent->d_name);
|
||||
if (android::base::StartsWith(filename, kPublicNativeLibrariesExtensionConfigPrefix) &&
|
||||
android::base::EndsWith(filename, kPublicNativeLibrariesExtensionConfigSuffix)) {
|
||||
const size_t start = kPublicNativeLibrariesExtensionConfigPrefixLen;
|
||||
const size_t end = filename.size() - kPublicNativeLibrariesExtensionConfigSuffixLen;
|
||||
const std::string company_name = filename.substr(start, end - start);
|
||||
const std::string config_file_path = dirname + "/"s + filename;
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
company_name.empty(),
|
||||
"Error extracting company name from public native library list file path \"%s\"",
|
||||
config_file_path.c_str());
|
||||
|
||||
std::string error_msg;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
!ReadConfig(
|
||||
config_file_path, sonames,
|
||||
[&company_name](const std::string& soname, std::string* error_msg) {
|
||||
if (android::base::StartsWith(soname, "lib") &&
|
||||
android::base::EndsWith(soname, "." + company_name + ".so")) {
|
||||
return true;
|
||||
} else {
|
||||
*error_msg = "Library name \"" + soname +
|
||||
"\" does not end with the company name: " + company_name + ".";
|
||||
return false;
|
||||
}
|
||||
},
|
||||
&error_msg),
|
||||
"Error reading public native library list from \"%s\": %s", config_file_path.c_str(),
|
||||
error_msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
|
||||
const std::function<bool(const std::string& /* soname */,
|
||||
std::string* /* error_msg */)>& check_soname,
|
||||
|
@ -559,6 +578,7 @@ class LibraryNamespaces {
|
|||
std::string system_public_libraries_;
|
||||
std::string vendor_public_libraries_;
|
||||
std::string oem_public_libraries_;
|
||||
std::string product_public_libraries_;
|
||||
std::string system_llndk_libraries_;
|
||||
std::string system_vndksp_libraries_;
|
||||
|
||||
|
|
|
@ -49,3 +49,23 @@ cc_library {
|
|||
"libbase",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo.product1",
|
||||
srcs: ["test.cpp"],
|
||||
cflags: ["-DLIBNAME=\"libfoo.product1.so\""],
|
||||
product_specific: true,
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar.product1",
|
||||
srcs: ["test.cpp"],
|
||||
cflags: ["-DLIBNAME=\"libbar.product1.so\""],
|
||||
product_specific: true,
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -29,6 +29,13 @@ LOCAL_MODULE_CLASS := ETC
|
|||
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
|
||||
include $(BUILD_PREBUILT)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := public.libraries-product1.txt
|
||||
LOCAL_SRC_FILES:= $(LOCAL_MODULE)
|
||||
LOCAL_MODULE_CLASS := ETC
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)
|
||||
include $(BUILD_PREBUILT)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PACKAGE_NAME := oemlibrarytest-system
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
libfoo.product1.so
|
||||
libbar.product1.so
|
|
@ -29,6 +29,8 @@ public class TestActivity extends Activity {
|
|||
tryLoadingLib("bar.oem1");
|
||||
tryLoadingLib("foo.oem2");
|
||||
tryLoadingLib("bar.oem2");
|
||||
tryLoadingLib("foo.product1");
|
||||
tryLoadingLib("bar.product1");
|
||||
}
|
||||
|
||||
private void tryLoadingLib(String name) {
|
||||
|
|
|
@ -37,7 +37,8 @@ additional.namespaces = sphal,vndk,rs
|
|||
###############################################################################
|
||||
namespace.default.isolated = true
|
||||
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths += /product/${LIB}
|
||||
|
||||
# We can't have entire /system/${LIB} as permitted paths because doing so
|
||||
# makes it possible to load libs in /system/${LIB}/vndk* directories by
|
||||
|
@ -49,6 +50,7 @@ namespace.default.search.paths = /system/${LIB}
|
|||
namespace.default.permitted.paths = /system/${LIB}/drm
|
||||
namespace.default.permitted.paths += /system/${LIB}/extractors
|
||||
namespace.default.permitted.paths += /system/${LIB}/hw
|
||||
namespace.default.permitted.paths += /product/${LIB}
|
||||
# These are where odex files are located. libart has to be able to dlopen the files
|
||||
namespace.default.permitted.paths += /system/framework
|
||||
namespace.default.permitted.paths += /system/app
|
||||
|
@ -68,6 +70,8 @@ namespace.default.permitted.paths += /mnt/expand
|
|||
|
||||
namespace.default.asan.search.paths = /data/asan/system/${LIB}
|
||||
namespace.default.asan.search.paths += /system/${LIB}
|
||||
namespace.default.asan.search.paths += /data/asan/product/${LIB}
|
||||
namespace.default.asan.search.paths += /product/${LIB}
|
||||
|
||||
namespace.default.asan.permitted.paths = /data
|
||||
namespace.default.asan.permitted.paths += /system/${LIB}/drm
|
||||
|
@ -83,6 +87,7 @@ namespace.default.asan.permitted.paths += /odm/framework
|
|||
namespace.default.asan.permitted.paths += /odm/app
|
||||
namespace.default.asan.permitted.paths += /odm/priv-app
|
||||
namespace.default.asan.permitted.paths += /oem/app
|
||||
namespace.default.asan.permitted.paths += /product/${LIB}
|
||||
namespace.default.asan.permitted.paths += /product/framework
|
||||
namespace.default.asan.permitted.paths += /product/app
|
||||
namespace.default.asan.permitted.paths += /product/priv-app
|
||||
|
@ -320,10 +325,13 @@ namespace.vndk.link.default.allow_all_shared_libs = true
|
|||
###############################################################################
|
||||
namespace.system.isolated = false
|
||||
|
||||
namespace.system.search.paths = /system/${LIB}
|
||||
namespace.system.search.paths = /system/${LIB}
|
||||
namespace.system.search.paths += /product/${LIB}
|
||||
|
||||
namespace.system.asan.search.paths = /data/asan/system/${LIB}
|
||||
namespace.system.asan.search.paths += /system/${LIB}
|
||||
namespace.system.asan.search.paths += /data/asan/product/${LIB}
|
||||
namespace.system.asan.search.paths += /product/${LIB}
|
||||
|
||||
###############################################################################
|
||||
# Namespace config for binaries under /postinstall.
|
||||
|
@ -335,4 +343,5 @@ namespace.system.asan.search.paths += /system/${LIB}
|
|||
###############################################################################
|
||||
[postinstall]
|
||||
namespace.default.isolated = false
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths += /product/${LIB}
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace.default.isolated = false
|
|||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths += /odm/${LIB}
|
||||
namespace.default.search.paths += /vendor/${LIB}
|
||||
namespace.default.search.paths += /product/${LIB}
|
||||
|
||||
namespace.default.asan.search.paths = /data/asan/system/${LIB}
|
||||
namespace.default.asan.search.paths += /system/${LIB}
|
||||
|
@ -47,6 +48,8 @@ namespace.default.asan.search.paths += /data/asan/odm/${LIB}
|
|||
namespace.default.asan.search.paths += /odm/${LIB}
|
||||
namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
|
||||
namespace.default.asan.search.paths += /vendor/${LIB}
|
||||
namespace.default.asan.search.paths += /data/asan/product/${LIB}
|
||||
namespace.default.asan.search.paths += /product/${LIB}
|
||||
|
||||
###############################################################################
|
||||
# "sphal" namespace
|
||||
|
@ -205,6 +208,7 @@ namespace.default.search.paths += /vendor/${LIB}/vndk-sp
|
|||
namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
|
||||
namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
|
||||
namespace.default.search.paths += /system/${LIB}
|
||||
namespace.default.search.paths += /product/${LIB}
|
||||
|
||||
namespace.default.asan.search.paths = /data/asan/odm/${LIB}
|
||||
namespace.default.asan.search.paths += /odm/${LIB}
|
||||
|
@ -224,6 +228,8 @@ namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER
|
|||
namespace.default.asan.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
|
||||
namespace.default.asan.search.paths += /data/asan/system/${LIB}
|
||||
namespace.default.asan.search.paths += /system/${LIB}
|
||||
namespace.default.asan.search.paths += /data/asan/product/${LIB}
|
||||
namespace.default.asan.search.paths += /product/${LIB}
|
||||
|
||||
###############################################################################
|
||||
# Namespace config for binaries under /postinstall.
|
||||
|
@ -235,4 +241,5 @@ namespace.default.asan.search.paths += /system/${LIB}
|
|||
###############################################################################
|
||||
[postinstall]
|
||||
namespace.default.isolated = false
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths = /system/${LIB}
|
||||
namespace.default.search.paths += /product/${LIB}
|
||||
|
|
Loading…
Reference in New Issue