summaryrefslogtreecommitdiff
path: root/odrefresh/odrefresh.cc
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2022-05-04 14:34:01 +0100
committer TreeHugger Robot <treehugger-gerrit@google.com> 2022-05-06 17:42:49 +0000
commit45d0881f7444307955b51db5be88c5f890647c5e (patch)
treed7056c8087bda94c183cce4506c24966dd705e26 /odrefresh/odrefresh.cc
parent36c0cb0ed53420b65dd79c2cfaaf7f4a49e69ba7 (diff)
Re-compile on userfaultfd phenotype flag change.
After this change, odrefresh re-compiles everything when the phenotype flag `runtime_native_boot.enable_uffd_gc` changes. It writes the value of the flag to cache-info.xml for change detection. According to go/platform-experiment-namespaces#namespace-types, the phenotype flag is back by a persistent system property. Therefore, we can directly read the flag from the system property instead of depending on the `server_configurable_flags` library. This behavior is consistent with the existing ART code (particularly, `art::Flag`), which reads other phenotype flags. Bug: 231298279 Test: atest odsign_e2e_tests_full Ignore-AOSP-First: Merge conflict. Will cherry-pick later. Change-Id: I02b70569ecd96d4ded6d2d3be22c34b2c6a4c5b4
Diffstat (limited to 'odrefresh/odrefresh.cc')
-rw-r--r--odrefresh/odrefresh.cc134
1 files changed, 121 insertions, 13 deletions
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index 1d12b94fce..70cf48e918 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -648,6 +648,11 @@ Result<void> OnDeviceRefresh::WriteCacheInfo() const {
return Errorf("Could not create directory {}", QuotePath(dir_name));
}
+ std::vector<art_apex::KeyValuePair> system_properties;
+ for (const auto& [key, value] : config_.GetSystemProperties()) {
+ system_properties.emplace_back(key, value);
+ }
+
std::optional<std::vector<apex::ApexInfo>> apex_info_list = GetApexInfoList();
if (!apex_info_list.has_value()) {
return Errorf("Could not update {}: no APEX info", QuotePath(cache_info_filename_));
@@ -685,15 +690,16 @@ Result<void> OnDeviceRefresh::WriteCacheInfo() const {
return Errorf("Cannot open {} for writing.", QuotePath(cache_info_filename_));
}
- art_apex::CacheInfo info(
+ std::unique_ptr<art_apex::CacheInfo> info(new art_apex::CacheInfo(
+ {art_apex::KeyValuePairList(system_properties)},
{art_module_info},
{art_apex::ModuleInfoList(module_info_list)},
{art_apex::Classpath(bcp_components.value())},
{art_apex::Classpath(bcp_compilable_components.value())},
{art_apex::SystemServerComponents(system_server_components.value())},
- config_.GetCompilationOsMode() ? std::make_optional(true) : std::nullopt);
+ config_.GetCompilationOsMode() ? std::make_optional(true) : std::nullopt));
- art_apex::write(out, info);
+ art_apex::write(out, *info);
out.close();
if (out.fail()) {
return Errorf("Cannot write to {}", QuotePath(cache_info_filename_));
@@ -836,16 +842,106 @@ WARN_UNUSED bool OnDeviceRefresh::SystemServerArtifactsExist(
return jars_missing_artifacts->empty();
}
+WARN_UNUSED bool OnDeviceRefresh::CheckSystemPropertiesAreDefault() const {
+ const std::unordered_map<std::string, std::string>& system_properties =
+ config_.GetSystemProperties();
+
+ for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
+ auto property = system_properties.find(system_property_config.name);
+ DCHECK(property != system_properties.end());
+
+ if (property->second != system_property_config.default_value) {
+ LOG(INFO) << "System property " << system_property_config.name << " has a non-default value ("
+ << property->second << ").";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+WARN_UNUSED bool OnDeviceRefresh::CheckSystemPropertiesHaveNotChanged(
+ const art_apex::CacheInfo& cache_info) const {
+ std::unordered_map<std::string, std::string> cached_system_properties;
+ const art_apex::KeyValuePairList* list = cache_info.getFirstSystemProperties();
+ if (list == nullptr) {
+ // This should never happen. We have already checked the ART module version, and the cache
+ // info is generated by the latest version of the ART module if it exists.
+ LOG(ERROR) << "Missing system properties from cache-info.";
+ return false;
+ }
+
+ for (const art_apex::KeyValuePair& pair : list->getItem()) {
+ cached_system_properties[pair.getK()] = pair.getV();
+ }
+
+ const std::unordered_map<std::string, std::string>& system_properties =
+ config_.GetSystemProperties();
+
+ for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
+ auto property = system_properties.find(system_property_config.name);
+ DCHECK(property != system_properties.end());
+
+ auto cached_property = cached_system_properties.find(system_property_config.name);
+ if (cached_property == cached_system_properties.end()) {
+ // This should never happen. We have already checked the ART module version, and the cache
+ // info is generated by the latest version of the ART module if it exists.
+ LOG(ERROR) << "Missing system property from cache-info (" << system_property_config.name
+ << ")";
+ return false;
+ }
+
+ if (property->second != cached_property->second) {
+ LOG(INFO) << "System property " << system_property_config.name
+ << " value changed (before: " << cached_property->second
+ << ", now: " << property->second << ").";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+WARN_UNUSED bool OnDeviceRefresh::BootClasspathArtifactsOnSystemUsable(
+ const apex::ApexInfo& art_apex_info) const {
+ if (!art_apex_info.getIsFactory()) {
+ return false;
+ }
+ LOG(INFO) << "Factory ART APEX mounted.";
+
+ if (!CheckSystemPropertiesAreDefault()) {
+ return false;
+ }
+ LOG(INFO) << "System properties are set to default values.";
+
+ return true;
+}
+
+WARN_UNUSED bool OnDeviceRefresh::SystemServerArtifactsOnSystemUsable(
+ const std::vector<apex::ApexInfo>& apex_info_list) const {
+ if (std::any_of(apex_info_list.begin(),
+ apex_info_list.end(),
+ [](const apex::ApexInfo& apex_info) { return !apex_info.getIsFactory(); })) {
+ return false;
+ }
+ LOG(INFO) << "Factory APEXes mounted.";
+
+ if (!CheckSystemPropertiesAreDefault()) {
+ return false;
+ }
+ LOG(INFO) << "System properties are set to default values.";
+
+ return true;
+}
+
WARN_UNUSED bool OnDeviceRefresh::CheckBootClasspathArtifactsAreUpToDate(
OdrMetrics& metrics,
const InstructionSet isa,
const apex::ApexInfo& art_apex_info,
const std::optional<art_apex::CacheInfo>& cache_info,
/*out*/ std::vector<std::string>* checked_artifacts) const {
- if (art_apex_info.getIsFactory()) {
- LOG(INFO) << "Factory ART APEX mounted.";
-
- // ART is not updated, so we can use the artifacts on /system. Check if they exist.
+ if (BootClasspathArtifactsOnSystemUsable(art_apex_info)) {
+ // We can use the artifacts on /system. Check if they exist.
std::string error_msg;
if (BootClasspathArtifactsExist(/*on_system=*/true, /*minimal=*/false, isa, &error_msg)) {
return true;
@@ -900,6 +996,14 @@ WARN_UNUSED bool OnDeviceRefresh::CheckBootClasspathArtifactsAreUpToDate(
return false;
}
+ if (!CheckSystemPropertiesHaveNotChanged(cache_info.value())) {
+ // We don't have a trigger kind for system property changes. For now, we reuse
+ // `kApexVersionMismatch` as it implies the expected behavior: re-compile regardless of the last
+ // compilation attempt.
+ metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+ return false;
+ }
+
// Check boot class components.
//
// This checks the size and checksums of odrefresh compilable files on the DEX2OATBOOTCLASSPATH
@@ -961,12 +1065,8 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate(
std::set<std::string> jars_missing_artifacts_on_system;
bool artifacts_on_system_up_to_date = false;
- if (std::all_of(apex_info_list.begin(),
- apex_info_list.end(),
- [](const apex::ApexInfo& apex_info) { return apex_info.getIsFactory(); })) {
- LOG(INFO) << "Factory APEXes mounted.";
-
- // APEXes are not updated, so we can use the artifacts on /system. Check if they exist.
+ if (SystemServerArtifactsOnSystemUsable(apex_info_list)) {
+ // We can use the artifacts on /system. Check if they exist.
std::string error_msg;
if (SystemServerArtifactsExist(
/*on_system=*/true, &error_msg, &jars_missing_artifacts_on_system)) {
@@ -1052,6 +1152,14 @@ bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate(
}
}
+ if (!CheckSystemPropertiesHaveNotChanged(cache_info.value())) {
+ // We don't have a trigger kind for system property changes. For now, we reuse
+ // `kApexVersionMismatch` as it implies the expected behavior: re-compile regardless of the last
+ // compilation attempt.
+ metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+ return false;
+ }
+
// Check system server components.
//
// This checks the size and checksums of odrefresh compilable files on the