diff --git a/init/init.cpp b/init/init.cpp index fd8ee0fe8..4955bc5f2 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -85,6 +85,10 @@ #include "system/core/init/property_service.pb.h" #include "util.h" +#ifndef RECOVERY +#include "com_android_apex.h" +#endif // RECOVERY + using namespace std::chrono_literals; using namespace std::string_literals; @@ -293,14 +297,58 @@ Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) { return parser; } +#ifndef RECOVERY +template +struct LibXmlErrorHandler { + T handler_; + template + LibXmlErrorHandler(Handler&& handler) : handler_(std::move(handler)) { + xmlSetGenericErrorFunc(nullptr, &ErrorHandler); + } + ~LibXmlErrorHandler() { xmlSetGenericErrorFunc(nullptr, nullptr); } + static void ErrorHandler(void*, const char* msg, ...) { + va_list args; + va_start(args, msg); + char* formatted; + if (vasprintf(&formatted, msg, args) >= 0) { + LOG(ERROR) << formatted; + } + free(formatted); + va_end(args); + } +}; + +template +LibXmlErrorHandler(Handler&&) -> LibXmlErrorHandler; +#endif // RECOVERY + // Returns a Parser that accepts scripts from APEX modules. It supports `service` and `on`. Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list) { Parser parser; - - parser.AddSectionParser( - "service", std::make_unique(&service_list, GetSubcontext(), std::nullopt, - /*from_apex=*/true)); - parser.AddSectionParser("on", std::make_unique(&action_manager, GetSubcontext())); + auto subcontext = GetSubcontext(); +#ifndef RECOVERY + if (subcontext) { + const auto apex_info_list_file = "/apex/apex-info-list.xml"; + auto error_handler = LibXmlErrorHandler([&](const auto& error_message) { + LOG(ERROR) << "Failed to read " << apex_info_list_file << ":" << error_message; + }); + const auto apex_info_list = com::android::apex::readApexInfoList(apex_info_list_file); + if (apex_info_list.has_value()) { + std::vector subcontext_apexes; + for (const auto& info : apex_info_list->getApexInfo()) { + if (info.hasPreinstalledModulePath() && + subcontext->PathMatchesSubcontext(info.getPreinstalledModulePath())) { + subcontext_apexes.push_back(info.getModuleName()); + } + } + subcontext->SetApexList(std::move(subcontext_apexes)); + } + } +#endif // RECOVERY + parser.AddSectionParser("service", + std::make_unique(&service_list, subcontext, std::nullopt, + /*from_apex=*/true)); + parser.AddSectionParser("on", std::make_unique(&action_manager, subcontext)); return parser; } diff --git a/init/subcontext.cpp b/init/subcontext.cpp index 7aa4a9d2c..bb3967e09 100644 --- a/init/subcontext.cpp +++ b/init/subcontext.cpp @@ -250,7 +250,14 @@ void Subcontext::Restart() { Fork(); } -bool Subcontext::PathMatchesSubcontext(const std::string& path) { +bool Subcontext::PathMatchesSubcontext(const std::string& path) const { + static const std::string kApexDir = "/apex/"; + if (StartsWith(path, kApexDir)) { + auto begin = kApexDir.size(); + auto end = path.find('/', begin); + auto apex_name = path.substr(begin, end - begin); + return std::find(apex_list_.begin(), apex_list_.end(), apex_name) != apex_list_.end(); + } for (const auto& prefix : path_prefixes_) { if (StartsWith(path, prefix)) { return true; @@ -259,6 +266,10 @@ bool Subcontext::PathMatchesSubcontext(const std::string& path) { return false; } +void Subcontext::SetApexList(std::vector&& apex_list) { + apex_list_ = std::move(apex_list); +} + Result Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) { if (auto result = SendMessage(socket_, subcontext_command); !result.ok()) { Restart(); diff --git a/init/subcontext.h b/init/subcontext.h index cb4138e69..8acc032d6 100644 --- a/init/subcontext.h +++ b/init/subcontext.h @@ -46,7 +46,8 @@ class Subcontext { Result Execute(const std::vector& args); Result> ExpandArgs(const std::vector& args); void Restart(); - bool PathMatchesSubcontext(const std::string& path); + bool PathMatchesSubcontext(const std::string& path) const; + void SetApexList(std::vector&& apex_list); const std::string& context() const { return context_; } pid_t pid() const { return pid_; } @@ -56,6 +57,7 @@ class Subcontext { Result TransmitMessage(const SubcontextCommand& subcontext_command); std::vector path_prefixes_; + std::vector apex_list_; std::string context_; pid_t pid_; android::base::unique_fd socket_;