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