using android::base::ErrnoError; using android::base::Result; using internal::ConfigEntry; using internal::ParseConfig; using internal::ParseApexLibrariesConfig;
void ReadExtensionLibraries(constchar* 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);
std::string_view fn = filename; if (android::base::ConsumePrefix(&fn, kExtendedPublicLibrariesFilePrefix) &&
android::base::ConsumeSuffix(&fn, kExtendedPublicLibrariesFileSuffix)) { const std::string company_name(fn); const std::string config_file_path = std::string(dirname) + std::string("/") + 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());
Result<std::vector<std::string>> ret = ReadConfig(
config_file_path, [&company_name](conststruct ConfigEntry& entry) -> Result<bool> { if (entry.soname.starts_with("lib") &&
entry.soname.ends_with("." + company_name + ".so")) { returntrue;
} else { return Errorf( "Library name \"{}\" does not start with \"lib\" and/or " "does not end with the company name \"{}\".",
entry.soname,
company_name);
}
}); if (ret.ok()) {
sonames->insert(sonames->end(), ret->begin(), ret->end());
} else {
LOG_ALWAYS_FATAL("Error reading extension library list: %s",
ret.error().message().c_str());
}
}
}
}
}
// If this is for preloading libs, don't remove the libs from APEXes. if (!for_preload) { // Remove the public libs provided by apexes because these libs are available // from apex namespaces. for (constauto& [_, library_list] : apex_public_libraries()) {
std::vector<std::string> public_libs = base::Split(library_list, ":");
sonames->erase(std::remove_if(sonames->begin(),
sonames->end(),
[&public_libs](const std::string& v) { return std::find(public_libs.begin(), public_libs.end(), v) !=
public_libs.end();
}),
sonames->end());
}
}
static std::string InitVendorPublicLibraries() { // This file is optional, quietly ignore if the file does not exist.
Result<std::vector<std::string>> sonames = ReadConfig(kVendorPublicLibrariesFile, always_true); if (!sonames.ok()) {
ALOGI("InitVendorPublicLibraries skipped: %s", sonames.error().message().c_str()); return"";
}
std::string libs = android::base::Join(*sonames, ':');
ALOGD("InitVendorPublicLibraries: %s", libs.c_str()); return libs;
}
// If ro.product.vndk.version is defined, /product/etc/public.libraries-<companyname>.txt contains // the product public libraries that are loaded from the product namespace. Otherwise, the file // contains the extended public libraries that are loaded from the system namespace. static std::string InitProductPublicLibraries() {
std::vector<std::string> sonames; if (is_product_treblelized()) {
ReadExtensionLibraries("/product/etc", &sonames);
}
std::string libs = android::base::Join(sonames, ':');
ALOGD("InitProductPublicLibraries: %s", libs.c_str()); return libs;
}
// 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 // system libs that are exposed to apps. The libs in the txt files must be // named as lib<name>.<companyname>.so. static std::string InitExtendedPublicLibraries() {
std::vector<std::string> sonames;
ReadExtensionLibraries("/system/etc", &sonames);
ReadExtensionLibraries("/system_ext/etc", &sonames); if (!is_product_treblelized()) {
ReadExtensionLibraries("/product/etc", &sonames);
}
std::string libs = android::base::Join(sonames, ':');
ALOGD("InitExtendedPublicLibraries: %s", libs.c_str()); return libs;
}
static std::string InitVndkspLibrariesVendor() { if (!IsVendorVndkEnabled()) {
ALOGD("InitVndkspLibrariesVendor: VNDK is deprecated with vendor"); return"";
}
bool is_product_treblelized() { #ifdefined(ART_TARGET_ANDROID) // Product is treblelized iff the sdk version is newer than U // or launching version is R or newer or ro.product.vndk.version is defined return android::modules::sdklevel::IsAtLeastV() ||
android::base::GetIntProperty("ro.product.first_api_level", 0) >= __ANDROID_API_R__ ||
android::sysprop::VndkProperties::product_vndk_version().has_value(); #else returnfalse; #endif
}
std::vector<std::string> sonames; for (std::string& line : lines) {
std::string trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue;
}
std::vector<std::string> tokens = android::base::Split(trimmed_line, " "); if (tokens.size() < 1 || tokens.size() > 3) { return Errorf("Malformed line \"{}\"", line);
} struct ConfigEntry entry = {.soname = "", .nopreload = false, .bitness = ALL};
size_t i = tokens.size(); while (i-- > 0) { if (tokens[i] == "nopreload") {
entry.nopreload = true;
} elseif (tokens[i] == "32" || tokens[i] == "64") { if (entry.bitness != ALL) { return Errorf("Malformed line \"{}\": bitness can be specified only once", line);
}
entry.bitness = tokens[i] == "32" ? ONLY_32 : ONLY_64;
} else { if (i != 0) { return Errorf("Malformed line \"{}\"", line);
}
entry.soname = tokens[i];
}
}
// skip 32-bit lib on 64-bit process and vice versa #ifdefined(__LP64__) if (entry.bitness == ONLY_32) continue; #else if (entry.bitness == ONLY_64) continue; #endif
// TODO(b/206676167): Remove this check when renderscript is officially removed. #ifdefined(__riscv) // skip renderscript lib on riscv target if (entry.soname == "libRS.so") continue; #endif
Result<bool> ret = filter_fn(entry); if (!ret.ok()) { return ret.error();
} if (*ret) { // filter_fn has returned true.
sonames.push_back(entry.soname);
}
} return sonames;
}
// Parses apex.libraries.config.txt file generated by linkerconfig which looks like // system/linkerconfig/testdata/golden_output/stages/apex.libraries.config.txt // and returns mapping of <apex namespace> to <library list> which matches <tag>. // // The file is line-based and each line consists of "<tag> <apex namespace> <library list>". // // <tag> explains what <library list> is. (e.g "jni", "public") // <library list> is colon-separated list of library names. (e.g "libfoo.so:libbar.so") // // If <tag> is "jni", <library list> is the list of JNI libraries exposed by <apex namespace>. // If <tag> is "public", <library list> is the list of public libraries exposed by <apex namespace>. // Public libraries are the libs listed in /system/etc/public.libraries.txt. // If <tag> is "vendor_public", <library list> is the list of vendor public libraries exposed by // <apex namespace>. Vendor public libraries are the libs listed in // /vendor/etc/public.libraries.txt.
Result<std::map<std::string, std::string>> ParseApexLibrariesConfig(const std::string& file_content, const std::string& tag) {
std::map<std::string, std::string> entries;
std::vector<std::string> lines = base::Split(file_content, "\n"); for (std::string& line : lines) {
std::string trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue;
}
Result<ApexLibrariesConfigLine> config_line = ParseApexLibrariesConfigLine(trimmed_line); if (!config_line.ok()) { return config_line.error();
} if (config_line->tag != tag) { continue;
}
entries[config_line->apex_namespace] = config_line->library_list;
} return entries;
}
} // namespace internal
} // namespace android::nativeloader
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.