1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_ODREFRESH_ODR_CONFIG_H_ 18 #define ART_ODREFRESH_ODR_CONFIG_H_ 19 20 #include <algorithm> 21 #include <optional> 22 #include <string> 23 #include <unordered_map> 24 #include <unordered_set> 25 #include <vector> 26 27 #include "android-base/file.h" 28 #include "android-base/no_destructor.h" 29 #include "android-base/strings.h" 30 #include "arch/instruction_set.h" 31 #include "base/file_utils.h" 32 #include "base/globals.h" 33 #include "log/log.h" 34 #include "odr_common.h" 35 #include "odrefresh/odrefresh.h" 36 #include "tools/system_properties.h" 37 38 namespace art { 39 namespace odrefresh { 40 41 // The prefixes of system properties that odrefresh keeps track of. Odrefresh will recompile 42 // everything if any property matching a prefix changes. 43 constexpr const char* kCheckedSystemPropertyPrefixes[]{"dalvik.vm.", "ro.dalvik.vm."}; 44 45 // System property for the phenotype flag to override the device or default-configured 46 // system server compiler filter setting. 47 static constexpr char kSystemPropertySystemServerCompilerFilterOverride[] = 48 "persist.device_config.runtime_native_boot.systemservercompilerfilter_override"; 49 50 // The list of system properties that odrefresh ignores. They don't affect compilation results. 51 const std::unordered_set<std::string> kIgnoredSystemProperties{ 52 "dalvik.vm.dex2oat-cpu-set", 53 "dalvik.vm.dex2oat-threads", 54 "dalvik.vm.boot-dex2oat-cpu-set", 55 "dalvik.vm.boot-dex2oat-threads", 56 "dalvik.vm.restore-dex2oat-cpu-set", 57 "dalvik.vm.restore-dex2oat-threads", 58 "dalvik.vm.background-dex2oat-cpu-set", 59 "dalvik.vm.background-dex2oat-threads"}; 60 61 struct SystemPropertyConfig { 62 const char* name; 63 const char* default_value; 64 }; 65 66 // The system properties that odrefresh keeps track of, in addition to the ones matching the 67 // prefixes in `kCheckedSystemPropertyPrefixes`. Odrefresh will recompile everything if any property 68 // changes. 69 // All phenotype flags under the `runtime_native_boot` namespace that affects the compiler's 70 // behavior must be explicitly listed below. We cannot use a prefix to match all phenotype flags 71 // because a default value is required for each flag. Changing the flag value from empty to the 72 // default value should not trigger re-compilation. This is to comply with the phenotype flag 73 // requirement (go/platform-experiments-flags#pre-requisites). 74 const android::base::NoDestructor<std::vector<SystemPropertyConfig>> kSystemProperties{ 75 {SystemPropertyConfig{.name = "persist.device_config.runtime_native_boot.enable_uffd_gc_2", 76 .default_value = "false"}, 77 SystemPropertyConfig{.name = "persist.device_config.runtime_native_boot.force_disable_uffd_gc", 78 .default_value = "false"}, 79 SystemPropertyConfig{.name = kSystemPropertySystemServerCompilerFilterOverride, 80 .default_value = ""}, 81 // For testing only (cf. odsign_e2e_tests_full). 82 SystemPropertyConfig{.name = "persist.device_config.runtime_native_boot.odrefresh_test_toggle", 83 .default_value = "false"}}}; 84 85 // An enumeration of the possible zygote configurations on Android. 86 enum class ZygoteKind : uint8_t { 87 // 32-bit primary zygote, no secondary zygote. 88 kZygote32 = 0, 89 // 32-bit primary zygote, 64-bit secondary zygote. 90 kZygote32_64 = 1, 91 // 64-bit primary zygote, 32-bit secondary zygote. 92 kZygote64_32 = 2, 93 // 64-bit primary zygote, no secondary zygote. 94 kZygote64 = 3 95 }; 96 97 class OdrSystemProperties : public tools::SystemProperties { 98 public: OdrSystemProperties(const std::unordered_map<std::string,std::string> * system_properties)99 explicit OdrSystemProperties( 100 const std::unordered_map<std::string, std::string>* system_properties) 101 : system_properties_(system_properties) {} 102 103 // For supporting foreach loops. begin()104 auto begin() const { return system_properties_->begin(); } end()105 auto end() const { return system_properties_->end(); } 106 107 // Return a given property's value if it exists in the map. GetOrNull(const std::string & key)108 std::optional<std::string> GetOrNull(const std::string& key) const { 109 auto it = system_properties_->find(key); 110 return it != system_properties_->end() ? std::make_optional(it->second) : std::nullopt; 111 } 112 113 protected: GetProperty(const std::string & key)114 std::string GetProperty(const std::string& key) const override { 115 auto it = system_properties_->find(key); 116 return it != system_properties_->end() ? it->second : ""; 117 } 118 119 private: 120 const std::unordered_map<std::string, std::string>* system_properties_; 121 }; 122 123 // Configuration class for odrefresh. Exists to enable abstracting environment variables and 124 // system properties into a configuration class for development and testing purposes. 125 class OdrConfig final { 126 private: 127 std::string apex_info_list_file_; 128 std::string art_bin_dir_; 129 std::string dex2oat_; 130 std::string dex2oat_boot_classpath_; 131 bool dry_run_; 132 std::optional<bool> refresh_; 133 std::optional<bool> partial_compilation_; 134 InstructionSet isa_; 135 std::string program_name_; 136 std::string system_server_classpath_; 137 std::string boot_image_compiler_filter_; 138 std::string system_server_compiler_filter_; 139 ZygoteKind zygote_kind_; 140 std::string boot_classpath_; 141 std::string artifact_dir_; 142 std::string standalone_system_server_jars_; 143 bool compilation_os_mode_ = false; 144 bool minimal_ = false; 145 bool only_boot_images_ = false; 146 147 // The current values of system properties listed in `kSystemProperties`. 148 std::unordered_map<std::string, std::string> system_properties_; 149 150 // A helper for reading from `system_properties_`. 151 OdrSystemProperties odr_system_properties_; 152 153 public: OdrConfig(const char * program_name)154 explicit OdrConfig(const char* program_name) 155 : dry_run_(false), 156 isa_(InstructionSet::kNone), 157 program_name_(android::base::Basename(program_name)), 158 artifact_dir_(GetApexDataDalvikCacheDirectory(InstructionSet::kNone)), 159 odr_system_properties_(&system_properties_) {} 160 GetApexInfoListFile()161 const std::string& GetApexInfoListFile() const { return apex_info_list_file_; } 162 GetBootClasspathIsas()163 std::vector<InstructionSet> GetBootClasspathIsas() const { 164 const auto [isa32, isa64] = GetPotentialInstructionSets(); 165 switch (zygote_kind_) { 166 case ZygoteKind::kZygote32: 167 CHECK_NE(isa32, art::InstructionSet::kNone); 168 return {isa32}; 169 case ZygoteKind::kZygote32_64: 170 CHECK_NE(isa32, art::InstructionSet::kNone); 171 CHECK_NE(isa64, art::InstructionSet::kNone); 172 return {isa32, isa64}; 173 case ZygoteKind::kZygote64_32: 174 CHECK_NE(isa32, art::InstructionSet::kNone); 175 CHECK_NE(isa64, art::InstructionSet::kNone); 176 return {isa64, isa32}; 177 case ZygoteKind::kZygote64: 178 CHECK_NE(isa64, art::InstructionSet::kNone); 179 return {isa64}; 180 } 181 } 182 GetSystemServerIsa()183 InstructionSet GetSystemServerIsa() const { 184 const auto [isa32, isa64] = GetPotentialInstructionSets(); 185 switch (zygote_kind_) { 186 case ZygoteKind::kZygote32: 187 case ZygoteKind::kZygote32_64: 188 CHECK_NE(isa32, art::InstructionSet::kNone); 189 return isa32; 190 case ZygoteKind::kZygote64_32: 191 case ZygoteKind::kZygote64: 192 CHECK_NE(isa64, art::InstructionSet::kNone); 193 return isa64; 194 } 195 } 196 GetDex2oatBootClasspath()197 const std::string& GetDex2oatBootClasspath() const { return dex2oat_boot_classpath_; } 198 GetArtifactDirectory()199 const std::string& GetArtifactDirectory() const { return artifact_dir_; } 200 GetDex2Oat()201 std::string GetDex2Oat() const { 202 const char* prefix = UseDebugBinaries() ? "dex2oatd" : "dex2oat"; 203 const char* suffix = ""; 204 if (kIsTargetBuild) { 205 switch (zygote_kind_) { 206 case ZygoteKind::kZygote32: 207 suffix = "32"; 208 break; 209 case ZygoteKind::kZygote32_64: 210 case ZygoteKind::kZygote64_32: 211 case ZygoteKind::kZygote64: 212 suffix = "64"; 213 break; 214 } 215 } 216 return art_bin_dir_ + '/' + prefix + suffix; 217 } 218 GetDryRun()219 bool GetDryRun() const { return dry_run_; } HasPartialCompilation()220 bool HasPartialCompilation() const { 221 return partial_compilation_.has_value(); 222 } GetPartialCompilation()223 bool GetPartialCompilation() const { 224 return partial_compilation_.value_or(true); 225 } GetRefresh()226 bool GetRefresh() const { 227 return refresh_.value_or(true); 228 } GetSystemServerClasspath()229 const std::string& GetSystemServerClasspath() const { 230 return system_server_classpath_; 231 } GetBootImageCompilerFilter()232 const std::string& GetBootImageCompilerFilter() const { 233 return boot_image_compiler_filter_; 234 } GetSystemServerCompilerFilter()235 const std::string& GetSystemServerCompilerFilter() const { 236 return system_server_compiler_filter_; 237 } GetCompilationOsMode()238 bool GetCompilationOsMode() const { return compilation_os_mode_; } GetMinimal()239 bool GetMinimal() const { return minimal_; } GetOnlyBootImages()240 bool GetOnlyBootImages() const { return only_boot_images_; } GetSystemProperties()241 const OdrSystemProperties& GetSystemProperties() const { return odr_system_properties_; } 242 SetApexInfoListFile(const std::string & file_path)243 void SetApexInfoListFile(const std::string& file_path) { apex_info_list_file_ = file_path; } SetArtBinDir(const std::string & art_bin_dir)244 void SetArtBinDir(const std::string& art_bin_dir) { art_bin_dir_ = art_bin_dir; } 245 SetDex2oatBootclasspath(const std::string & classpath)246 void SetDex2oatBootclasspath(const std::string& classpath) { 247 dex2oat_boot_classpath_ = classpath; 248 } 249 SetArtifactDirectory(const std::string & artifact_dir)250 void SetArtifactDirectory(const std::string& artifact_dir) { 251 artifact_dir_ = artifact_dir; 252 } 253 SetDryRun()254 void SetDryRun() { dry_run_ = true; } SetPartialCompilation(bool value)255 void SetPartialCompilation(bool value) { 256 partial_compilation_ = value; 257 } SetRefresh(bool value)258 void SetRefresh(bool value) { 259 refresh_ = value; 260 } SetIsa(const InstructionSet isa)261 void SetIsa(const InstructionSet isa) { isa_ = isa; } 262 SetSystemServerClasspath(const std::string & classpath)263 void SetSystemServerClasspath(const std::string& classpath) { 264 system_server_classpath_ = classpath; 265 } 266 SetBootImageCompilerFilter(const std::string & filter)267 void SetBootImageCompilerFilter(const std::string& filter) { 268 boot_image_compiler_filter_ = filter; 269 } SetSystemServerCompilerFilter(const std::string & filter)270 void SetSystemServerCompilerFilter(const std::string& filter) { 271 system_server_compiler_filter_ = filter; 272 } 273 SetZygoteKind(ZygoteKind zygote_kind)274 void SetZygoteKind(ZygoteKind zygote_kind) { zygote_kind_ = zygote_kind; } 275 GetBootClasspath()276 const std::string& GetBootClasspath() const { return boot_classpath_; } 277 SetBootClasspath(const std::string & classpath)278 void SetBootClasspath(const std::string& classpath) { boot_classpath_ = classpath; } 279 GetStandaloneSystemServerJars()280 const std::string& GetStandaloneSystemServerJars() const { 281 return standalone_system_server_jars_; 282 } 283 SetStandaloneSystemServerJars(const std::string & jars)284 void SetStandaloneSystemServerJars(const std::string& jars) { 285 standalone_system_server_jars_ = jars; 286 } 287 SetCompilationOsMode(bool value)288 void SetCompilationOsMode(bool value) { compilation_os_mode_ = value; } 289 SetMinimal(bool value)290 void SetMinimal(bool value) { minimal_ = value; } 291 SetOnlyBootImages(bool value)292 void SetOnlyBootImages(bool value) { only_boot_images_ = value; } 293 MutableSystemProperties()294 std::unordered_map<std::string, std::string>* MutableSystemProperties() { 295 return &system_properties_; 296 } 297 298 private: 299 // Returns a pair for the possible instruction sets for the configured instruction set 300 // architecture. The first item is the 32-bit architecture and the second item is the 64-bit 301 // architecture. The current `isa` is based on `kRuntimeISA` on target, odrefresh is compiled 302 // 32-bit by default so this method returns all options which are finessed based on the 303 // `ro.zygote` property. GetPotentialInstructionSets()304 std::pair<InstructionSet, InstructionSet> GetPotentialInstructionSets() const { 305 switch (isa_) { 306 case art::InstructionSet::kArm: 307 case art::InstructionSet::kArm64: 308 return std::make_pair(art::InstructionSet::kArm, art::InstructionSet::kArm64); 309 case art::InstructionSet::kX86: 310 case art::InstructionSet::kX86_64: 311 return std::make_pair(art::InstructionSet::kX86, art::InstructionSet::kX86_64); 312 case art::InstructionSet::kRiscv64: 313 return std::make_pair(art::InstructionSet::kNone, art::InstructionSet::kRiscv64); 314 case art::InstructionSet::kThumb2: 315 case art::InstructionSet::kNone: 316 LOG(FATAL) << "Invalid instruction set " << isa_; 317 return std::make_pair(art::InstructionSet::kNone, art::InstructionSet::kNone); 318 } 319 } 320 UseDebugBinaries()321 bool UseDebugBinaries() const { return program_name_ == "odrefreshd"; } 322 323 OdrConfig() = delete; 324 OdrConfig(const OdrConfig&) = delete; 325 OdrConfig& operator=(const OdrConfig&) = delete; 326 }; 327 328 } // namespace odrefresh 329 } // namespace art 330 331 #endif // ART_ODREFRESH_ODR_CONFIG_H_ 332