xref: /aosp_15_r20/art/odrefresh/odrefresh_main.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <string>
20*795d594fSAndroid Build Coastguard Worker #include <string_view>
21*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include "android-base/parsebool.h"
24*795d594fSAndroid Build Coastguard Worker #include "android-base/properties.h"
25*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
26*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
27*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
32*795d594fSAndroid Build Coastguard Worker #include "odr_common.h"
33*795d594fSAndroid Build Coastguard Worker #include "odr_compilation_log.h"
34*795d594fSAndroid Build Coastguard Worker #include "odr_config.h"
35*795d594fSAndroid Build Coastguard Worker #include "odr_metrics.h"
36*795d594fSAndroid Build Coastguard Worker #include "odrefresh.h"
37*795d594fSAndroid Build Coastguard Worker #include "odrefresh/odrefresh.h"
38*795d594fSAndroid Build Coastguard Worker #include "selinux/android.h"
39*795d594fSAndroid Build Coastguard Worker #include "selinux/selinux.h"
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker namespace {
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker using ::android::base::GetProperty;
44*795d594fSAndroid Build Coastguard Worker using ::android::base::ParseBool;
45*795d594fSAndroid Build Coastguard Worker using ::android::base::ParseBoolResult;
46*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::CompilationOptions;
47*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::ExitCode;
48*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::kCheckedSystemPropertyPrefixes;
49*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::kSystemProperties;
50*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::kSystemPropertySystemServerCompilerFilterOverride;
51*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::OdrCompilationLog;
52*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::OdrConfig;
53*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::OdrMetrics;
54*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::OnDeviceRefresh;
55*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::QuotePath;
56*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::ShouldDisablePartialCompilation;
57*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::ShouldDisableRefresh;
58*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::SystemPropertyConfig;
59*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::SystemPropertyForeach;
60*795d594fSAndroid Build Coastguard Worker using ::art::odrefresh::ZygoteKind;
61*795d594fSAndroid Build Coastguard Worker 
UsageMsgV(const char * fmt,va_list ap)62*795d594fSAndroid Build Coastguard Worker void UsageMsgV(const char* fmt, va_list ap) {
63*795d594fSAndroid Build Coastguard Worker   std::string error;
64*795d594fSAndroid Build Coastguard Worker   android::base::StringAppendV(&error, fmt, ap);
65*795d594fSAndroid Build Coastguard Worker   if (isatty(fileno(stderr))) {
66*795d594fSAndroid Build Coastguard Worker     std::cerr << error << std::endl;
67*795d594fSAndroid Build Coastguard Worker   } else {
68*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << error;
69*795d594fSAndroid Build Coastguard Worker   }
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker 
UsageMsg(const char * fmt,...)72*795d594fSAndroid Build Coastguard Worker void UsageMsg(const char* fmt, ...) {
73*795d594fSAndroid Build Coastguard Worker   va_list ap;
74*795d594fSAndroid Build Coastguard Worker   va_start(ap, fmt);
75*795d594fSAndroid Build Coastguard Worker   UsageMsgV(fmt, ap);
76*795d594fSAndroid Build Coastguard Worker   va_end(ap);
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker 
ArgumentError(const char * fmt,...)79*795d594fSAndroid Build Coastguard Worker NO_RETURN void ArgumentError(const char* fmt, ...) {
80*795d594fSAndroid Build Coastguard Worker   va_list ap;
81*795d594fSAndroid Build Coastguard Worker   va_start(ap, fmt);
82*795d594fSAndroid Build Coastguard Worker   UsageMsgV(fmt, ap);
83*795d594fSAndroid Build Coastguard Worker   va_end(ap);
84*795d594fSAndroid Build Coastguard Worker   UsageMsg("Try '--help' for more information.");
85*795d594fSAndroid Build Coastguard Worker   exit(EX_USAGE);
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker 
ParseZygoteKind(const char * input,ZygoteKind * zygote_kind)88*795d594fSAndroid Build Coastguard Worker bool ParseZygoteKind(const char* input, ZygoteKind* zygote_kind) {
89*795d594fSAndroid Build Coastguard Worker   std::string_view z(input);
90*795d594fSAndroid Build Coastguard Worker   if (z == "zygote32") {
91*795d594fSAndroid Build Coastguard Worker     *zygote_kind = ZygoteKind::kZygote32;
92*795d594fSAndroid Build Coastguard Worker     return true;
93*795d594fSAndroid Build Coastguard Worker   } else if (z == "zygote32_64") {
94*795d594fSAndroid Build Coastguard Worker     *zygote_kind = ZygoteKind::kZygote32_64;
95*795d594fSAndroid Build Coastguard Worker     return true;
96*795d594fSAndroid Build Coastguard Worker   } else if (z == "zygote64_32") {
97*795d594fSAndroid Build Coastguard Worker     *zygote_kind = ZygoteKind::kZygote64_32;
98*795d594fSAndroid Build Coastguard Worker     return true;
99*795d594fSAndroid Build Coastguard Worker   } else if (z == "zygote64") {
100*795d594fSAndroid Build Coastguard Worker     *zygote_kind = ZygoteKind::kZygote64;
101*795d594fSAndroid Build Coastguard Worker     return true;
102*795d594fSAndroid Build Coastguard Worker   }
103*795d594fSAndroid Build Coastguard Worker   return false;
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker 
GetEnvironmentVariableOrDie(const char * name)106*795d594fSAndroid Build Coastguard Worker std::string GetEnvironmentVariableOrDie(const char* name) {
107*795d594fSAndroid Build Coastguard Worker   const char* value = getenv(name);
108*795d594fSAndroid Build Coastguard Worker   LOG_ALWAYS_FATAL_IF(value == nullptr, "%s is not defined.", name);
109*795d594fSAndroid Build Coastguard Worker   return value;
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker 
GetEnvironmentVariableOrDefault(const char * name,std::string default_value)112*795d594fSAndroid Build Coastguard Worker std::string GetEnvironmentVariableOrDefault(const char* name, std::string default_value) {
113*795d594fSAndroid Build Coastguard Worker   const char* value = getenv(name);
114*795d594fSAndroid Build Coastguard Worker   if (value == nullptr) {
115*795d594fSAndroid Build Coastguard Worker     return default_value;
116*795d594fSAndroid Build Coastguard Worker   }
117*795d594fSAndroid Build Coastguard Worker   return value;
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker 
ArgumentMatches(std::string_view argument,std::string_view prefix,std::string * value)120*795d594fSAndroid Build Coastguard Worker bool ArgumentMatches(std::string_view argument, std::string_view prefix, std::string* value) {
121*795d594fSAndroid Build Coastguard Worker   if (argument.starts_with(prefix)) {
122*795d594fSAndroid Build Coastguard Worker     *value = std::string(argument.substr(prefix.size()));
123*795d594fSAndroid Build Coastguard Worker     return true;
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker   return false;
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker 
ArgumentEquals(std::string_view argument,std::string_view expected)128*795d594fSAndroid Build Coastguard Worker bool ArgumentEquals(std::string_view argument, std::string_view expected) {
129*795d594fSAndroid Build Coastguard Worker   return argument == expected;
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
InitializeConfig(int argc,char ** argv,OdrConfig * config)132*795d594fSAndroid Build Coastguard Worker int InitializeConfig(int argc, char** argv, OdrConfig* config) {
133*795d594fSAndroid Build Coastguard Worker   config->SetApexInfoListFile("/apex/apex-info-list.xml");
134*795d594fSAndroid Build Coastguard Worker   config->SetArtBinDir(art::GetArtBinDir());
135*795d594fSAndroid Build Coastguard Worker   config->SetBootClasspath(GetEnvironmentVariableOrDie("BOOTCLASSPATH"));
136*795d594fSAndroid Build Coastguard Worker   config->SetDex2oatBootclasspath(GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"));
137*795d594fSAndroid Build Coastguard Worker   config->SetSystemServerClasspath(GetEnvironmentVariableOrDie("SYSTEMSERVERCLASSPATH"));
138*795d594fSAndroid Build Coastguard Worker   config->SetStandaloneSystemServerJars(
139*795d594fSAndroid Build Coastguard Worker       GetEnvironmentVariableOrDefault("STANDALONE_SYSTEMSERVER_JARS", /*default_value=*/""));
140*795d594fSAndroid Build Coastguard Worker   config->SetIsa(art::kRuntimeISA);
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   std::string zygote;
143*795d594fSAndroid Build Coastguard Worker   int n = 1;
144*795d594fSAndroid Build Coastguard Worker   for (; n < argc - 1; ++n) {
145*795d594fSAndroid Build Coastguard Worker     const char* arg = argv[n];
146*795d594fSAndroid Build Coastguard Worker     std::string value;
147*795d594fSAndroid Build Coastguard Worker     if (ArgumentEquals(arg, "--compilation-os-mode")) {
148*795d594fSAndroid Build Coastguard Worker       config->SetCompilationOsMode(true);
149*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--dalvik-cache=", &value)) {
150*795d594fSAndroid Build Coastguard Worker       art::OverrideDalvikCacheSubDirectory(value);
151*795d594fSAndroid Build Coastguard Worker       config->SetArtifactDirectory(GetApexDataDalvikCacheDirectory(art::InstructionSet::kNone));
152*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--zygote-arch=", &value)) {
153*795d594fSAndroid Build Coastguard Worker       zygote = value;
154*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--boot-image-compiler-filter=", &value)) {
155*795d594fSAndroid Build Coastguard Worker       config->SetBootImageCompilerFilter(value);
156*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--system-server-compiler-filter=", &value)) {
157*795d594fSAndroid Build Coastguard Worker       config->SetSystemServerCompilerFilter(value);
158*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--staging-dir=", &value)) {
159*795d594fSAndroid Build Coastguard Worker       // Keep this for compatibility with CompOS in old platforms.
160*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "--staging-dir is deprecated and its value is ignored";
161*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentEquals(arg, "--dry-run")) {
162*795d594fSAndroid Build Coastguard Worker       config->SetDryRun();
163*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentMatches(arg, "--partial-compilation=", &value)) {
164*795d594fSAndroid Build Coastguard Worker       config->SetPartialCompilation(ParseBool(value) == ParseBoolResult::kTrue);
165*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentEquals(arg, "--no-refresh")) {
166*795d594fSAndroid Build Coastguard Worker       config->SetRefresh(false);
167*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentEquals(arg, "--minimal")) {
168*795d594fSAndroid Build Coastguard Worker       config->SetMinimal(true);
169*795d594fSAndroid Build Coastguard Worker     } else if (ArgumentEquals(arg, "--only-boot-images")) {
170*795d594fSAndroid Build Coastguard Worker       config->SetOnlyBootImages(true);
171*795d594fSAndroid Build Coastguard Worker     } else {
172*795d594fSAndroid Build Coastguard Worker       ArgumentError("Unrecognized argument: '%s'", arg);
173*795d594fSAndroid Build Coastguard Worker     }
174*795d594fSAndroid Build Coastguard Worker   }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker   if (zygote.empty()) {
177*795d594fSAndroid Build Coastguard Worker     // Use ro.zygote by default, if not overridden by --zygote-arch flag.
178*795d594fSAndroid Build Coastguard Worker     zygote = GetProperty("ro.zygote", {});
179*795d594fSAndroid Build Coastguard Worker   }
180*795d594fSAndroid Build Coastguard Worker   ZygoteKind zygote_kind;
181*795d594fSAndroid Build Coastguard Worker   if (!ParseZygoteKind(zygote.c_str(), &zygote_kind)) {
182*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unknown zygote: " << QuotePath(zygote);
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker   config->SetZygoteKind(zygote_kind);
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker   if (config->GetSystemServerCompilerFilter().empty()) {
187*795d594fSAndroid Build Coastguard Worker     std::string filter = GetProperty("dalvik.vm.systemservercompilerfilter", "");
188*795d594fSAndroid Build Coastguard Worker     filter = GetProperty(kSystemPropertySystemServerCompilerFilterOverride, filter);
189*795d594fSAndroid Build Coastguard Worker     config->SetSystemServerCompilerFilter(filter);
190*795d594fSAndroid Build Coastguard Worker   }
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker   if (!config->HasPartialCompilation() &&
193*795d594fSAndroid Build Coastguard Worker       ShouldDisablePartialCompilation(
194*795d594fSAndroid Build Coastguard Worker           GetProperty("ro.build.version.security_patch", /*default_value=*/""))) {
195*795d594fSAndroid Build Coastguard Worker     config->SetPartialCompilation(false);
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker   if (ShouldDisableRefresh(GetProperty("ro.build.version.sdk", /*default_value=*/""))) {
199*795d594fSAndroid Build Coastguard Worker     config->SetRefresh(false);
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   return n;
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker 
GetSystemProperties(std::unordered_map<std::string,std::string> * system_properties)205*795d594fSAndroid Build Coastguard Worker void GetSystemProperties(std::unordered_map<std::string, std::string>* system_properties) {
206*795d594fSAndroid Build Coastguard Worker   SystemPropertyForeach([&](std::string_view name, const char* value) {
207*795d594fSAndroid Build Coastguard Worker     if (strlen(value) == 0) {
208*795d594fSAndroid Build Coastguard Worker       return;
209*795d594fSAndroid Build Coastguard Worker     }
210*795d594fSAndroid Build Coastguard Worker     for (const char* prefix : kCheckedSystemPropertyPrefixes) {
211*795d594fSAndroid Build Coastguard Worker       if (name.starts_with(prefix)) {
212*795d594fSAndroid Build Coastguard Worker         (*system_properties)[std::string(name)] = value;
213*795d594fSAndroid Build Coastguard Worker       }
214*795d594fSAndroid Build Coastguard Worker     }
215*795d594fSAndroid Build Coastguard Worker   });
216*795d594fSAndroid Build Coastguard Worker   for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
217*795d594fSAndroid Build Coastguard Worker     (*system_properties)[system_property_config.name] =
218*795d594fSAndroid Build Coastguard Worker         GetProperty(system_property_config.name, system_property_config.default_value);
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker 
UsageHelp(const char * argv0)222*795d594fSAndroid Build Coastguard Worker NO_RETURN void UsageHelp(const char* argv0) {
223*795d594fSAndroid Build Coastguard Worker   std::string name(android::base::Basename(argv0));
224*795d594fSAndroid Build Coastguard Worker   UsageMsg("Usage: %s [OPTION...] ACTION", name.c_str());
225*795d594fSAndroid Build Coastguard Worker   UsageMsg("On-device refresh tool for boot classpath and system server");
226*795d594fSAndroid Build Coastguard Worker   UsageMsg("following an update of the ART APEX.");
227*795d594fSAndroid Build Coastguard Worker   UsageMsg("");
228*795d594fSAndroid Build Coastguard Worker   UsageMsg("Valid ACTION choices are:");
229*795d594fSAndroid Build Coastguard Worker   UsageMsg("");
230*795d594fSAndroid Build Coastguard Worker   UsageMsg("--check          Check compilation artifacts are up-to-date based on metadata.");
231*795d594fSAndroid Build Coastguard Worker   UsageMsg("--compile        Compile boot classpath and system_server jars when necessary.");
232*795d594fSAndroid Build Coastguard Worker   UsageMsg("--force-compile  Unconditionally compile the bootclass path and system_server jars.");
233*795d594fSAndroid Build Coastguard Worker   UsageMsg("--help           Display this help information.");
234*795d594fSAndroid Build Coastguard Worker   UsageMsg("");
235*795d594fSAndroid Build Coastguard Worker   UsageMsg("Available OPTIONs are:");
236*795d594fSAndroid Build Coastguard Worker   UsageMsg("");
237*795d594fSAndroid Build Coastguard Worker   UsageMsg("--dry-run");
238*795d594fSAndroid Build Coastguard Worker   UsageMsg("--partial-compilation            Only generate artifacts that are out-of-date or");
239*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 missing.");
240*795d594fSAndroid Build Coastguard Worker   UsageMsg("--no-refresh                     Do not refresh existing artifacts.");
241*795d594fSAndroid Build Coastguard Worker   UsageMsg("--compilation-os-mode            Indicate that odrefresh is running in Compilation");
242*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 OS.");
243*795d594fSAndroid Build Coastguard Worker   UsageMsg("--dalvik-cache=<DIR>             Write artifacts to .../<DIR> rather than");
244*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 .../dalvik-cache");
245*795d594fSAndroid Build Coastguard Worker   UsageMsg("--zygote-arch=<STRING>           Zygote kind that overrides ro.zygote");
246*795d594fSAndroid Build Coastguard Worker   UsageMsg("--boot-image-compiler-filter=<STRING>");
247*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 Compiler filter for the boot image. Default: ");
248*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 speed-profile");
249*795d594fSAndroid Build Coastguard Worker   UsageMsg("--system-server-compiler-filter=<STRING>");
250*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 Compiler filter that overrides");
251*795d594fSAndroid Build Coastguard Worker   UsageMsg("                                 dalvik.vm.systemservercompilerfilter");
252*795d594fSAndroid Build Coastguard Worker   UsageMsg("--minimal                        Generate a minimal boot image only.");
253*795d594fSAndroid Build Coastguard Worker   UsageMsg("--only-boot-images               Generate boot images only.");
254*795d594fSAndroid Build Coastguard Worker 
255*795d594fSAndroid Build Coastguard Worker   exit(EX_USAGE);
256*795d594fSAndroid Build Coastguard Worker }
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker }  // namespace
259*795d594fSAndroid Build Coastguard Worker 
main(int argc,char ** argv)260*795d594fSAndroid Build Coastguard Worker int main(int argc, char** argv) {
261*795d594fSAndroid Build Coastguard Worker   // odrefresh is launched by `init` which sets the umask of forked processed to
262*795d594fSAndroid Build Coastguard Worker   // 077 (S_IRWXG | S_IRWXO). This blocks the ability to make files and directories readable
263*795d594fSAndroid Build Coastguard Worker   // by others and prevents system_server from loading generated artifacts.
264*795d594fSAndroid Build Coastguard Worker   umask(S_IWGRP | S_IWOTH);
265*795d594fSAndroid Build Coastguard Worker 
266*795d594fSAndroid Build Coastguard Worker   // Explicitly initialize logging (b/201042799).
267*795d594fSAndroid Build Coastguard Worker   android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker   OdrConfig config(argv[0]);
270*795d594fSAndroid Build Coastguard Worker   int n = InitializeConfig(argc, argv, &config);
271*795d594fSAndroid Build Coastguard Worker 
272*795d594fSAndroid Build Coastguard Worker   art::MemMap::Init();  // Needed by DexFileLoader.
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker   argv += n;
275*795d594fSAndroid Build Coastguard Worker   argc -= n;
276*795d594fSAndroid Build Coastguard Worker   if (argc != 1) {
277*795d594fSAndroid Build Coastguard Worker     ArgumentError("Expected 1 argument, but have %d.", argc);
278*795d594fSAndroid Build Coastguard Worker   }
279*795d594fSAndroid Build Coastguard Worker 
280*795d594fSAndroid Build Coastguard Worker   GetSystemProperties(config.MutableSystemProperties());
281*795d594fSAndroid Build Coastguard Worker 
282*795d594fSAndroid Build Coastguard Worker   OdrMetrics metrics(config.GetArtifactDirectory());
283*795d594fSAndroid Build Coastguard Worker   OnDeviceRefresh odr(config, setfilecon, selinux_android_restorecon);
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   std::string_view action(argv[0]);
286*795d594fSAndroid Build Coastguard Worker   CompilationOptions compilation_options;
287*795d594fSAndroid Build Coastguard Worker   if (action == "--check") {
288*795d594fSAndroid Build Coastguard Worker     // Fast determination of whether artifacts are up to date.
289*795d594fSAndroid Build Coastguard Worker     ExitCode exit_code = odr.CheckArtifactsAreUpToDate(metrics, &compilation_options);
290*795d594fSAndroid Build Coastguard Worker     // Normally, `--check` should not write metrics. If compilation is not required, there's no need
291*795d594fSAndroid Build Coastguard Worker     // to write metrics; if compilation is required, `--compile` will write metrics. Therefore,
292*795d594fSAndroid Build Coastguard Worker     // `--check` should only write metrics when things went wrong.
293*795d594fSAndroid Build Coastguard Worker     metrics.SetEnabled(exit_code != ExitCode::kOkay && exit_code != ExitCode::kCompilationRequired);
294*795d594fSAndroid Build Coastguard Worker     return exit_code;
295*795d594fSAndroid Build Coastguard Worker   } else if (action == "--compile") {
296*795d594fSAndroid Build Coastguard Worker     ExitCode exit_code = odr.CheckArtifactsAreUpToDate(metrics, &compilation_options);
297*795d594fSAndroid Build Coastguard Worker     if (exit_code != ExitCode::kCompilationRequired) {
298*795d594fSAndroid Build Coastguard Worker       // No compilation required, so only write metrics when things went wrong.
299*795d594fSAndroid Build Coastguard Worker       metrics.SetEnabled(exit_code != ExitCode::kOkay);
300*795d594fSAndroid Build Coastguard Worker       return exit_code;
301*795d594fSAndroid Build Coastguard Worker     }
302*795d594fSAndroid Build Coastguard Worker     if (config.GetSystemProperties().GetBool("dalvik.vm.disable-odrefresh",
303*795d594fSAndroid Build Coastguard Worker                                              /*default_value=*/false)) {
304*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Compilation skipped because it's disabled by system property";
305*795d594fSAndroid Build Coastguard Worker       return ExitCode::kOkay;
306*795d594fSAndroid Build Coastguard Worker     }
307*795d594fSAndroid Build Coastguard Worker     OdrCompilationLog compilation_log;
308*795d594fSAndroid Build Coastguard Worker     if (!compilation_log.ShouldAttemptCompile(metrics.GetTrigger())) {
309*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Compilation skipped because it was attempted recently";
310*795d594fSAndroid Build Coastguard Worker       return ExitCode::kOkay;
311*795d594fSAndroid Build Coastguard Worker     }
312*795d594fSAndroid Build Coastguard Worker     // Compilation required, so always write metrics.
313*795d594fSAndroid Build Coastguard Worker     metrics.SetEnabled(true);
314*795d594fSAndroid Build Coastguard Worker     ExitCode compile_result = odr.Compile(metrics, compilation_options);
315*795d594fSAndroid Build Coastguard Worker     compilation_log.Log(metrics.GetArtApexVersion(),
316*795d594fSAndroid Build Coastguard Worker                         metrics.GetArtApexLastUpdateMillis(),
317*795d594fSAndroid Build Coastguard Worker                         metrics.GetTrigger(),
318*795d594fSAndroid Build Coastguard Worker                         compile_result);
319*795d594fSAndroid Build Coastguard Worker     return compile_result;
320*795d594fSAndroid Build Coastguard Worker   } else if (action == "--force-compile") {
321*795d594fSAndroid Build Coastguard Worker     // Clean-up existing files.
322*795d594fSAndroid Build Coastguard Worker     if (!odr.RemoveArtifactsDirectory()) {
323*795d594fSAndroid Build Coastguard Worker       metrics.SetStatus(OdrMetrics::Status::kIoError);
324*795d594fSAndroid Build Coastguard Worker       return ExitCode::kCleanupFailed;
325*795d594fSAndroid Build Coastguard Worker     }
326*795d594fSAndroid Build Coastguard Worker     return odr.Compile(metrics, CompilationOptions::CompileAll(odr));
327*795d594fSAndroid Build Coastguard Worker   } else if (action == "--help") {
328*795d594fSAndroid Build Coastguard Worker     UsageHelp(argv[0]);
329*795d594fSAndroid Build Coastguard Worker   } else {
330*795d594fSAndroid Build Coastguard Worker     ArgumentError("Unknown argument: %s", action.data());
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker }
333