diff options
author | 2022-01-06 14:09:00 +0000 | |
---|---|---|
committer | 2022-01-07 13:47:55 +0000 | |
commit | a2e3936e53ff326d201623b539ebcd12cecc4bee (patch) | |
tree | c519f71b235b8d9385d428506d46a6b369a2fe36 | |
parent | 0628e784532303b27e062ed957494bfd7e858bd9 (diff) |
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
-rw-r--r-- | libartbase/base/file_utils.cc | 12 | ||||
-rw-r--r-- | libartbase/base/file_utils.h | 4 | ||||
-rw-r--r-- | libartbase/base/file_utils_test.cc | 11 | ||||
-rw-r--r-- | odrefresh/odrefresh.cc | 32 | ||||
-rw-r--r-- | runtime/runtime.cc | 12 |
5 files changed, 54 insertions, 17 deletions
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc index 8159b0cf66..bc08f309bb 100644 --- a/libartbase/base/file_utils.cc +++ b/libartbase/base/file_utils.cc @@ -661,6 +661,18 @@ bool LocationIsOnApex(std::string_view full_path) { 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 d0d986b3ff..709ac12d14 100644 --- a/libartbase/base/file_utils.h +++ b/libartbase/base/file_utils.h @@ -168,6 +168,10 @@ bool LocationIsOnSystemExtFramework(std::string_view location); // 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 913eedee03..dff4478549 100644 --- a/libartbase/base/file_utils_test.cc +++ b/libartbase/base/file_utils_test.cc @@ -330,4 +330,15 @@ TEST_F(FileUtilsTest, GetSystemOdexFilenameForApex) { 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 d9c5f6f75c..ce80901643 100644 --- a/odrefresh/odrefresh.cc +++ b/odrefresh/odrefresh.cc @@ -583,11 +583,25 @@ std::optional<std::vector<apex::ApexInfo>> OnDeviceRefresh::GetApexInfoList() co 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 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate( 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 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate( 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 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate( } 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 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate( 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 64970e1f66..483e2abaf5 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1281,16 +1281,8 @@ static inline void CreatePreAllocatedException(Thread* self, 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); } } |