xref: /aosp_15_r20/art/odrefresh/odr_config.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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