blob: 7e02b6bcfca4da374039994afcb5de619b739dc8 [file] [log] [blame]
Andreas Gampe73dae112015-11-19 14:12:14 -08001/*
2 ** Copyright 2016, 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 <algorithm>
18#include <inttypes.h>
19#include <random>
Andreas Gampe1842af32016-03-16 14:28:50 -070020#include <regex>
Andreas Gampe73dae112015-11-19 14:12:14 -080021#include <selinux/android.h>
22#include <selinux/avc.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/capability.h>
26#include <sys/prctl.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29
30#include <android-base/logging.h>
31#include <android-base/macros.h>
32#include <android-base/stringprintf.h>
Andreas Gampe6db8db92016-06-03 10:22:19 -070033#include <android-base/strings.h>
Andreas Gampe73dae112015-11-19 14:12:14 -080034#include <cutils/fs.h>
35#include <cutils/log.h>
36#include <cutils/properties.h>
37#include <private/android_filesystem_config.h>
38
39#include <commands.h>
Andreas Gampe1842af32016-03-16 14:28:50 -070040#include <file_parsing.h>
Andreas Gampe73dae112015-11-19 14:12:14 -080041#include <globals.h>
42#include <installd_deps.h> // Need to fill in requirements of commands.
Andreas Gampefd12eda2016-07-12 09:47:17 -070043#include <otapreopt_utils.h>
Andreas Gampe73dae112015-11-19 14:12:14 -080044#include <system_properties.h>
45#include <utils.h>
46
47#ifndef LOG_TAG
48#define LOG_TAG "otapreopt"
49#endif
50
51#define BUFFER_MAX 1024 /* input buffer for commands */
52#define TOKEN_MAX 16 /* max number of arguments in buffer */
53#define REPLY_MAX 256 /* largest reply allowed */
54
Andreas Gampe56f79f92016-06-08 15:11:37 -070055using android::base::EndsWith;
Andreas Gampe6db8db92016-06-03 10:22:19 -070056using android::base::Join;
57using android::base::Split;
Andreas Gampe56f79f92016-06-08 15:11:37 -070058using android::base::StartsWith;
Andreas Gampe73dae112015-11-19 14:12:14 -080059using android::base::StringPrintf;
60
61namespace android {
62namespace installd {
63
Andreas Gampe73dae112015-11-19 14:12:14 -080064template<typename T>
65static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
66 return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
67}
68
69template<typename T>
70static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
71 return RoundDown(x + n - 1, n);
72}
73
74class OTAPreoptService {
75 public:
Andreas Gampe73dae112015-11-19 14:12:14 -080076 // Main driver. Performs the following steps.
77 //
78 // 1) Parse options (read system properties etc from B partition).
79 //
80 // 2) Read in package data.
81 //
82 // 3) Prepare environment variables.
83 //
84 // 4) Prepare(compile) boot image, if necessary.
85 //
86 // 5) Run update.
87 int Main(int argc, char** argv) {
Andreas Gamped089ca12016-06-27 14:25:30 -070088 if (!ReadArguments(argc, argv)) {
89 LOG(ERROR) << "Failed reading command line.";
90 return 1;
91 }
92
Andreas Gampe73dae112015-11-19 14:12:14 -080093 if (!ReadSystemProperties()) {
94 LOG(ERROR)<< "Failed reading system properties.";
Andreas Gamped089ca12016-06-27 14:25:30 -070095 return 2;
Andreas Gampe73dae112015-11-19 14:12:14 -080096 }
97
98 if (!ReadEnvironment()) {
99 LOG(ERROR) << "Failed reading environment properties.";
Andreas Gamped089ca12016-06-27 14:25:30 -0700100 return 3;
Andreas Gampe73dae112015-11-19 14:12:14 -0800101 }
102
Andreas Gamped089ca12016-06-27 14:25:30 -0700103 if (!CheckAndInitializeInstalldGlobals()) {
104 LOG(ERROR) << "Failed initializing globals.";
105 return 4;
Andreas Gampe73dae112015-11-19 14:12:14 -0800106 }
107
108 PrepareEnvironment();
109
Andreas Gamped089ca12016-06-27 14:25:30 -0700110 if (!PrepareBootImage(/* force */ false)) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800111 LOG(ERROR) << "Failed preparing boot image.";
Andreas Gamped089ca12016-06-27 14:25:30 -0700112 return 5;
Andreas Gampe73dae112015-11-19 14:12:14 -0800113 }
114
115 int dexopt_retcode = RunPreopt();
116
117 return dexopt_retcode;
118 }
119
Andreas Gamped089ca12016-06-27 14:25:30 -0700120 int GetProperty(const char* key, char* value, const char* default_value) const {
Andreas Gampe73dae112015-11-19 14:12:14 -0800121 const std::string* prop_value = system_properties_.GetProperty(key);
122 if (prop_value == nullptr) {
123 if (default_value == nullptr) {
124 return 0;
125 }
126 // Copy in the default value.
127 strncpy(value, default_value, kPropertyValueMax - 1);
128 value[kPropertyValueMax - 1] = 0;
129 return strlen(default_value);// TODO: Need to truncate?
130 }
131 size_t size = std::min(kPropertyValueMax - 1, prop_value->length());
132 strncpy(value, prop_value->data(), size);
133 value[size] = 0;
134 return static_cast<int>(size);
135 }
136
Andreas Gamped089ca12016-06-27 14:25:30 -0700137 std::string GetOTADataDirectory() const {
138 return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), target_slot_.c_str());
139 }
140
141 const std::string& GetTargetSlot() const {
142 return target_slot_;
143 }
144
Andreas Gampe73dae112015-11-19 14:12:14 -0800145private:
Andreas Gamped089ca12016-06-27 14:25:30 -0700146
Andreas Gampe73dae112015-11-19 14:12:14 -0800147 bool ReadSystemProperties() {
Andreas Gampe1842af32016-03-16 14:28:50 -0700148 static constexpr const char* kPropertyFiles[] = {
149 "/default.prop", "/system/build.prop"
150 };
Andreas Gampe73dae112015-11-19 14:12:14 -0800151
Andreas Gampe1842af32016-03-16 14:28:50 -0700152 for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
153 if (!system_properties_.Load(kPropertyFiles[i])) {
154 return false;
155 }
156 }
157
158 return true;
Andreas Gampe73dae112015-11-19 14:12:14 -0800159 }
160
161 bool ReadEnvironment() {
Andreas Gampe1842af32016-03-16 14:28:50 -0700162 // Parse the environment variables from init.environ.rc, which have the form
163 // export NAME VALUE
164 // For simplicity, don't respect string quotation. The values we are interested in can be
165 // encoded without them.
166 std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
167 bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
168 std::smatch export_match;
169 if (!std::regex_match(line, export_match, export_regex)) {
170 return true;
171 }
Andreas Gampe73dae112015-11-19 14:12:14 -0800172
Andreas Gampe1842af32016-03-16 14:28:50 -0700173 if (export_match.size() != 3) {
174 return true;
175 }
176
177 std::string name = export_match[1].str();
178 std::string value = export_match[2].str();
179
180 system_properties_.SetProperty(name, value);
181
182 return true;
183 });
184 if (!parse_result) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800185 return false;
186 }
Andreas Gampe1842af32016-03-16 14:28:50 -0700187
Andreas Gamped089ca12016-06-27 14:25:30 -0700188 if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
189 return false;
190 }
191 android_data_ = *system_properties_.GetProperty(kAndroidDataPathPropertyName);
192
193 if (system_properties_.GetProperty(kAndroidRootPathPropertyName) == nullptr) {
194 return false;
195 }
196 android_root_ = *system_properties_.GetProperty(kAndroidRootPathPropertyName);
197
198 if (system_properties_.GetProperty(kBootClassPathPropertyName) == nullptr) {
199 return false;
200 }
201 boot_classpath_ = *system_properties_.GetProperty(kBootClassPathPropertyName);
202
203 if (system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) == nullptr) {
204 return false;
205 }
206 asec_mountpoint_ = *system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME);
207
208 return true;
209 }
210
211 const std::string& GetAndroidData() const {
212 return android_data_;
213 }
214
215 const std::string& GetAndroidRoot() const {
216 return android_root_;
217 }
218
219 const std::string GetOtaDirectoryPrefix() const {
220 return GetAndroidData() + "/ota";
221 }
222
223 bool CheckAndInitializeInstalldGlobals() {
224 // init_globals_from_data_and_root requires "ASEC_MOUNTPOINT" in the environment. We
225 // do not use any datapath that includes this, but we'll still have to set it.
226 CHECK(system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) != nullptr);
227 int result = setenv(ASEC_MOUNTPOINT_ENV_NAME, asec_mountpoint_.c_str(), 0);
228 if (result != 0) {
229 LOG(ERROR) << "Could not set ASEC_MOUNTPOINT environment variable";
230 return false;
231 }
232
233 if (!init_globals_from_data_and_root(GetAndroidData().c_str(), GetAndroidRoot().c_str())) {
234 LOG(ERROR) << "Could not initialize globals; exiting.";
235 return false;
236 }
237
238 // This is different from the normal installd. We only do the base
239 // directory, the rest will be created on demand when each app is compiled.
240 if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
241 LOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
242 return false;
Andreas Gampe1842af32016-03-16 14:28:50 -0700243 }
Andreas Gampe73dae112015-11-19 14:12:14 -0800244
245 return true;
246 }
247
Andreas Gamped089ca12016-06-27 14:25:30 -0700248 bool ReadArguments(int argc ATTRIBUTE_UNUSED, char** argv) {
249 // Expected command line:
250 // target-slot dexopt {DEXOPT_PARAMETERS}
251 // The DEXOPT_PARAMETERS are passed on to dexopt(), so we expect DEXOPT_PARAM_COUNT
252 // of them. We store them in package_parameters_ (size checks are done when
253 // parsing the special parameters and when copying into package_parameters_.
254
Andreas Gampe548bdb92016-06-02 17:56:45 -0700255 static_assert(DEXOPT_PARAM_COUNT == ARRAY_SIZE(package_parameters_),
256 "Unexpected dexopt param count");
Andreas Gamped089ca12016-06-27 14:25:30 -0700257
258 const char* target_slot_arg = argv[1];
259 if (target_slot_arg == nullptr) {
260 LOG(ERROR) << "Missing parameters";
261 return false;
262 }
263 // Sanitize value. Only allow (a-zA-Z0-9_)+.
264 target_slot_ = target_slot_arg;
Andreas Gampefd12eda2016-07-12 09:47:17 -0700265 if (!ValidateTargetSlotSuffix(target_slot_)) {
266 LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
267 return false;
Andreas Gamped089ca12016-06-27 14:25:30 -0700268 }
269
270 // Check for "dexopt" next.
271 if (argv[2] == nullptr) {
272 LOG(ERROR) << "Missing parameters";
273 return false;
274 }
275 if (std::string("dexopt").compare(argv[2]) != 0) {
276 LOG(ERROR) << "Second parameter not dexopt: " << argv[2];
277 return false;
278 }
279
280 // Copy the rest into package_parameters_, but be careful about over- and underflow.
281 size_t index = 0;
Andreas Gampe548bdb92016-06-02 17:56:45 -0700282 while (index < DEXOPT_PARAM_COUNT &&
Andreas Gamped089ca12016-06-27 14:25:30 -0700283 argv[index + 3] != nullptr) {
284 package_parameters_[index] = argv[index + 3];
Andreas Gampe73dae112015-11-19 14:12:14 -0800285 index++;
286 }
Andreas Gamped089ca12016-06-27 14:25:30 -0700287 if (index != ARRAY_SIZE(package_parameters_) || argv[index + 3] != nullptr) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800288 LOG(ERROR) << "Wrong number of parameters";
289 return false;
290 }
291
292 return true;
293 }
294
295 void PrepareEnvironment() {
Andreas Gamped089ca12016-06-27 14:25:30 -0700296 environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str()));
297 environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str()));
298 environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str()));
Andreas Gampe73dae112015-11-19 14:12:14 -0800299
300 for (const std::string& e : environ_) {
301 putenv(const_cast<char*>(e.c_str()));
302 }
303 }
304
305 // Ensure that we have the right boot image. The first time any app is
306 // compiled, we'll try to generate it.
Andreas Gamped089ca12016-06-27 14:25:30 -0700307 bool PrepareBootImage(bool force) const {
Andreas Gampe73dae112015-11-19 14:12:14 -0800308 if (package_parameters_[kISAIndex] == nullptr) {
309 LOG(ERROR) << "Instruction set missing.";
310 return false;
311 }
312 const char* isa = package_parameters_[kISAIndex];
313
314 // Check whether the file exists where expected.
Andreas Gamped089ca12016-06-27 14:25:30 -0700315 std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
Andreas Gampe73dae112015-11-19 14:12:14 -0800316 std::string isa_path = dalvik_cache + "/" + isa;
317 std::string art_path = isa_path + "/system@framework@boot.art";
318 std::string oat_path = isa_path + "/system@framework@boot.oat";
Andreas Gamped089ca12016-06-27 14:25:30 -0700319 bool cleared = false;
320 if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
321 // Files exist, assume everything is alright if not forced. Otherwise clean up.
322 if (!force) {
323 return true;
324 }
325 ClearDirectory(isa_path);
326 cleared = true;
Andreas Gampe73dae112015-11-19 14:12:14 -0800327 }
328
Andreas Gamped089ca12016-06-27 14:25:30 -0700329 // Reset umask in otapreopt, so that we control the the access for the files we create.
330 umask(0);
331
Andreas Gampe73dae112015-11-19 14:12:14 -0800332 // Create the directories, if necessary.
333 if (access(dalvik_cache.c_str(), F_OK) != 0) {
Andreas Gamped089ca12016-06-27 14:25:30 -0700334 if (!CreatePath(dalvik_cache)) {
335 PLOG(ERROR) << "Could not create dalvik-cache dir " << dalvik_cache;
Andreas Gampe73dae112015-11-19 14:12:14 -0800336 return false;
337 }
338 }
339 if (access(isa_path.c_str(), F_OK) != 0) {
Andreas Gamped089ca12016-06-27 14:25:30 -0700340 if (!CreatePath(isa_path)) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800341 PLOG(ERROR) << "Could not create dalvik-cache isa dir";
342 return false;
343 }
344 }
345
Andreas Gampe5709b572016-02-12 17:42:59 -0800346 // Prepare to create.
Andreas Gamped089ca12016-06-27 14:25:30 -0700347 if (!cleared) {
348 ClearDirectory(isa_path);
349 }
Andreas Gampe73dae112015-11-19 14:12:14 -0800350
Andreas Gampe9fb85b02016-03-16 10:09:29 -0700351 std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
Andreas Gampe5709b572016-02-12 17:42:59 -0800352 if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
353 return PatchoatBootImage(art_path, isa);
354 } else {
355 // No preopted boot image. Try to compile.
Andreas Gamped089ca12016-06-27 14:25:30 -0700356 return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
Andreas Gampe5709b572016-02-12 17:42:59 -0800357 }
358 }
359
Andreas Gamped089ca12016-06-27 14:25:30 -0700360 static bool CreatePath(const std::string& path) {
361 // Create the given path. Use string processing instead of dirname, as dirname's need for
362 // a writable char buffer is painful.
363
364 // First, try to use the full path.
365 if (mkdir(path.c_str(), 0711) == 0) {
366 return true;
367 }
368 if (errno != ENOENT) {
369 PLOG(ERROR) << "Could not create path " << path;
370 return false;
371 }
372
373 // Now find the parent and try that first.
374 size_t last_slash = path.find_last_of('/');
375 if (last_slash == std::string::npos || last_slash == 0) {
376 PLOG(ERROR) << "Could not create " << path;
377 return false;
378 }
379
380 if (!CreatePath(path.substr(0, last_slash))) {
381 return false;
382 }
383
384 if (mkdir(path.c_str(), 0711) == 0) {
385 return true;
386 }
387 PLOG(ERROR) << "Could not create " << path;
388 return false;
389 }
390
391 static void ClearDirectory(const std::string& dir) {
392 DIR* c_dir = opendir(dir.c_str());
393 if (c_dir == nullptr) {
394 PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
395 return;
396 }
397
398 for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
399 const char* name = de->d_name;
400 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
401 continue;
402 }
403 // We only want to delete regular files and symbolic links.
404 std::string file = StringPrintf("%s/%s", dir.c_str(), name);
405 if (de->d_type != DT_REG && de->d_type != DT_LNK) {
406 LOG(WARNING) << "Unexpected file "
407 << file
408 << " of type "
409 << std::hex
410 << de->d_type
411 << " encountered.";
412 } else {
413 // Try to unlink the file.
414 if (unlink(file.c_str()) != 0) {
415 PLOG(ERROR) << "Unable to unlink " << file;
416 }
417 }
418 }
419 CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
420 }
421
422 bool PatchoatBootImage(const std::string& art_path, const char* isa) const {
Andreas Gampe5709b572016-02-12 17:42:59 -0800423 // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
424
425 std::vector<std::string> cmd;
Andreas Gampe9fb85b02016-03-16 10:09:29 -0700426 cmd.push_back("/system/bin/patchoat");
Andreas Gampe5709b572016-02-12 17:42:59 -0800427
428 cmd.push_back("--input-image-location=/system/framework/boot.art");
429 cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
430
431 cmd.push_back(StringPrintf("--instruction-set=%s", isa));
432
433 int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
434 ART_BASE_ADDRESS_MAX_DELTA);
Andreas Gampefebf0bf2016-02-29 18:04:17 -0800435 cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
Andreas Gampe5709b572016-02-12 17:42:59 -0800436
437 std::string error_msg;
438 bool result = Exec(cmd, &error_msg);
439 if (!result) {
440 LOG(ERROR) << "Could not generate boot image: " << error_msg;
441 }
442 return result;
443 }
444
445 bool Dex2oatBootImage(const std::string& boot_cp,
446 const std::string& art_path,
447 const std::string& oat_path,
Andreas Gamped089ca12016-06-27 14:25:30 -0700448 const char* isa) const {
Andreas Gampe73dae112015-11-19 14:12:14 -0800449 // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
450 std::vector<std::string> cmd;
Andreas Gampe9fb85b02016-03-16 10:09:29 -0700451 cmd.push_back("/system/bin/dex2oat");
Andreas Gampe73dae112015-11-19 14:12:14 -0800452 cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
Andreas Gampe6db8db92016-06-03 10:22:19 -0700453 for (const std::string& boot_part : Split(boot_cp, ":")) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800454 cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
455 }
456 cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
457
458 int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
459 ART_BASE_ADDRESS_MAX_DELTA);
460 cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
461
462 cmd.push_back(StringPrintf("--instruction-set=%s", isa));
463
464 // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp.
465 AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms",
466 "-Xms",
467 true,
468 cmd);
469 AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx",
470 "-Xmx",
471 true,
472 cmd);
473 AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter",
474 "--compiler-filter=",
475 false,
476 cmd);
Andreas Gampe9fb85b02016-03-16 10:09:29 -0700477 cmd.push_back("--image-classes=/system/etc/preloaded-classes");
Andreas Gampe73dae112015-11-19 14:12:14 -0800478 // TODO: Compiled-classes.
479 const std::string* extra_opts =
480 system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
481 if (extra_opts != nullptr) {
Andreas Gampe6db8db92016-06-03 10:22:19 -0700482 std::vector<std::string> extra_vals = Split(*extra_opts, " ");
Andreas Gampe73dae112015-11-19 14:12:14 -0800483 cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end());
484 }
485 // TODO: Should we lower this? It's usually set close to max, because
486 // normally there's not much else going on at boot.
487 AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads",
488 "-j",
489 false,
490 cmd);
491 AddCompilerOptionFromSystemProperty(
492 StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
493 "--instruction-set-variant=",
494 false,
495 cmd);
496 AddCompilerOptionFromSystemProperty(
497 StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(),
498 "--instruction-set-features=",
499 false,
500 cmd);
501
502 std::string error_msg;
503 bool result = Exec(cmd, &error_msg);
504 if (!result) {
505 LOG(ERROR) << "Could not generate boot image: " << error_msg;
506 }
507 return result;
508 }
509
510 static const char* ParseNull(const char* arg) {
511 return (strcmp(arg, "!") == 0) ? nullptr : arg;
512 }
513
Andreas Gamped089ca12016-06-27 14:25:30 -0700514 bool ShouldSkipPreopt() const {
Andreas Gampe56f79f92016-06-08 15:11:37 -0700515 // There's one thing we have to be careful about: we may/will be asked to compile an app
516 // living in the system image. This may be a valid request - if the app wasn't compiled,
517 // e.g., if the system image wasn't large enough to include preopted files. However, the
518 // data we have is from the old system, so the driver (the OTA service) can't actually
519 // know. Thus, we will get requests for apps that have preopted components. To avoid
520 // duplication (we'd generate files that are not used and are *not* cleaned up), do two
521 // simple checks:
522 //
523 // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
524 // (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
525 //
526 // 2) If you replace the name in the apk_path with "oat," does the path exist?
527 // (=have a subdirectory for preopted files)
528 //
529 // If the answer to both is yes, skip the dexopt.
530 //
531 // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
532 // be stripped), that's not true for APKs signed outside the build system (so the
533 // jar content must be exactly the same).
534
535 // (This is ugly as it's the only thing where we need to understand the contents
536 // of package_parameters_, but it beats postponing the decision or using the call-
537 // backs to do weird things.)
538 constexpr size_t kApkPathIndex = 0;
539 CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
540 CHECK(package_parameters_[kApkPathIndex] != nullptr);
Andreas Gamped089ca12016-06-27 14:25:30 -0700541 if (StartsWith(package_parameters_[kApkPathIndex], android_root_.c_str())) {
Andreas Gampe56f79f92016-06-08 15:11:37 -0700542 const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
543 if (last_slash != nullptr) {
544 std::string path(package_parameters_[kApkPathIndex],
545 last_slash - package_parameters_[kApkPathIndex] + 1);
546 CHECK(EndsWith(path, "/"));
547 path = path + "oat";
548 if (access(path.c_str(), F_OK) == 0) {
Andreas Gamped089ca12016-06-27 14:25:30 -0700549 return true;
Andreas Gampe56f79f92016-06-08 15:11:37 -0700550 }
551 }
552 }
553
Andreas Gamped089ca12016-06-27 14:25:30 -0700554 // Another issue is unavailability of files in the new system. If the partition
555 // layout changes, otapreopt_chroot may not know about this. Then files from that
556 // partition will not be available and fail to build. This is problematic, as
557 // this tool will wipe the OTA artifact cache and try again (for robustness after
558 // a failed OTA with remaining cache artifacts).
559 if (access(package_parameters_[kApkPathIndex], F_OK) != 0) {
560 LOG(WARNING) << "Skipping preopt of non-existing package "
561 << package_parameters_[kApkPathIndex];
562 return true;
563 }
564
565 return false;
566 }
567
568 int RunPreopt() {
569 if (ShouldSkipPreopt()) {
570 return 0;
571 }
572
573 int dexopt_result = dexopt(package_parameters_);
574 if (dexopt_result == 0) {
575 return 0;
576 }
577
578 // If the dexopt failed, we may have a stale boot image from a previous OTA run.
579 // Try to delete and retry.
580
581 if (!PrepareBootImage(/* force */ true)) {
582 LOG(ERROR) << "Forced boot image creating failed. Original error return was "
583 << dexopt_result;
584 return dexopt_result;
585 }
586
587 LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
Andreas Gampe548bdb92016-06-02 17:56:45 -0700588 return dexopt(package_parameters_);
Andreas Gampe73dae112015-11-19 14:12:14 -0800589 }
590
591 ////////////////////////////////////
592 // Helpers, mostly taken from ART //
593 ////////////////////////////////////
594
595 // Wrapper on fork/execv to run a command in a subprocess.
Andreas Gamped089ca12016-06-27 14:25:30 -0700596 static bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
Andreas Gampe6db8db92016-06-03 10:22:19 -0700597 const std::string command_line = Join(arg_vector, ' ');
Andreas Gampe73dae112015-11-19 14:12:14 -0800598
599 CHECK_GE(arg_vector.size(), 1U) << command_line;
600
601 // Convert the args to char pointers.
602 const char* program = arg_vector[0].c_str();
603 std::vector<char*> args;
604 for (size_t i = 0; i < arg_vector.size(); ++i) {
605 const std::string& arg = arg_vector[i];
606 char* arg_str = const_cast<char*>(arg.c_str());
607 CHECK(arg_str != nullptr) << i;
608 args.push_back(arg_str);
609 }
610 args.push_back(nullptr);
611
612 // Fork and exec.
613 pid_t pid = fork();
614 if (pid == 0) {
615 // No allocation allowed between fork and exec.
616
617 // Change process groups, so we don't get reaped by ProcessManager.
618 setpgid(0, 0);
619
620 execv(program, &args[0]);
621
622 PLOG(ERROR) << "Failed to execv(" << command_line << ")";
623 // _exit to avoid atexit handlers in child.
624 _exit(1);
625 } else {
626 if (pid == -1) {
627 *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
628 command_line.c_str(), strerror(errno));
629 return false;
630 }
631
632 // wait for subprocess to finish
633 int status;
634 pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
635 if (got_pid != pid) {
636 *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
637 "wanted %d, got %d: %s",
638 command_line.c_str(), pid, got_pid, strerror(errno));
639 return false;
640 }
641 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
642 *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
643 command_line.c_str());
644 return false;
645 }
646 }
647 return true;
648 }
649
650 // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
651 static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
652 constexpr size_t kPageSize = PAGE_SIZE;
653 CHECK_EQ(min_delta % kPageSize, 0u);
654 CHECK_EQ(max_delta % kPageSize, 0u);
655 CHECK_LT(min_delta, max_delta);
656
657 std::default_random_engine generator;
658 generator.seed(GetSeed());
659 std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta);
660 int32_t r = distribution(generator);
661 if (r % 2 == 0) {
662 r = RoundUp(r, kPageSize);
663 } else {
664 r = RoundDown(r, kPageSize);
665 }
666 CHECK_LE(min_delta, r);
667 CHECK_GE(max_delta, r);
668 CHECK_EQ(r % kPageSize, 0u);
669 return r;
670 }
671
672 static uint64_t GetSeed() {
673#ifdef __BIONIC__
674 // Bionic exposes arc4random, use it.
675 uint64_t random_data;
676 arc4random_buf(&random_data, sizeof(random_data));
677 return random_data;
678#else
679#error "This is only supposed to run with bionic. Otherwise, implement..."
680#endif
681 }
682
683 void AddCompilerOptionFromSystemProperty(const char* system_property,
684 const char* prefix,
685 bool runtime,
Andreas Gamped089ca12016-06-27 14:25:30 -0700686 std::vector<std::string>& out) const {
687 const std::string* value = system_properties_.GetProperty(system_property);
Andreas Gampe73dae112015-11-19 14:12:14 -0800688 if (value != nullptr) {
689 if (runtime) {
690 out.push_back("--runtime-arg");
691 }
692 if (prefix != nullptr) {
693 out.push_back(StringPrintf("%s%s", prefix, value->c_str()));
694 } else {
695 out.push_back(*value);
696 }
697 }
698 }
699
Andreas Gamped089ca12016-06-27 14:25:30 -0700700 static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
701 static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
702 static constexpr const char* kAndroidDataPathPropertyName = "ANDROID_DATA";
703 // The index of the instruction-set string inside the package parameters. Needed for
704 // some special-casing that requires knowledge of the instruction-set.
705 static constexpr size_t kISAIndex = 3;
706
Andreas Gampe73dae112015-11-19 14:12:14 -0800707 // Stores the system properties read out of the B partition. We need to use these properties
708 // to compile, instead of the A properties we could get from init/get_property.
709 SystemProperties system_properties_;
710
Andreas Gamped089ca12016-06-27 14:25:30 -0700711 // Some select properties that are always needed.
712 std::string target_slot_;
713 std::string android_root_;
714 std::string android_data_;
715 std::string boot_classpath_;
716 std::string asec_mountpoint_;
717
Andreas Gampe548bdb92016-06-02 17:56:45 -0700718 const char* package_parameters_[DEXOPT_PARAM_COUNT];
Andreas Gampe73dae112015-11-19 14:12:14 -0800719
720 // Store environment values we need to set.
721 std::vector<std::string> environ_;
722};
723
724OTAPreoptService gOps;
725
726////////////////////////
727// Plug-in functions. //
728////////////////////////
729
730int get_property(const char *key, char *value, const char *default_value) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800731 return gOps.GetProperty(key, value, default_value);
732}
733
734// Compute the output path of
735bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
736 const char *apk_path,
737 const char *instruction_set) {
Dan Austin9c8f93a2016-06-03 16:15:54 -0700738 const char *file_name_start;
739 const char *file_name_end;
Andreas Gampe73dae112015-11-19 14:12:14 -0800740
741 file_name_start = strrchr(apk_path, '/');
742 if (file_name_start == nullptr) {
743 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
744 return false;
745 }
746 file_name_end = strrchr(file_name_start, '.');
747 if (file_name_end == nullptr) {
748 ALOGE("apk_path '%s' has no extension\n", apk_path);
749 return false;
750 }
751
752 // Calculate file_name
753 file_name_start++; // Move past '/', is valid as file_name_end is valid.
754 size_t file_name_len = file_name_end - file_name_start;
755 std::string file_name(file_name_start, file_name_len);
756
757 // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
Andreas Gamped089ca12016-06-27 14:25:30 -0700758 snprintf(path,
759 PKG_PATH_MAX,
760 "%s/%s/%s.odex.%s",
761 oat_dir,
762 instruction_set,
763 file_name.c_str(),
764 gOps.GetTargetSlot().c_str());
Andreas Gampe73dae112015-11-19 14:12:14 -0800765 return true;
766}
767
768/*
769 * Computes the odex file for the given apk_path and instruction_set.
770 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
771 *
772 * Returns false if it failed to determine the odex file path.
773 */
774bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
775 const char *instruction_set) {
Andreas Gampe73dae112015-11-19 14:12:14 -0800776 const char *path_end = strrchr(apk_path, '/');
777 if (path_end == nullptr) {
778 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
779 return false;
780 }
781 std::string path_component(apk_path, path_end - apk_path);
782
783 const char *name_begin = path_end + 1;
784 const char *extension_start = strrchr(name_begin, '.');
785 if (extension_start == nullptr) {
786 ALOGE("apk_path '%s' has no extension.\n", apk_path);
787 return false;
788 }
789 std::string name_component(name_begin, extension_start - name_begin);
790
Andreas Gamped089ca12016-06-27 14:25:30 -0700791 std::string new_path = StringPrintf("%s/oat/%s/%s.odex.%s",
Andreas Gampe73dae112015-11-19 14:12:14 -0800792 path_component.c_str(),
793 instruction_set,
Andreas Gamped089ca12016-06-27 14:25:30 -0700794 name_component.c_str(),
795 gOps.GetTargetSlot().c_str());
796 if (new_path.length() >= PKG_PATH_MAX) {
797 LOG(ERROR) << "apk_path of " << apk_path << " is too long: " << new_path;
798 return false;
799 }
Andreas Gampe73dae112015-11-19 14:12:14 -0800800 strcpy(path, new_path.c_str());
801 return true;
802}
803
804bool create_cache_path(char path[PKG_PATH_MAX],
805 const char *src,
806 const char *instruction_set) {
807 size_t srclen = strlen(src);
808
809 /* demand that we are an absolute path */
810 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
811 return false;
812 }
813
814 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
815 return false;
816 }
817
818 std::string from_src = std::string(src + 1);
819 std::replace(from_src.begin(), from_src.end(), '/', '@');
820
821 std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
Andreas Gamped089ca12016-06-27 14:25:30 -0700822 gOps.GetOTADataDirectory().c_str(),
Andreas Gampe73dae112015-11-19 14:12:14 -0800823 DALVIK_CACHE,
824 instruction_set,
825 from_src.c_str(),
David Brazdil249c1792016-09-06 15:35:28 +0100826 DALVIK_CACHE_POSTFIX);
Andreas Gampe73dae112015-11-19 14:12:14 -0800827
828 if (assembled_path.length() + 1 > PKG_PATH_MAX) {
829 return false;
830 }
831 strcpy(path, assembled_path.c_str());
832
833 return true;
834}
835
Andreas Gampe73dae112015-11-19 14:12:14 -0800836static int log_callback(int type, const char *fmt, ...) {
837 va_list ap;
838 int priority;
839
840 switch (type) {
841 case SELINUX_WARNING:
842 priority = ANDROID_LOG_WARN;
843 break;
844 case SELINUX_INFO:
845 priority = ANDROID_LOG_INFO;
846 break;
847 default:
848 priority = ANDROID_LOG_ERROR;
849 break;
850 }
851 va_start(ap, fmt);
852 LOG_PRI_VA(priority, "SELinux", fmt, ap);
853 va_end(ap);
854 return 0;
855}
856
857static int otapreopt_main(const int argc, char *argv[]) {
858 int selinux_enabled = (is_selinux_enabled() > 0);
859
860 setenv("ANDROID_LOG_TAGS", "*:v", 1);
861 android::base::InitLogging(argv);
862
Andreas Gampe73dae112015-11-19 14:12:14 -0800863 if (argc < 2) {
864 ALOGE("Expecting parameters");
865 exit(1);
866 }
867
868 union selinux_callback cb;
869 cb.func_log = log_callback;
870 selinux_set_callback(SELINUX_CB_LOG, cb);
871
Andreas Gampe73dae112015-11-19 14:12:14 -0800872 if (selinux_enabled && selinux_status_open(true) < 0) {
873 ALOGE("Could not open selinux status; exiting.\n");
874 exit(1);
875 }
876
877 int ret = android::installd::gOps.Main(argc, argv);
878
879 return ret;
880}
881
882} // namespace installd
883} // namespace android
884
885int main(const int argc, char *argv[]) {
886 return android::installd::otapreopt_main(argc, argv);
887}