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