otapreopt.cpp revision 1842af3a4a8fccf71f5c569071518de14b3698ac
173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe/* 273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** Copyright 2016, The Android Open Source Project 373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** 473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** Licensed under the Apache License, Version 2.0 (the "License"); 573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** you may not use this file except in compliance with the License. 673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** You may obtain a copy of the License at 773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** 873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** http://www.apache.org/licenses/LICENSE-2.0 973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** 1073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** Unless required by applicable law or agreed to in writing, software 1173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** distributed under the License is distributed on an "AS IS" BASIS, 1273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** See the License for the specific language governing permissions and 1473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ** limitations under the License. 1573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe */ 1673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 1773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <algorithm> 1873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <inttypes.h> 1973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <random> 201842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe#include <regex> 2173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <selinux/android.h> 2273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <selinux/avc.h> 2373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <stdlib.h> 2473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <string.h> 2573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <sys/capability.h> 2673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <sys/prctl.h> 2773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <sys/stat.h> 2873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <sys/wait.h> 2973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 3073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <android-base/logging.h> 3173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <android-base/macros.h> 3273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <android-base/stringprintf.h> 3373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/fs.h> 3473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/log.h> 3573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/properties.h> 3673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <private/android_filesystem_config.h> 3773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 3873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <commands.h> 391842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe#include <file_parsing.h> 4073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <globals.h> 4173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <installd_deps.h> // Need to fill in requirements of commands. 4273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <string_helpers.h> 4373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <system_properties.h> 4473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <utils.h> 4573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 4673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#ifndef LOG_TAG 4773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define LOG_TAG "otapreopt" 4873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#endif 4973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 5073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define BUFFER_MAX 1024 /* input buffer for commands */ 5173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define TOKEN_MAX 16 /* max number of arguments in buffer */ 5273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define REPLY_MAX 256 /* largest reply allowed */ 5373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 5473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeusing android::base::StringPrintf; 5573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 5673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampenamespace android { 5773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampenamespace installd { 5873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 591842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampestatic constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH"; 601842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampestatic constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT"; 6173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr const char* kOTARootDirectory = "/system-b"; 6273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr size_t kISAIndex = 3; 6373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 6473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampetemplate<typename T> 6573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr T RoundDown(T x, typename std::decay<T>::type n) { 6673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n); 6773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 6873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 6973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampetemplate<typename T> 7073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) { 7173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return RoundDown(x + n - 1, n); 7273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 7373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 7473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeclass OTAPreoptService { 7573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe public: 7673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe static constexpr const char* kOTADataDirectory = "/data/ota"; 7773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 7873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Main driver. Performs the following steps. 7973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 8073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 1) Parse options (read system properties etc from B partition). 8173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 8273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 2) Read in package data. 8373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 8473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 3) Prepare environment variables. 8573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 8673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 4) Prepare(compile) boot image, if necessary. 8773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 8873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // 5) Run update. 8973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int Main(int argc, char** argv) { 9073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!ReadSystemProperties()) { 9173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR)<< "Failed reading system properties."; 9273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 1; 9373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 9473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 9573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!ReadEnvironment()) { 9673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Failed reading environment properties."; 9773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 2; 9873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 9973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 10073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!ReadPackage(argc, argv)) { 10173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Failed reading command line file."; 10273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 3; 10373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 10473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 10573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe PrepareEnvironment(); 10673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 10773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!PrepareBootImage()) { 10873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Failed preparing boot image."; 10973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 4; 11073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 11173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 11273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int dexopt_retcode = RunPreopt(); 11373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 11473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return dexopt_retcode; 11573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 11673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 11773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int GetProperty(const char* key, char* value, const char* default_value) { 11873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string* prop_value = system_properties_.GetProperty(key); 11973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (prop_value == nullptr) { 12073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (default_value == nullptr) { 12173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 0; 12273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 12373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Copy in the default value. 12473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe strncpy(value, default_value, kPropertyValueMax - 1); 12573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe value[kPropertyValueMax - 1] = 0; 12673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return strlen(default_value);// TODO: Need to truncate? 12773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 12873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe size_t size = std::min(kPropertyValueMax - 1, prop_value->length()); 12973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe strncpy(value, prop_value->data(), size); 13073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe value[size] = 0; 13173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return static_cast<int>(size); 13273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 13373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 13473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeprivate: 13573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool ReadSystemProperties() { 1361842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe static constexpr const char* kPropertyFiles[] = { 1371842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe "/default.prop", "/system/build.prop" 1381842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe }; 1391842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1401842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) { 1411842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe if (!system_properties_.Load(kPropertyFiles[i])) { 1421842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return false; 1431842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe } 1441842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe } 1451842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1461842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return true; 14773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 14873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 14973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool ReadEnvironment() { 1501842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe // Parse the environment variables from init.environ.rc, which have the form 1511842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe // export NAME VALUE 1521842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe // For simplicity, don't respect string quotation. The values we are interested in can be 1531842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe // encoded without them. 1541842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)"); 1551842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) { 1561842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe std::smatch export_match; 1571842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe if (!std::regex_match(line, export_match, export_regex)) { 1581842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return true; 1591842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe } 1601842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1611842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe if (export_match.size() != 3) { 1621842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return true; 1631842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe } 1641842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1651842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe std::string name = export_match[1].str(); 1661842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe std::string value = export_match[2].str(); 1671842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1681842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe system_properties_.SetProperty(name, value); 1691842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe 1701842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return true; 1711842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe }); 1721842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe if (!parse_result) { 17373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 17473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 17573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 1761842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe // Check that we found important properties. 1771842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe constexpr const char* kRequiredProperties[] = { 1781842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe kBootClassPathPropertyName, kAndroidRootPathPropertyName 1791842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe }; 1801842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe for (size_t i = 0; i < arraysize(kRequiredProperties); ++i) { 1811842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe if (system_properties_.GetProperty(kRequiredProperties[i]) == nullptr) { 1821842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe return false; 1831842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe } 18473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 18573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 18673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 18773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 18873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 18973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool ReadPackage(int argc ATTRIBUTE_UNUSED, char** argv) { 19073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe size_t index = 0; 19173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe while (index < ARRAY_SIZE(package_parameters_) && 19273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe argv[index + 1] != nullptr) { 19373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe package_parameters_[index] = argv[index + 1]; 19473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe index++; 19573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 19673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (index != ARRAY_SIZE(package_parameters_)) { 19773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Wrong number of parameters"; 19873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 19973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 20073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 20173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 20273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 20373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 20473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe void PrepareEnvironment() { 20573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK(system_properties_.GetProperty(kBootClassPathPropertyName) != nullptr); 20673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string& boot_cp = 20773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *system_properties_.GetProperty(kBootClassPathPropertyName); 20873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_cp.c_str())); 20973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe environ_.push_back(StringPrintf("ANDROID_DATA=%s", kOTADataDirectory)); 21073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK(system_properties_.GetProperty(kAndroidRootPathPropertyName) != nullptr); 21173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string& android_root = 21273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *system_properties_.GetProperty(kAndroidRootPathPropertyName); 21373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root.c_str())); 21473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 21573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe for (const std::string& e : environ_) { 21673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe putenv(const_cast<char*>(e.c_str())); 21773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 21873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 21973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 22073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Ensure that we have the right boot image. The first time any app is 22173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // compiled, we'll try to generate it. 22273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool PrepareBootImage() { 22373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (package_parameters_[kISAIndex] == nullptr) { 22473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Instruction set missing."; 22573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 22673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 22773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char* isa = package_parameters_[kISAIndex]; 22873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 22973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Check whether the file exists where expected. 23073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string dalvik_cache = std::string(kOTADataDirectory) + "/" + DALVIK_CACHE; 23173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string isa_path = dalvik_cache + "/" + isa; 23273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string art_path = isa_path + "/system@framework@boot.art"; 23373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string oat_path = isa_path + "/system@framework@boot.oat"; 23473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (access(art_path.c_str(), F_OK) == 0 && 23573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe access(oat_path.c_str(), F_OK) == 0) { 23673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Files exist, assume everything is alright. 23773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 23873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 23973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 24073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Create the directories, if necessary. 24173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (access(dalvik_cache.c_str(), F_OK) != 0) { 24273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (mkdir(dalvik_cache.c_str(), 0711) != 0) { 24373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe PLOG(ERROR) << "Could not create dalvik-cache dir"; 24473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 24573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 24673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 24773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (access(isa_path.c_str(), F_OK) != 0) { 24873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (mkdir(isa_path.c_str(), 0711) != 0) { 24973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe PLOG(ERROR) << "Could not create dalvik-cache isa dir"; 25073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 25173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 25273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 25373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 2545709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe // Prepare to create. 25573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // TODO: Delete files, just for a blank slate. 25673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string& boot_cp = *system_properties_.GetProperty(kBootClassPathPropertyName); 25773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 2589fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa); 2595709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe if (access(preopted_boot_art_path.c_str(), F_OK) == 0) { 2605709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe return PatchoatBootImage(art_path, isa); 2615709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe } else { 2625709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe // No preopted boot image. Try to compile. 2635709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe return Dex2oatBootImage(boot_cp, art_path, oat_path, isa); 2645709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe } 2655709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe } 2665709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2675709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe bool PatchoatBootImage(const std::string& art_path, const char* isa) { 2685709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc. 2695709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2705709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe std::vector<std::string> cmd; 2719fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe cmd.push_back("/system/bin/patchoat"); 2725709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2735709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe cmd.push_back("--input-image-location=/system/framework/boot.art"); 2745709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str())); 2755709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2765709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe cmd.push_back(StringPrintf("--instruction-set=%s", isa)); 2775709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2785709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 2795709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe ART_BASE_ADDRESS_MAX_DELTA); 280febf0bf33ca81edcdaab3625e2711fa58b398cc5Andreas Gampe cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset)); 2815709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2825709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe std::string error_msg; 2835709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe bool result = Exec(cmd, &error_msg); 2845709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe if (!result) { 2855709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe LOG(ERROR) << "Could not generate boot image: " << error_msg; 2865709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe } 2875709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe return result; 2885709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe } 2895709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe 2905709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe bool Dex2oatBootImage(const std::string& boot_cp, 2915709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe const std::string& art_path, 2925709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe const std::string& oat_path, 2935709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe const char* isa) { 29473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc. 29573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::vector<std::string> cmd; 2969fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe cmd.push_back("/system/bin/dex2oat"); 29773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.push_back(StringPrintf("--image=%s", art_path.c_str())); 29873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe for (const std::string& boot_part : Split(boot_cp, ':')) { 29973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str())); 30073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 30173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str())); 30273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 30373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 30473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ART_BASE_ADDRESS_MAX_DELTA); 30573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset)); 30673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 30773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.push_back(StringPrintf("--instruction-set=%s", isa)); 30873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 30973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp. 31073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms", 31173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "-Xms", 31273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe true, 31373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 31473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx", 31573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "-Xmx", 31673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe true, 31773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 31873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter", 31973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "--compiler-filter=", 32073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe false, 32173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 3229fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe cmd.push_back("--image-classes=/system/etc/preloaded-classes"); 32373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // TODO: Compiled-classes. 32473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string* extra_opts = 32573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags"); 32673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (extra_opts != nullptr) { 32773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::vector<std::string> extra_vals = Split(*extra_opts, ' '); 32873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end()); 32973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 33073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // TODO: Should we lower this? It's usually set close to max, because 33173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // normally there's not much else going on at boot. 33273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads", 33373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "-j", 33473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe false, 33573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 33673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty( 33773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(), 33873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "--instruction-set-variant=", 33973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe false, 34073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 34173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe AddCompilerOptionFromSystemProperty( 34273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(), 34373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "--instruction-set-features=", 34473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe false, 34573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cmd); 34673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 34773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string error_msg; 34873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool result = Exec(cmd, &error_msg); 34973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!result) { 35073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(ERROR) << "Could not generate boot image: " << error_msg; 35173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 35273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return result; 35373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 35473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 35573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe static const char* ParseNull(const char* arg) { 35673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return (strcmp(arg, "!") == 0) ? nullptr : arg; 35773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 35873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 35973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int RunPreopt() { 36073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags, 36173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe volume_uuid, use_profiles */ 36273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int ret = dexopt(package_parameters_[0], 36373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe atoi(package_parameters_[1]), 36473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe package_parameters_[2], 36573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe package_parameters_[3], 36673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe atoi(package_parameters_[4]), 36773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe package_parameters_[5], 36873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe atoi(package_parameters_[6]), 36973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ParseNull(package_parameters_[7]), 37073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe (atoi(package_parameters_[8]) == 0 ? false : true)); 37173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return ret; 37273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 37373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 37473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe //////////////////////////////////// 37573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Helpers, mostly taken from ART // 37673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe //////////////////////////////////// 37773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 37873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Wrapper on fork/execv to run a command in a subprocess. 37973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) { 38073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string command_line(Join(arg_vector, ' ')); 38173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 38273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_GE(arg_vector.size(), 1U) << command_line; 38373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 38473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Convert the args to char pointers. 38573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char* program = arg_vector[0].c_str(); 38673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::vector<char*> args; 38773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe for (size_t i = 0; i < arg_vector.size(); ++i) { 38873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string& arg = arg_vector[i]; 38973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe char* arg_str = const_cast<char*>(arg.c_str()); 39073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK(arg_str != nullptr) << i; 39173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe args.push_back(arg_str); 39273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 39373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe args.push_back(nullptr); 39473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 39573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Fork and exec. 39673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe pid_t pid = fork(); 39773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (pid == 0) { 39873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // No allocation allowed between fork and exec. 39973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 40073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Change process groups, so we don't get reaped by ProcessManager. 40173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe setpgid(0, 0); 40273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 40373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe execv(program, &args[0]); 40473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 40573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe PLOG(ERROR) << "Failed to execv(" << command_line << ")"; 40673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // _exit to avoid atexit handlers in child. 40773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe _exit(1); 40873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } else { 40973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (pid == -1) { 41073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s", 41173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe command_line.c_str(), strerror(errno)); 41273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 41373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 41473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 41573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // wait for subprocess to finish 41673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int status; 41773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); 41873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (got_pid != pid) { 41973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: " 42073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe "wanted %d, got %d: %s", 42173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe command_line.c_str(), pid, got_pid, strerror(errno)); 42273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 42373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 42473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 42573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status", 42673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe command_line.c_str()); 42773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 42873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 42973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 43073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 43173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 43273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 43373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc. 43473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) { 43573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe constexpr size_t kPageSize = PAGE_SIZE; 43673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_EQ(min_delta % kPageSize, 0u); 43773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_EQ(max_delta % kPageSize, 0u); 43873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_LT(min_delta, max_delta); 43973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 44073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::default_random_engine generator; 44173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe generator.seed(GetSeed()); 44273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta); 44373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int32_t r = distribution(generator); 44473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (r % 2 == 0) { 44573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe r = RoundUp(r, kPageSize); 44673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } else { 44773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe r = RoundDown(r, kPageSize); 44873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 44973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_LE(min_delta, r); 45073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_GE(max_delta, r); 45173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_EQ(r % kPageSize, 0u); 45273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return r; 45373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 45473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 45573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe static uint64_t GetSeed() { 45673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#ifdef __BIONIC__ 45773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Bionic exposes arc4random, use it. 45873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe uint64_t random_data; 45973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe arc4random_buf(&random_data, sizeof(random_data)); 46073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return random_data; 46173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#else 46273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#error "This is only supposed to run with bionic. Otherwise, implement..." 46373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#endif 46473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 46573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 46673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe void AddCompilerOptionFromSystemProperty(const char* system_property, 46773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char* prefix, 46873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe bool runtime, 46973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::vector<std::string>& out) { 47073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const std::string* value = 47173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe system_properties_.GetProperty(system_property); 47273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (value != nullptr) { 47373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (runtime) { 47473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe out.push_back("--runtime-arg"); 47573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 47673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (prefix != nullptr) { 47773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe out.push_back(StringPrintf("%s%s", prefix, value->c_str())); 47873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } else { 47973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe out.push_back(*value); 48073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 48173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 48273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 48373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 48473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Stores the system properties read out of the B partition. We need to use these properties 48573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // to compile, instead of the A properties we could get from init/get_property. 48673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe SystemProperties system_properties_; 48773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 48873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char* package_parameters_[9]; 48973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 49073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Store environment values we need to set. 49173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::vector<std::string> environ_; 49273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}; 49373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 49473dae11162aa61396c06cbdb05b954764e944e02Andreas GampeOTAPreoptService gOps; 49573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 49673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe//////////////////////// 49773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe// Plug-in functions. // 49873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe//////////////////////// 49973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 50073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeint get_property(const char *key, char *value, const char *default_value) { 50173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // TODO: Replace with system-properties map. 50273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return gOps.GetProperty(key, value, default_value); 50373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 50473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 50573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe// Compute the output path of 50673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, 50773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *apk_path, 50873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *instruction_set) { 50973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // TODO: Insert B directory. 51073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe char *file_name_start; 51173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe char *file_name_end; 51273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 51373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe file_name_start = strrchr(apk_path, '/'); 51473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (file_name_start == nullptr) { 51573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); 51673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 51773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 51873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe file_name_end = strrchr(file_name_start, '.'); 51973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (file_name_end == nullptr) { 52073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("apk_path '%s' has no extension\n", apk_path); 52173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 52273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 52373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 52473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // Calculate file_name 52573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe file_name_start++; // Move past '/', is valid as file_name_end is valid. 52673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe size_t file_name_len = file_name_end - file_name_start; 52773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string file_name(file_name_start, file_name_len); 52873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 52973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b 53073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex.b", oat_dir, instruction_set, 53173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe file_name.c_str()); 53273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 53373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 53473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 53573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe/* 53673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * Computes the odex file for the given apk_path and instruction_set. 53773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex 53873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * 53973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * Returns false if it failed to determine the odex file path. 54073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe */ 54173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path, 54273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *instruction_set) { 54373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (StringPrintf("%soat/%s/odex.b", apk_path, instruction_set).length() + 1 > PKG_PATH_MAX) { 54473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); 54573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 54673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 54773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 54873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *path_end = strrchr(apk_path, '/'); 54973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (path_end == nullptr) { 55073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 55173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 55273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 55373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string path_component(apk_path, path_end - apk_path); 55473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 55573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *name_begin = path_end + 1; 55673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *extension_start = strrchr(name_begin, '.'); 55773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (extension_start == nullptr) { 55873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("apk_path '%s' has no extension.\n", apk_path); 55973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 56073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 56173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string name_component(name_begin, extension_start - name_begin); 56273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 56373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string new_path = StringPrintf("%s/oat/%s/%s.odex.b", 56473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe path_component.c_str(), 56573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe instruction_set, 56673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe name_component.c_str()); 56773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe CHECK_LT(new_path.length(), PKG_PATH_MAX); 56873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe strcpy(path, new_path.c_str()); 56973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 57073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 57173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 57273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool create_cache_path(char path[PKG_PATH_MAX], 57373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *src, 57473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char *instruction_set) { 57573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe size_t srclen = strlen(src); 57673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 57773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe /* demand that we are an absolute path */ 57873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 57973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 58073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 58173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 58273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 58373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 58473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 58573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 58673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string from_src = std::string(src + 1); 58773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::replace(from_src.begin(), from_src.end(), '/', '@'); 58873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 58973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe std::string assembled_path = StringPrintf("%s/%s/%s/%s%s", 59073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe OTAPreoptService::kOTADataDirectory, 59173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe DALVIK_CACHE, 59273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe instruction_set, 59373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe from_src.c_str(), 59473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe DALVIK_CACHE_POSTFIX2); 59573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 59673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (assembled_path.length() + 1 > PKG_PATH_MAX) { 59773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 59873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 59973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe strcpy(path, assembled_path.c_str()); 60073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 60173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 60273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 60373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 60473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool initialize_globals() { 60573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe const char* data_path = getenv("ANDROID_DATA"); 60673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (data_path == nullptr) { 60773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Could not find ANDROID_DATA"); 60873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 60973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 61073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return init_globals_from_data_and_root(data_path, kOTARootDirectory); 61173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 61273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 61373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic bool initialize_directories() { 61473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // This is different from the normal installd. We only do the base 61573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe // directory, the rest will be created on demand when each app is compiled. 61673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe mode_t old_umask = umask(0); 61773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG(INFO) << "Old umask: " << old_umask; 61873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (access(OTAPreoptService::kOTADataDirectory, R_OK) < 0) { 61973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Could not access %s\n", OTAPreoptService::kOTADataDirectory); 62073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return false; 62173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 62273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return true; 62373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 62473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 62573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic int log_callback(int type, const char *fmt, ...) { 62673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe va_list ap; 62773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int priority; 62873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 62973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe switch (type) { 63073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe case SELINUX_WARNING: 63173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe priority = ANDROID_LOG_WARN; 63273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe break; 63373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe case SELINUX_INFO: 63473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe priority = ANDROID_LOG_INFO; 63573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe break; 63673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe default: 63773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe priority = ANDROID_LOG_ERROR; 63873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe break; 63973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 64073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe va_start(ap, fmt); 64173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe LOG_PRI_VA(priority, "SELinux", fmt, ap); 64273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe va_end(ap); 64373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return 0; 64473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 64573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 64673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic int otapreopt_main(const int argc, char *argv[]) { 64773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int selinux_enabled = (is_selinux_enabled() > 0); 64873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 64973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe setenv("ANDROID_LOG_TAGS", "*:v", 1); 65073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe android::base::InitLogging(argv); 65173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 65273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGI("otapreopt firing up\n"); 65373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 65473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (argc < 2) { 65573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Expecting parameters"); 65673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe exit(1); 65773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 65873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 65973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe union selinux_callback cb; 66073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe cb.func_log = log_callback; 66173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe selinux_set_callback(SELINUX_CB_LOG, cb); 66273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 66373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!initialize_globals()) { 66473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Could not initialize globals; exiting.\n"); 66573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe exit(1); 66673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 66773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 66873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (!initialize_directories()) { 66973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Could not create directories; exiting.\n"); 67073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe exit(1); 67173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 67273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 67373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe if (selinux_enabled && selinux_status_open(true) < 0) { 67473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe ALOGE("Could not open selinux status; exiting.\n"); 67573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe exit(1); 67673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe } 67773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 67873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe int ret = android::installd::gOps.Main(argc, argv); 67973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 68073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return ret; 68173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 68273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 68373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} // namespace installd 68473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} // namespace android 68573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe 68673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeint main(const int argc, char *argv[]) { 68773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe return android::installd::otapreopt_main(argc, argv); 68873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe} 689