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 37 namespace art { 38 namespace odrefresh { 39 40 // The prefixes of system properties that odrefresh keeps track of. Odrefresh will recompile 41 // everything if any property matching a prefix changes. 42 constexpr const char* kCheckedSystemPropertyPrefixes[]{"dalvik.vm.", "ro.dalvik.vm."}; 43 44 // System property for the phenotype flag to override the device or default-configured 45 // system server compiler filter setting. 46 static constexpr char kSystemPropertySystemServerCompilerFilterOverride[] = 47 "persist.device_config.runtime_native_boot.systemservercompilerfilter_override"; 48 49 // The list of system properties that odrefresh ignores. They don't affect compilation results. 50 const std::unordered_set<std::string> kIgnoredSystemProperties{ 51 "dalvik.vm.dex2oat-cpu-set", 52 "dalvik.vm.dex2oat-threads", 53 "dalvik.vm.boot-dex2oat-cpu-set", 54 "dalvik.vm.boot-dex2oat-threads", 55 "dalvik.vm.restore-dex2oat-cpu-set", 56 "dalvik.vm.restore-dex2oat-threads", 57 "dalvik.vm.background-dex2oat-cpu-set", 58 "dalvik.vm.background-dex2oat-threads"}; 59 60 struct SystemPropertyConfig { 61 const char* name; 62 const char* default_value; 63 }; 64 65 // The system properties that odrefresh keeps track of, in addition to the ones matching the 66 // prefixes in `kCheckedSystemPropertyPrefixes`. Odrefresh will recompile everything if any property 67 // changes. 68 // All phenotype flags under the `runtime_native_boot` namespace that affects the compiler's 69 // behavior must be explicitly listed below. We cannot use a prefix to match all phenotype flags 70 // because a default value is required for each flag. Changing the flag value from empty to the 71 // default value should not trigger re-compilation. This is to comply with the phenotype flag 72 // requirement (go/platform-experiments-flags#pre-requisites). 73 const android::base::NoDestructor<std::vector<SystemPropertyConfig>> kSystemProperties{ 74 {SystemPropertyConfig{.name = "persist.device_config.runtime_native_boot.enable_uffd_gc", 75 .default_value = ""}, 76 SystemPropertyConfig{.name = kPhDisableCompactDex, .default_value = "false"}, 77 SystemPropertyConfig{.name = kSystemPropertySystemServerCompilerFilterOverride, 78 .default_value = ""}}}; 79 80 // An enumeration of the possible zygote configurations on Android. 81 enum class ZygoteKind : uint8_t { 82 // 32-bit primary zygote, no secondary zygote. 83 kZygote32 = 0, 84 // 32-bit primary zygote, 64-bit secondary zygote. 85 kZygote32_64 = 1, 86 // 64-bit primary zygote, 32-bit secondary zygote. 87 kZygote64_32 = 2, 88 // 64-bit primary zygote, no secondary zygote. 89 kZygote64 = 3 90 }; 91 92 // Configuration class for odrefresh. Exists to enable abstracting environment variables and 93 // system properties into a configuration class for development and testing purposes. 94 class OdrConfig final { 95 private: 96 std::string apex_info_list_file_; 97 std::string art_bin_dir_; 98 std::string dex2oat_; 99 std::string dex2oat_boot_classpath_; 100 bool dry_run_; 101 std::optional<bool> refresh_; 102 std::optional<bool> partial_compilation_; 103 InstructionSet isa_; 104 std::string program_name_; 105 std::string system_server_classpath_; 106 std::string boot_image_compiler_filter_; 107 std::string system_server_compiler_filter_; 108 ZygoteKind zygote_kind_; 109 std::string boot_classpath_; 110 std::string artifact_dir_; 111 std::string standalone_system_server_jars_; 112 bool compilation_os_mode_ = false; 113 bool minimal_ = false; 114 115 // The current values of system properties listed in `kSystemProperties`. 116 std::unordered_map<std::string, std::string> system_properties_; 117 118 // Staging directory for artifacts. The directory must exist and will be automatically removed 119 // after compilation. If empty, use the default directory. 120 std::string staging_dir_; 121 122 public: OdrConfig(const char * program_name)123 explicit OdrConfig(const char* program_name) 124 : dry_run_(false), 125 isa_(InstructionSet::kNone), 126 program_name_(android::base::Basename(program_name)), 127 artifact_dir_(GetApexDataDalvikCacheDirectory(InstructionSet::kNone)) { 128 } 129 GetApexInfoListFile()130 const std::string& GetApexInfoListFile() const { return apex_info_list_file_; } 131 GetBootClasspathIsas()132 std::vector<InstructionSet> GetBootClasspathIsas() const { 133 const auto [isa32, isa64] = GetPotentialInstructionSets(); 134 switch (zygote_kind_) { 135 case ZygoteKind::kZygote32: 136 CHECK_NE(isa32, art::InstructionSet::kNone); 137 return {isa32}; 138 case ZygoteKind::kZygote32_64: 139 CHECK_NE(isa32, art::InstructionSet::kNone); 140 CHECK_NE(isa64, art::InstructionSet::kNone); 141 return {isa32, isa64}; 142 case ZygoteKind::kZygote64_32: 143 CHECK_NE(isa32, art::InstructionSet::kNone); 144 CHECK_NE(isa64, art::InstructionSet::kNone); 145 return {isa64, isa32}; 146 case ZygoteKind::kZygote64: 147 CHECK_NE(isa64, art::InstructionSet::kNone); 148 return {isa64}; 149 } 150 } 151 GetSystemServerIsa()152 InstructionSet GetSystemServerIsa() const { 153 const auto [isa32, isa64] = GetPotentialInstructionSets(); 154 switch (zygote_kind_) { 155 case ZygoteKind::kZygote32: 156 case ZygoteKind::kZygote32_64: 157 CHECK_NE(isa32, art::InstructionSet::kNone); 158 return isa32; 159 case ZygoteKind::kZygote64_32: 160 case ZygoteKind::kZygote64: 161 CHECK_NE(isa64, art::InstructionSet::kNone); 162 return isa64; 163 } 164 } 165 GetDex2oatBootClasspath()166 const std::string& GetDex2oatBootClasspath() const { return dex2oat_boot_classpath_; } 167 GetArtifactDirectory()168 const std::string& GetArtifactDirectory() const { return artifact_dir_; } 169 GetDex2Oat()170 std::string GetDex2Oat() const { 171 const char* prefix = UseDebugBinaries() ? "dex2oatd" : "dex2oat"; 172 const char* suffix = ""; 173 if (kIsTargetBuild) { 174 switch (zygote_kind_) { 175 case ZygoteKind::kZygote32: 176 suffix = "32"; 177 break; 178 case ZygoteKind::kZygote32_64: 179 case ZygoteKind::kZygote64_32: 180 case ZygoteKind::kZygote64: 181 suffix = "64"; 182 break; 183 } 184 } 185 return art_bin_dir_ + '/' + prefix + suffix; 186 } 187 GetDryRun()188 bool GetDryRun() const { return dry_run_; } HasPartialCompilation()189 bool HasPartialCompilation() const { 190 return partial_compilation_.has_value(); 191 } GetPartialCompilation()192 bool GetPartialCompilation() const { 193 return partial_compilation_.value_or(true); 194 } GetRefresh()195 bool GetRefresh() const { 196 return refresh_.value_or(true); 197 } GetSystemServerClasspath()198 const std::string& GetSystemServerClasspath() const { 199 return system_server_classpath_; 200 } GetBootImageCompilerFilter()201 const std::string& GetBootImageCompilerFilter() const { 202 return boot_image_compiler_filter_; 203 } GetSystemServerCompilerFilter()204 const std::string& GetSystemServerCompilerFilter() const { 205 return system_server_compiler_filter_; 206 } GetStagingDir()207 const std::string& GetStagingDir() const { 208 return staging_dir_; 209 } GetCompilationOsMode()210 bool GetCompilationOsMode() const { return compilation_os_mode_; } GetMinimal()211 bool GetMinimal() const { return minimal_; } GetSystemProperties()212 const std::unordered_map<std::string, std::string>& GetSystemProperties() const { 213 return system_properties_; 214 } 215 SetApexInfoListFile(const std::string & file_path)216 void SetApexInfoListFile(const std::string& file_path) { apex_info_list_file_ = file_path; } SetArtBinDir(const std::string & art_bin_dir)217 void SetArtBinDir(const std::string& art_bin_dir) { art_bin_dir_ = art_bin_dir; } 218 SetDex2oatBootclasspath(const std::string & classpath)219 void SetDex2oatBootclasspath(const std::string& classpath) { 220 dex2oat_boot_classpath_ = classpath; 221 } 222 SetArtifactDirectory(const std::string & artifact_dir)223 void SetArtifactDirectory(const std::string& artifact_dir) { 224 artifact_dir_ = artifact_dir; 225 } 226 SetDryRun()227 void SetDryRun() { dry_run_ = true; } SetPartialCompilation(bool value)228 void SetPartialCompilation(bool value) { 229 partial_compilation_ = value; 230 } SetRefresh(bool value)231 void SetRefresh(bool value) { 232 refresh_ = value; 233 } SetIsa(const InstructionSet isa)234 void SetIsa(const InstructionSet isa) { isa_ = isa; } 235 SetSystemServerClasspath(const std::string & classpath)236 void SetSystemServerClasspath(const std::string& classpath) { 237 system_server_classpath_ = classpath; 238 } 239 SetBootImageCompilerFilter(const std::string & filter)240 void SetBootImageCompilerFilter(const std::string& filter) { 241 boot_image_compiler_filter_ = filter; 242 } SetSystemServerCompilerFilter(const std::string & filter)243 void SetSystemServerCompilerFilter(const std::string& filter) { 244 system_server_compiler_filter_ = filter; 245 } 246 SetZygoteKind(ZygoteKind zygote_kind)247 void SetZygoteKind(ZygoteKind zygote_kind) { zygote_kind_ = zygote_kind; } 248 GetBootClasspath()249 const std::string& GetBootClasspath() const { return boot_classpath_; } 250 SetBootClasspath(const std::string & classpath)251 void SetBootClasspath(const std::string& classpath) { boot_classpath_ = classpath; } 252 SetStagingDir(const std::string & staging_dir)253 void SetStagingDir(const std::string& staging_dir) { 254 staging_dir_ = staging_dir; 255 } 256 GetStandaloneSystemServerJars()257 const std::string& GetStandaloneSystemServerJars() const { 258 return standalone_system_server_jars_; 259 } 260 SetStandaloneSystemServerJars(const std::string & jars)261 void SetStandaloneSystemServerJars(const std::string& jars) { 262 standalone_system_server_jars_ = jars; 263 } 264 SetCompilationOsMode(bool value)265 void SetCompilationOsMode(bool value) { compilation_os_mode_ = value; } 266 SetMinimal(bool value)267 void SetMinimal(bool value) { minimal_ = value; } 268 MutableSystemProperties()269 std::unordered_map<std::string, std::string>* MutableSystemProperties() { 270 return &system_properties_; 271 } 272 273 private: 274 // Returns a pair for the possible instruction sets for the configured instruction set 275 // architecture. The first item is the 32-bit architecture and the second item is the 64-bit 276 // architecture. The current `isa` is based on `kRuntimeISA` on target, odrefresh is compiled 277 // 32-bit by default so this method returns all options which are finessed based on the 278 // `ro.zygote` property. GetPotentialInstructionSets()279 std::pair<InstructionSet, InstructionSet> GetPotentialInstructionSets() const { 280 switch (isa_) { 281 case art::InstructionSet::kArm: 282 case art::InstructionSet::kArm64: 283 return std::make_pair(art::InstructionSet::kArm, art::InstructionSet::kArm64); 284 case art::InstructionSet::kX86: 285 case art::InstructionSet::kX86_64: 286 return std::make_pair(art::InstructionSet::kX86, art::InstructionSet::kX86_64); 287 case art::InstructionSet::kRiscv64: 288 return std::make_pair(art::InstructionSet::kNone, art::InstructionSet::kRiscv64); 289 case art::InstructionSet::kThumb2: 290 case art::InstructionSet::kNone: 291 LOG(FATAL) << "Invalid instruction set " << isa_; 292 return std::make_pair(art::InstructionSet::kNone, art::InstructionSet::kNone); 293 } 294 } 295 UseDebugBinaries()296 bool UseDebugBinaries() const { return program_name_ == "odrefreshd"; } 297 298 OdrConfig() = delete; 299 OdrConfig(const OdrConfig&) = delete; 300 OdrConfig& operator=(const OdrConfig&) = delete; 301 }; 302 303 } // namespace odrefresh 304 } // namespace art 305 306 #endif // ART_ODREFRESH_ODR_CONFIG_H_ 307