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