blob: 58ef28fdf7c32d1faf0fec3a83e9d4a6c4b564d4 [file] [log] [blame]
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +00001/*
2 * Copyright (C) 2020 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#include <sys/stat.h>
18
19#include <string>
20#include <string_view>
Jiakai Zhang45d08812022-05-04 14:34:01 +010021#include <unordered_map>
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000022
23#include "android-base/properties.h"
24#include "android-base/stringprintf.h"
25#include "android-base/strings.h"
26#include "arch/instruction_set.h"
27#include "base/file_utils.h"
28#include "base/globals.h"
29#include "odr_common.h"
30#include "odr_compilation_log.h"
31#include "odr_config.h"
32#include "odr_metrics.h"
33#include "odrefresh.h"
34#include "odrefresh/odrefresh.h"
35
36namespace {
37
Jiakai Zhang45d08812022-05-04 14:34:01 +010038using ::android::base::GetProperty;
Jiakai Zhangdff7de42022-05-13 18:47:09 +010039using ::android::base::StartsWith;
Jiakai Zhang83c38e22021-11-03 20:54:55 +000040using ::art::odrefresh::CompilationOptions;
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000041using ::art::odrefresh::ExitCode;
Jiakai Zhangdff7de42022-05-13 18:47:09 +010042using ::art::odrefresh::kCheckedSystemPropertyPrefixes;
Jiakai Zhang45d08812022-05-04 14:34:01 +010043using ::art::odrefresh::kSystemProperties;
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000044using ::art::odrefresh::OdrCompilationLog;
45using ::art::odrefresh::OdrConfig;
46using ::art::odrefresh::OdrMetrics;
47using ::art::odrefresh::OnDeviceRefresh;
48using ::art::odrefresh::QuotePath;
Jiakai Zhang38fd2542022-03-07 15:58:59 +000049using ::art::odrefresh::ShouldDisablePartialCompilation;
Jiakai Zhang39f6d002022-02-10 18:20:50 +000050using ::art::odrefresh::ShouldDisableRefresh;
Jiakai Zhang45d08812022-05-04 14:34:01 +010051using ::art::odrefresh::SystemPropertyConfig;
Jiakai Zhangdff7de42022-05-13 18:47:09 +010052using ::art::odrefresh::SystemPropertyForeach;
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000053using ::art::odrefresh::ZygoteKind;
54
Alan Stokesd98612e2022-01-10 17:59:01 +000055void UsageMsgV(const char* fmt, va_list ap) {
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000056 std::string error;
57 android::base::StringAppendV(&error, fmt, ap);
58 if (isatty(fileno(stderr))) {
59 std::cerr << error << std::endl;
60 } else {
61 LOG(ERROR) << error;
62 }
63}
64
Alan Stokesd98612e2022-01-10 17:59:01 +000065void UsageMsg(const char* fmt, ...) {
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000066 va_list ap;
67 va_start(ap, fmt);
Alan Stokesd98612e2022-01-10 17:59:01 +000068 UsageMsgV(fmt, ap);
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000069 va_end(ap);
70}
71
72NO_RETURN void ArgumentError(const char* fmt, ...) {
73 va_list ap;
74 va_start(ap, fmt);
Alan Stokesd98612e2022-01-10 17:59:01 +000075 UsageMsgV(fmt, ap);
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000076 va_end(ap);
Alan Stokesd98612e2022-01-10 17:59:01 +000077 UsageMsg("Try '--help' for more information.");
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000078 exit(EX_USAGE);
79}
80
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +000081bool ParseZygoteKind(const char* input, ZygoteKind* zygote_kind) {
82 std::string_view z(input);
83 if (z == "zygote32") {
84 *zygote_kind = ZygoteKind::kZygote32;
85 return true;
86 } else if (z == "zygote32_64") {
87 *zygote_kind = ZygoteKind::kZygote32_64;
88 return true;
89 } else if (z == "zygote64_32") {
90 *zygote_kind = ZygoteKind::kZygote64_32;
91 return true;
92 } else if (z == "zygote64") {
93 *zygote_kind = ZygoteKind::kZygote64;
94 return true;
95 }
96 return false;
97}
98
99std::string GetEnvironmentVariableOrDie(const char* name) {
100 const char* value = getenv(name);
101 LOG_ALWAYS_FATAL_IF(value == nullptr, "%s is not defined.", name);
102 return value;
103}
104
Jiakai Zhang9b7ddf62021-11-01 11:36:52 +0000105std::string GetEnvironmentVariableOrDefault(const char* name, std::string default_value) {
106 const char* value = getenv(name);
107 if (value == nullptr) {
108 return default_value;
109 }
110 return value;
111}
112
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000113bool ArgumentMatches(std::string_view argument, std::string_view prefix, std::string* value) {
114 if (android::base::StartsWith(argument, prefix)) {
115 *value = std::string(argument.substr(prefix.size()));
116 return true;
117 }
118 return false;
119}
120
121bool ArgumentEquals(std::string_view argument, std::string_view expected) {
122 return argument == expected;
123}
124
Jiakai Zhangfcdc7cf2022-01-07 14:40:26 +0000125int InitializeConfig(int argc, char** argv, OdrConfig* config) {
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000126 config->SetApexInfoListFile("/apex/apex-info-list.xml");
127 config->SetArtBinDir(art::GetArtBinDir());
128 config->SetBootClasspath(GetEnvironmentVariableOrDie("BOOTCLASSPATH"));
129 config->SetDex2oatBootclasspath(GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"));
130 config->SetSystemServerClasspath(GetEnvironmentVariableOrDie("SYSTEMSERVERCLASSPATH"));
Jiakai Zhang9b7ddf62021-11-01 11:36:52 +0000131 config->SetStandaloneSystemServerJars(
132 GetEnvironmentVariableOrDefault("STANDALONE_SYSTEMSERVER_JARS", /*default_value=*/""));
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000133 config->SetIsa(art::kRuntimeISA);
134
Victor Hsieh3644cb42021-11-16 10:49:28 -0800135 std::string zygote;
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000136 int n = 1;
137 for (; n < argc - 1; ++n) {
138 const char* arg = argv[n];
139 std::string value;
Victor Hsiehd0d10852022-01-04 16:17:13 -0800140 if (ArgumentEquals(arg, "--compilation-os-mode")) {
Jiakai Zhang34dcce52022-01-07 16:45:11 +0000141 config->SetCompilationOsMode(true);
Alan Stokesd4d21bf2021-10-13 11:07:25 +0100142 } else if (ArgumentMatches(arg, "--dalvik-cache=", &value)) {
143 art::OverrideDalvikCacheSubDirectory(value);
Alan Stokes1f8d2612021-12-14 14:27:45 +0000144 config->SetArtifactDirectory(GetApexDataDalvikCacheDirectory(art::InstructionSet::kNone));
Victor Hsieh3644cb42021-11-16 10:49:28 -0800145 } else if (ArgumentMatches(arg, "--zygote-arch=", &value)) {
146 zygote = value;
Victor Hsieha39356a2021-12-16 11:40:39 -0800147 } else if (ArgumentMatches(arg, "--system-server-compiler-filter=", &value)) {
148 config->SetSystemServerCompilerFilter(value);
Victor Hsieh27a740c2021-11-18 13:35:41 -0800149 } else if (ArgumentMatches(arg, "--staging-dir=", &value)) {
150 config->SetStagingDir(value);
Jiakai Zhangfcdc7cf2022-01-07 14:40:26 +0000151 } else if (ArgumentEquals(arg, "--dry-run")) {
152 config->SetDryRun();
153 } else if (ArgumentEquals(arg, "--partial-compilation")) {
154 config->SetPartialCompilation(true);
155 } else if (ArgumentEquals(arg, "--no-refresh")) {
156 config->SetRefresh(false);
Jiakai Zhang8046b622022-01-28 21:40:17 +0000157 } else if (ArgumentEquals(arg, "--minimal")) {
158 config->SetMinimal(true);
Jiakai Zhangfcdc7cf2022-01-07 14:40:26 +0000159 } else {
Alan Stokesd98612e2022-01-10 17:59:01 +0000160 ArgumentError("Unrecognized argument: '%s'", arg);
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000161 }
162 }
Victor Hsieh3644cb42021-11-16 10:49:28 -0800163
164 if (zygote.empty()) {
165 // Use ro.zygote by default, if not overridden by --zygote-arch flag.
Jiakai Zhang45d08812022-05-04 14:34:01 +0100166 zygote = GetProperty("ro.zygote", {});
Victor Hsieh3644cb42021-11-16 10:49:28 -0800167 }
168 ZygoteKind zygote_kind;
169 if (!ParseZygoteKind(zygote.c_str(), &zygote_kind)) {
170 LOG(FATAL) << "Unknown zygote: " << QuotePath(zygote);
171 }
172 config->SetZygoteKind(zygote_kind);
173
Victor Hsieha39356a2021-12-16 11:40:39 -0800174 if (config->GetSystemServerCompilerFilter().empty()) {
Jiakai Zhang45d08812022-05-04 14:34:01 +0100175 std::string filter = GetProperty("dalvik.vm.systemservercompilerfilter", "speed");
Victor Hsieha39356a2021-12-16 11:40:39 -0800176 config->SetSystemServerCompilerFilter(filter);
177 }
178
Jiakai Zhang38fd2542022-03-07 15:58:59 +0000179 if (!config->HasPartialCompilation() &&
180 ShouldDisablePartialCompilation(
Jiakai Zhang45d08812022-05-04 14:34:01 +0100181 GetProperty("ro.build.version.security_patch", /*default_value=*/""))) {
Jiakai Zhang38fd2542022-03-07 15:58:59 +0000182 config->SetPartialCompilation(false);
183 }
184
Jiakai Zhang45d08812022-05-04 14:34:01 +0100185 if (ShouldDisableRefresh(GetProperty("ro.build.version.sdk", /*default_value=*/""))) {
Jiakai Zhang39f6d002022-02-10 18:20:50 +0000186 config->SetRefresh(false);
187 }
188
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000189 return n;
190}
191
Jiakai Zhang45d08812022-05-04 14:34:01 +0100192void GetSystemProperties(std::unordered_map<std::string, std::string>* system_properties) {
Jiakai Zhangdff7de42022-05-13 18:47:09 +0100193 SystemPropertyForeach([&](const char* name, const char* value) {
194 if (strlen(value) == 0) {
195 return;
196 }
197 for (const char* prefix : kCheckedSystemPropertyPrefixes) {
198 if (StartsWith(name, prefix)) {
199 (*system_properties)[name] = value;
200 }
201 }
202 });
Jiakai Zhang45d08812022-05-04 14:34:01 +0100203 for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
204 (*system_properties)[system_property_config.name] =
205 GetProperty(system_property_config.name, system_property_config.default_value);
206 }
207}
208
Alan Stokesd4d21bf2021-10-13 11:07:25 +0100209NO_RETURN void UsageHelp(const char* argv0) {
210 std::string name(android::base::Basename(argv0));
Alan Stokesd98612e2022-01-10 17:59:01 +0000211 UsageMsg("Usage: %s [OPTION...] ACTION", name.c_str());
Jiakai Zhang884e22f2021-12-23 20:04:46 +0000212 UsageMsg("On-device refresh tool for boot classpath and system server");
Alan Stokesd98612e2022-01-10 17:59:01 +0000213 UsageMsg("following an update of the ART APEX.");
214 UsageMsg("");
215 UsageMsg("Valid ACTION choices are:");
216 UsageMsg("");
217 UsageMsg("--check Check compilation artifacts are up-to-date based on metadata.");
Jiakai Zhang884e22f2021-12-23 20:04:46 +0000218 UsageMsg("--compile Compile boot classpath and system_server jars when necessary.");
219 UsageMsg("--force-compile Unconditionally compile the bootclass path and system_server jars.");
Alan Stokesd98612e2022-01-10 17:59:01 +0000220 UsageMsg("--help Display this help information.");
221 UsageMsg("");
222 UsageMsg("Available OPTIONs are:");
223 UsageMsg("");
224 UsageMsg("--dry-run");
225 UsageMsg("--partial-compilation Only generate artifacts that are out-of-date or");
226 UsageMsg(" missing.");
227 UsageMsg("--no-refresh Do not refresh existing artifacts.");
Alan Stokesd98612e2022-01-10 17:59:01 +0000228 UsageMsg("--compilation-os-mode Indicate that odrefresh is running in Compilation");
229 UsageMsg(" OS.");
230 UsageMsg("--dalvik-cache=<DIR> Write artifacts to .../<DIR> rather than");
231 UsageMsg(" .../dalvik-cache");
Alan Stokesd98612e2022-01-10 17:59:01 +0000232 UsageMsg("--staging-dir=<DIR> Write temporary artifacts to <DIR> rather than");
233 UsageMsg(" .../staging");
234 UsageMsg("--zygote-arch=<STRING> Zygote kind that overrides ro.zygote");
235 UsageMsg("--system-server-compiler-filter=<STRING>");
236 UsageMsg(" Compiler filter that overrides");
237 UsageMsg(" dalvik.vm.systemservercompilerfilter");
Jiakai Zhang8046b622022-01-28 21:40:17 +0000238 UsageMsg("--minimal Generate a minimal boot image only.");
Alan Stokesd4d21bf2021-10-13 11:07:25 +0100239
240 exit(EX_USAGE);
241}
242
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000243} // namespace
244
Orion Hodsona182c932021-09-27 13:51:22 +0100245int main(int argc, char** argv) {
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000246 // odrefresh is launched by `init` which sets the umask of forked processed to
247 // 077 (S_IRWXG | S_IRWXO). This blocks the ability to make files and directories readable
248 // by others and prevents system_server from loading generated artifacts.
249 umask(S_IWGRP | S_IWOTH);
250
Orion Hodsona182c932021-09-27 13:51:22 +0100251 // Explicitly initialize logging (b/201042799).
252 android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
253
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000254 OdrConfig config(argv[0]);
255 int n = InitializeConfig(argc, argv, &config);
256 argv += n;
257 argc -= n;
258 if (argc != 1) {
Alan Stokesd98612e2022-01-10 17:59:01 +0000259 ArgumentError("Expected 1 argument, but have %d.", argc);
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000260 }
Jiakai Zhang45d08812022-05-04 14:34:01 +0100261 GetSystemProperties(config.MutableSystemProperties());
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000262
Alan Stokesd4d21bf2021-10-13 11:07:25 +0100263 OdrMetrics metrics(config.GetArtifactDirectory());
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000264 OnDeviceRefresh odr(config);
Victor Hsieh08e9f5f2021-12-16 10:22:02 -0800265
266 std::string_view action(argv[0]);
267 CompilationOptions compilation_options;
268 if (action == "--check") {
269 // Fast determination of whether artifacts are up to date.
270 return odr.CheckArtifactsAreUpToDate(metrics, &compilation_options);
271 } else if (action == "--compile") {
272 const ExitCode exit_code = odr.CheckArtifactsAreUpToDate(metrics, &compilation_options);
273 if (exit_code != ExitCode::kCompilationRequired) {
274 return exit_code;
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000275 }
Victor Hsieh08e9f5f2021-12-16 10:22:02 -0800276 OdrCompilationLog compilation_log;
277 if (!compilation_log.ShouldAttemptCompile(metrics.GetTrigger())) {
278 LOG(INFO) << "Compilation skipped because it was attempted recently";
279 return ExitCode::kOkay;
280 }
281 ExitCode compile_result = odr.Compile(metrics, compilation_options);
282 compilation_log.Log(metrics.GetArtApexVersion(),
283 metrics.GetArtApexLastUpdateMillis(),
284 metrics.GetTrigger(),
285 compile_result);
286 return compile_result;
287 } else if (action == "--force-compile") {
288 // Clean-up existing files.
289 if (!odr.RemoveArtifactsDirectory()) {
290 metrics.SetStatus(OdrMetrics::Status::kIoError);
291 return ExitCode::kCleanupFailed;
292 }
293 return odr.Compile(metrics,
294 CompilationOptions{
Jiakai Zhang884e22f2021-12-23 20:04:46 +0000295 .compile_boot_classpath_for_isas = config.GetBootClasspathIsas(),
296 .system_server_jars_to_compile = odr.AllSystemServerJars(),
Victor Hsieh08e9f5f2021-12-16 10:22:02 -0800297 });
298 } else if (action == "--help") {
299 UsageHelp(argv[0]);
300 } else {
Jiakai Zhang45d08812022-05-04 14:34:01 +0100301 ArgumentError("Unknown argument: %s", action.data());
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000302 }
Jiakai Zhang3ba3edf2021-08-11 08:25:40 +0000303}