Ignore changes to irrelevant APEXes
When reading the list of APEXes, ignore any APEXes that do not contain
any compilable JARs. Changes to such APEXes now do not and should not
trigger recompilation.
This is helpful for the CompOS use case, since it doesn't even see
these APEXes.
As part of this, extract existing code to determine APEX name from
location and make it resuable.
Bug: 210473615
Test: atest art_standalone_libartbase_tests
Test: Presubmits
Change-Id: I3f64e6228f091cabce33a292058f960787780f62
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 8159b0c..bc08f30 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -661,6 +661,18 @@
return android::base::StartsWith(full_path, kApexDefaultPath);
}
+std::string_view ApexNameFromLocation(std::string_view full_path) {
+ if (!android::base::StartsWith(full_path, kApexDefaultPath)) {
+ return {};
+ }
+ size_t start = strlen(kApexDefaultPath);
+ size_t end = full_path.find('/', start);
+ if (end == std::string_view::npos) {
+ return {};
+ }
+ return full_path.substr(start, end - start);
+}
+
bool LocationIsOnSystem(const std::string& location) {
#ifdef _WIN32
UNUSED(location);
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index d0d986b..709ac12 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -168,6 +168,10 @@
// Return whether the location is on /apex/.
bool LocationIsOnApex(std::string_view location);
+// If the given location is /apex/<apexname>/..., return <apexname>, otherwise return an empty
+// string. Note that the result is a view into full_path and is valid only as long as it is.
+std::string_view ApexNameFromLocation(std::string_view full_path);
+
// Returns whether the location is trusted for loading oat files. Trusted locations are protected
// by dm-verity or fs-verity. The recognized locations are on /system or
// /data/misc/apexdata/com.android.art.
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index 913eede..dff4478 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -330,4 +330,15 @@
GetSystemOdexFilenameForApex(apex_jar.c_str(), InstructionSet::kArm));
}
+TEST_F(FileUtilsTest, ApexNameFromLocation) {
+ EXPECT_EQ("", ApexNameFromLocation(""));
+ EXPECT_EQ("", ApexNameFromLocation("/apex/com.android.foo"));
+ EXPECT_EQ("", ApexNameFromLocation("/apex//something"));
+ EXPECT_EQ("com.android.foo", ApexNameFromLocation("/apex/com.android.foo/"));
+ EXPECT_EQ("", ApexNameFromLocation("apex/com.android.foo/"));
+ EXPECT_EQ("foo", ApexNameFromLocation("/apex/foo/something.jar"));
+ EXPECT_EQ("", ApexNameFromLocation("/bar/foo/baz"));
+ EXPECT_EQ("", ApexNameFromLocation("/apexx/foo/baz"));
+}
+
} // namespace art
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index d9c5f6f..ce80901 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -583,11 +583,25 @@
return std::nullopt;
}
+ // We are only interested in active APEXes that contain compilable JARs.
+ std::unordered_set<std::string_view> relevant_apexes;
+ relevant_apexes.reserve(info_list->getApexInfo().size());
+ for (const std::vector<std::string>* jar_list : { &boot_extension_compilable_jars_,
+ &all_systemserver_jars_, &boot_classpath_jars_}) {
+ for (auto& jar : *jar_list) {
+ std::string_view apex = ApexNameFromLocation(jar);
+ if (!apex.empty()) {
+ relevant_apexes.insert(apex);
+ }
+ }
+ }
+
std::vector<apex::ApexInfo> filtered_info_list;
std::copy_if(info_list->getApexInfo().begin(),
info_list->getApexInfo().end(),
std::back_inserter(filtered_info_list),
- [](const apex::ApexInfo& info) { return info.getIsActive(); });
+ [&](const apex::ApexInfo& info) { return info.getIsActive()
+ && relevant_apexes.count(info.getModuleName()) != 0; });
return filtered_info_list;
}
@@ -914,11 +928,15 @@
cached_module_info_map[module_info.getName()] = &module_info;
}
+ // Note that apex_info_list may omit APEXes that are included in cached_module_info - e.g. if an
+ // apex used to be compilable, but now isn't. That won't be detected by this loop, but will be
+ // detected below in CheckComponents.
for (const apex::ApexInfo& current_apex_info : apex_info_list) {
- auto it = cached_module_info_map.find(current_apex_info.getModuleName());
+ auto& apex_name = current_apex_info.getModuleName();
+
+ auto it = cached_module_info_map.find(apex_name);
if (it == cached_module_info_map.end()) {
- LOG(INFO) << "Missing APEX info from cache-info (" << current_apex_info.getModuleName()
- << ").";
+ LOG(INFO) << "Missing APEX info from cache-info (" << apex_name << ").";
metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
return compile_all();
}
@@ -926,7 +944,7 @@
const art_apex::ModuleInfo* cached_module_info = it->second;
if (cached_module_info->getVersionCode() != current_apex_info.getVersionCode()) {
- LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") version code mismatch ("
+ LOG(INFO) << "APEX (" << apex_name << ") version code mismatch ("
<< cached_module_info->getVersionCode()
<< " != " << current_apex_info.getVersionCode() << ").";
metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
@@ -934,7 +952,7 @@
}
if (cached_module_info->getVersionName() != current_apex_info.getVersionName()) {
- LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") version name mismatch ("
+ LOG(INFO) << "APEX (" << apex_name << ") version name mismatch ("
<< cached_module_info->getVersionName()
<< " != " << current_apex_info.getVersionName() << ").";
metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
@@ -943,7 +961,7 @@
if (!cached_module_info->hasLastUpdateMillis() ||
cached_module_info->getLastUpdateMillis() != current_apex_info.getLastUpdateMillis()) {
- LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") last update time mismatch ("
+ LOG(INFO) << "APEX (" << apex_name << ") last update time mismatch ("
<< cached_module_info->getLastUpdateMillis()
<< " != " << current_apex_info.getLastUpdateMillis() << ").";
metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 64970e1..483e2ab 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1281,16 +1281,8 @@
void Runtime::InitializeApexVersions() {
std::vector<std::string_view> bcp_apexes;
for (std::string_view jar : Runtime::Current()->GetBootClassPathLocations()) {
- if (LocationIsOnApex(jar)) {
- size_t start = jar.find('/', 1);
- if (start == std::string::npos) {
- continue;
- }
- size_t end = jar.find('/', start + 1);
- if (end == std::string::npos) {
- continue;
- }
- std::string_view apex = jar.substr(start + 1, end - start - 1);
+ std::string_view apex = ApexNameFromLocation(jar);
+ if (!apex.empty()) {
bcp_apexes.push_back(apex);
}
}