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