• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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