otapreopt.cpp revision f3e30b936ef103dc0f3d8697e0f86ba82b49609e
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>
336db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampe#include <android-base/strings.h>
3473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/fs.h>
3573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/log.h>
3673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <cutils/properties.h>
3773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#include <private/android_filesystem_config.h>
3873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
39f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "InstalldNativeService.h"
406c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include "dexopt.h"
41f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "file_parsing.h"
42f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "globals.h"
43f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "installd_deps.h"  // Need to fill in requirements of commands.
44f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "otapreopt_utils.h"
45f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "system_properties.h"
46f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "utils.h"
476c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
4873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#ifndef LOG_TAG
4973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define LOG_TAG "otapreopt"
5073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#endif
5173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
5273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define BUFFER_MAX    1024  /* input buffer for commands */
5373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define TOKEN_MAX     16    /* max number of arguments in buffer */
5473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#define REPLY_MAX     256   /* largest reply allowed */
5573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
5656f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampeusing android::base::EndsWith;
576db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampeusing android::base::Join;
586db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampeusing android::base::Split;
5956f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampeusing android::base::StartsWith;
6073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeusing android::base::StringPrintf;
6173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
6273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampenamespace android {
6373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampenamespace installd {
6473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
6573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampetemplate<typename T>
6673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr T RoundDown(T x, typename std::decay<T>::type n) {
6773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
6873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
6973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
7073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampetemplate<typename T>
7173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
7273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return RoundDown(x + n - 1, n);
7373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
7473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
7573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeclass OTAPreoptService {
7673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe public:
7773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Main driver. Performs the following steps.
7873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    //
7973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // 1) Parse options (read system properties etc from B partition).
8073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    //
8173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // 2) Read in package data.
8273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    //
8373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // 3) Prepare environment variables.
8473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    //
8573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // 4) Prepare(compile) boot image, if necessary.
8673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    //
8773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // 5) Run update.
8873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    int Main(int argc, char** argv) {
89d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!ReadArguments(argc, argv)) {
90d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Failed reading command line.";
91d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 1;
92d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
93d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
9473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (!ReadSystemProperties()) {
9573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR)<< "Failed reading system properties.";
96d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 2;
9773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
9873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
9973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (!ReadEnvironment()) {
10073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR) << "Failed reading environment properties.";
101d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 3;
10273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
10373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
104d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!CheckAndInitializeInstalldGlobals()) {
105d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Failed initializing globals.";
106d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 4;
10773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
10873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
10973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        PrepareEnvironment();
11073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
111d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!PrepareBootImage(/* force */ false)) {
11273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR) << "Failed preparing boot image.";
113d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 5;
11473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
11573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
11673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        int dexopt_retcode = RunPreopt();
11773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
11873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return dexopt_retcode;
11973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
12073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
121d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    int GetProperty(const char* key, char* value, const char* default_value) const {
12273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        const std::string* prop_value = system_properties_.GetProperty(key);
12373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (prop_value == nullptr) {
12473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (default_value == nullptr) {
12573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return 0;
12673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
12773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            // Copy in the default value.
12873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            strncpy(value, default_value, kPropertyValueMax - 1);
12973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            value[kPropertyValueMax - 1] = 0;
13073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            return strlen(default_value);// TODO: Need to truncate?
13173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
13273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        size_t size = std::min(kPropertyValueMax - 1, prop_value->length());
13373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        strncpy(value, prop_value->data(), size);
13473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        value[size] = 0;
13573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return static_cast<int>(size);
13673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
13773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
138d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string GetOTADataDirectory() const {
139d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), target_slot_.c_str());
140d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
141d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
142d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    const std::string& GetTargetSlot() const {
143d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return target_slot_;
144d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
145d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
14673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeprivate:
147d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
14873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    bool ReadSystemProperties() {
1491842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        static constexpr const char* kPropertyFiles[] = {
1501842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe                "/default.prop", "/system/build.prop"
1511842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        };
1521842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1531842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
1541842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            if (!system_properties_.Load(kPropertyFiles[i])) {
1551842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe                return false;
1561842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            }
1571842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        }
1581842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1591842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        return true;
16073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
16173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
16273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    bool ReadEnvironment() {
1631842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        // Parse the environment variables from init.environ.rc, which have the form
1641842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        //   export NAME VALUE
1651842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        // For simplicity, don't respect string quotation. The values we are interested in can be
1661842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        // encoded without them.
1671842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
1681842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
1691842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            std::smatch export_match;
1701842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            if (!std::regex_match(line, export_match, export_regex)) {
1711842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe                return true;
1721842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            }
1731842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1741842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            if (export_match.size() != 3) {
1751842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe                return true;
1761842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            }
1771842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1781842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            std::string name = export_match[1].str();
1791842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            std::string value = export_match[2].str();
1801842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1811842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            system_properties_.SetProperty(name, value);
1821842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe
1831842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe            return true;
1841842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        });
1851842af3a4a8fccf71f5c569071518de14b3698acAndreas Gampe        if (!parse_result) {
18673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            return false;
18773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
18873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
189d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
190d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
19173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
192d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        android_data_ = *system_properties_.GetProperty(kAndroidDataPathPropertyName);
193d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
194d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (system_properties_.GetProperty(kAndroidRootPathPropertyName) == nullptr) {
195d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
196d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
197d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        android_root_ = *system_properties_.GetProperty(kAndroidRootPathPropertyName);
198d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
199d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (system_properties_.GetProperty(kBootClassPathPropertyName) == nullptr) {
200d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
201d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
202d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        boot_classpath_ = *system_properties_.GetProperty(kBootClassPathPropertyName);
203d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
204d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) == nullptr) {
205d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
206d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
207d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        asec_mountpoint_ = *system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME);
20873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
20973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return true;
21073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
21173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
212d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    const std::string& GetAndroidData() const {
213d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return android_data_;
214d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
215d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
216d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    const std::string& GetAndroidRoot() const {
217d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return android_root_;
218d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
219d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
220d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    const std::string GetOtaDirectoryPrefix() const {
221d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return GetAndroidData() + "/ota";
222d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
223d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
224d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    bool CheckAndInitializeInstalldGlobals() {
225d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // init_globals_from_data_and_root requires "ASEC_MOUNTPOINT" in the environment. We
226d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // do not use any datapath that includes this, but we'll still have to set it.
227d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        CHECK(system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) != nullptr);
228d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        int result = setenv(ASEC_MOUNTPOINT_ENV_NAME, asec_mountpoint_.c_str(), 0);
229d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (result != 0) {
230d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Could not set ASEC_MOUNTPOINT environment variable";
231d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
232d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
233d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
234d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!init_globals_from_data_and_root(GetAndroidData().c_str(), GetAndroidRoot().c_str())) {
235d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Could not initialize globals; exiting.";
236d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
237d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
238d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
239d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // This is different from the normal installd. We only do the base
240d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // directory, the rest will be created on demand when each app is compiled.
241d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
242d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
243d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
244d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
245d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
246d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return true;
247d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
248d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
249d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    bool ReadArguments(int argc ATTRIBUTE_UNUSED, char** argv) {
250d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Expected command line:
251d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        //   target-slot dexopt {DEXOPT_PARAMETERS}
252d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // The DEXOPT_PARAMETERS are passed on to dexopt(), so we expect DEXOPT_PARAM_COUNT
253d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // of them. We store them in package_parameters_ (size checks are done when
254d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // parsing the special parameters and when copying into package_parameters_.
255d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
256548bdb930895d8fe6651eaada0bc5739ee5248c8Andreas Gampe        static_assert(DEXOPT_PARAM_COUNT == ARRAY_SIZE(package_parameters_),
257548bdb930895d8fe6651eaada0bc5739ee5248c8Andreas Gampe                      "Unexpected dexopt param count");
258d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
259d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        const char* target_slot_arg = argv[1];
260d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (target_slot_arg == nullptr) {
261d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Missing parameters";
262d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
263d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
264d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Sanitize value. Only allow (a-zA-Z0-9_)+.
265d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        target_slot_ = target_slot_arg;
266fd12edaeab839f3f1f087cc75bd18b4d8af5b192Andreas Gampe        if (!ValidateTargetSlotSuffix(target_slot_)) {
267fd12edaeab839f3f1f087cc75bd18b4d8af5b192Andreas Gampe            LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
268fd12edaeab839f3f1f087cc75bd18b4d8af5b192Andreas Gampe            return false;
269d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
270d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
271d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Check for "dexopt" next.
272d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (argv[2] == nullptr) {
273d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Missing parameters";
274d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
275d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
276d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (std::string("dexopt").compare(argv[2]) != 0) {
277d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Second parameter not dexopt: " << argv[2];
278d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
279d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
280d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
281d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Copy the rest into package_parameters_, but be careful about over- and underflow.
282d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        size_t index = 0;
283548bdb930895d8fe6651eaada0bc5739ee5248c8Andreas Gampe        while (index < DEXOPT_PARAM_COUNT &&
284d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                argv[index + 3] != nullptr) {
285d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            package_parameters_[index] = argv[index + 3];
28673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            index++;
28773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
288d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (index != ARRAY_SIZE(package_parameters_) || argv[index + 3] != nullptr) {
28973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR) << "Wrong number of parameters";
29073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            return false;
29173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
29273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
29373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return true;
29473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
29573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
29673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    void PrepareEnvironment() {
297d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str()));
298d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str()));
299d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str()));
30073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
30173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        for (const std::string& e : environ_) {
30273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            putenv(const_cast<char*>(e.c_str()));
30373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
30473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
30573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
30673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Ensure that we have the right boot image. The first time any app is
30773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // compiled, we'll try to generate it.
308d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    bool PrepareBootImage(bool force) const {
30973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (package_parameters_[kISAIndex] == nullptr) {
31073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR) << "Instruction set missing.";
31173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            return false;
31273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
31373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        const char* isa = package_parameters_[kISAIndex];
31473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
31573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // Check whether the file exists where expected.
316d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
31773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::string isa_path = dalvik_cache + "/" + isa;
31873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::string art_path = isa_path + "/system@framework@boot.art";
31973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::string oat_path = isa_path + "/system@framework@boot.oat";
320d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        bool cleared = false;
321d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
322d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            // Files exist, assume everything is alright if not forced. Otherwise clean up.
323d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            if (!force) {
324d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                return true;
325d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            }
326d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            ClearDirectory(isa_path);
327d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            cleared = true;
32873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
32973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
330d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Reset umask in otapreopt, so that we control the the access for the files we create.
331d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        umask(0);
332d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
33373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // Create the directories, if necessary.
33473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (access(dalvik_cache.c_str(), F_OK) != 0) {
335d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            if (!CreatePath(dalvik_cache)) {
336d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                PLOG(ERROR) << "Could not create dalvik-cache dir " << dalvik_cache;
33773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return false;
33873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
33973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
34073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (access(isa_path.c_str(), F_OK) != 0) {
341d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            if (!CreatePath(isa_path)) {
34273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                PLOG(ERROR) << "Could not create dalvik-cache isa dir";
34373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return false;
34473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
34573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
34673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
3475709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        // Prepare to create.
348d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!cleared) {
349d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            ClearDirectory(isa_path);
350d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
35173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
3529fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe        std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
3535709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
3545709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe          return PatchoatBootImage(art_path, isa);
3555709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        } else {
3565709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe          // No preopted boot image. Try to compile.
357d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe          return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
3585709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        }
3595709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe    }
3605709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
361d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static bool CreatePath(const std::string& path) {
362d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Create the given path. Use string processing instead of dirname, as dirname's need for
363d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // a writable char buffer is painful.
364d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
365d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // First, try to use the full path.
366d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (mkdir(path.c_str(), 0711) == 0) {
367d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return true;
368d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
369d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (errno != ENOENT) {
370d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            PLOG(ERROR) << "Could not create path " << path;
371d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
372d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
373d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
374d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Now find the parent and try that first.
375d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        size_t last_slash = path.find_last_of('/');
376d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (last_slash == std::string::npos || last_slash == 0) {
377d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            PLOG(ERROR) << "Could not create " << path;
378d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
379d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
380d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
381d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!CreatePath(path.substr(0, last_slash))) {
382d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return false;
383d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
384d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
385d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (mkdir(path.c_str(), 0711) == 0) {
386d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return true;
387d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
388d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        PLOG(ERROR) << "Could not create " << path;
389d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return false;
390d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
391d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
392d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static void ClearDirectory(const std::string& dir) {
393d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        DIR* c_dir = opendir(dir.c_str());
394d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (c_dir == nullptr) {
395d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
396d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return;
397d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
398d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
399d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
400d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            const char* name = de->d_name;
401d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
402d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                continue;
403d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            }
404d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            // We only want to delete regular files and symbolic links.
405d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            std::string file = StringPrintf("%s/%s", dir.c_str(), name);
406d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            if (de->d_type != DT_REG && de->d_type != DT_LNK) {
407d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                LOG(WARNING) << "Unexpected file "
408d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                             << file
409d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                             << " of type "
410d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                             << std::hex
411d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                             << de->d_type
412d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                             << " encountered.";
413d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            } else {
414d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                // Try to unlink the file.
415d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                if (unlink(file.c_str()) != 0) {
416d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                    PLOG(ERROR) << "Unable to unlink " << file;
417d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                }
418d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            }
419d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
420d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
421d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
422d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
423d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    bool PatchoatBootImage(const std::string& art_path, const char* isa) const {
4245709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
4255709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4265709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        std::vector<std::string> cmd;
4279fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe        cmd.push_back("/system/bin/patchoat");
4285709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4295709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        cmd.push_back("--input-image-location=/system/framework/boot.art");
4305709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
4315709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4325709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
4335709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4345709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
4355709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe                                                          ART_BASE_ADDRESS_MAX_DELTA);
436febf0bf33ca81edcdaab3625e2711fa58b398cc5Andreas Gampe        cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
4375709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4385709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        std::string error_msg;
4395709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        bool result = Exec(cmd, &error_msg);
4405709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        if (!result) {
4415709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe            LOG(ERROR) << "Could not generate boot image: " << error_msg;
4425709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        }
4435709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe        return result;
4445709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe    }
4455709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe
4465709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe    bool Dex2oatBootImage(const std::string& boot_cp,
4475709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe                          const std::string& art_path,
4485709b5758d75085aeab121db94e8d6dbafe0b7aeAndreas Gampe                          const std::string& oat_path,
449d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                          const char* isa) const {
45073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
45173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::vector<std::string> cmd;
4529fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe        cmd.push_back("/system/bin/dex2oat");
45373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
4546db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampe        for (const std::string& boot_part : Split(boot_cp, ":")) {
45573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
45673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
45773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
45873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
45973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
46073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                ART_BASE_ADDRESS_MAX_DELTA);
46173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
46273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
46373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
46473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
46573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp.
46673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms",
46773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "-Xms",
46873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                true,
46973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
47073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx",
47173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "-Xmx",
47273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                true,
47373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
47473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter",
47573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "--compiler-filter=",
47673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                false,
47773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
4789fb85b0667235ebfdea00ea345febc8f6eb203d2Andreas Gampe        cmd.push_back("--image-classes=/system/etc/preloaded-classes");
47973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // TODO: Compiled-classes.
48073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        const std::string* extra_opts =
48173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
48273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (extra_opts != nullptr) {
4836db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampe            std::vector<std::string> extra_vals = Split(*extra_opts, " ");
48473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end());
48573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
48673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // TODO: Should we lower this? It's usually set close to max, because
48773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        //       normally there's not much else going on at boot.
48873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads",
48973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "-j",
49073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                false,
49173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
49273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty(
49373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
49473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "--instruction-set-variant=",
49573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                false,
49673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
49773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        AddCompilerOptionFromSystemProperty(
49873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(),
49973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                "--instruction-set-features=",
50073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                false,
50173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                cmd);
50273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
50373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::string error_msg;
50473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        bool result = Exec(cmd, &error_msg);
50573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (!result) {
50673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            LOG(ERROR) << "Could not generate boot image: " << error_msg;
50773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
50873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return result;
50973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
51073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
51173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    static const char* ParseNull(const char* arg) {
51273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return (strcmp(arg, "!") == 0) ? nullptr : arg;
51373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
51473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
515d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    bool ShouldSkipPreopt() const {
51656f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // There's one thing we have to be careful about: we may/will be asked to compile an app
51756f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // living in the system image. This may be a valid request - if the app wasn't compiled,
51856f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // e.g., if the system image wasn't large enough to include preopted files. However, the
51956f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // data we have is from the old system, so the driver (the OTA service) can't actually
52056f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // know. Thus, we will get requests for apps that have preopted components. To avoid
52156f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // duplication (we'd generate files that are not used and are *not* cleaned up), do two
52256f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // simple checks:
52356f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //
52456f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
52556f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //    (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
52656f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //
52756f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // 2) If you replace the name in the apk_path with "oat," does the path exist?
52856f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //    (=have a subdirectory for preopted files)
52956f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //
53056f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // If the answer to both is yes, skip the dexopt.
53156f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //
53256f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
53356f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //       be stripped), that's not true for APKs signed outside the build system (so the
53456f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //       jar content must be exactly the same).
53556f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe
53656f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //       (This is ugly as it's the only thing where we need to understand the contents
53756f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //        of package_parameters_, but it beats postponing the decision or using the call-
53856f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        //        backs to do weird things.)
53956f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        constexpr size_t kApkPathIndex = 0;
54056f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
54156f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        CHECK(package_parameters_[kApkPathIndex] != nullptr);
542d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (StartsWith(package_parameters_[kApkPathIndex], android_root_.c_str())) {
54356f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe            const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
54456f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe            if (last_slash != nullptr) {
54556f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                std::string path(package_parameters_[kApkPathIndex],
54656f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                                 last_slash - package_parameters_[kApkPathIndex] + 1);
54756f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                CHECK(EndsWith(path, "/"));
54856f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                path = path + "oat";
54956f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                if (access(path.c_str(), F_OK) == 0) {
550d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                    return true;
55156f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe                }
55256f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe            }
55356f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe        }
55456f79f96207c9c0101a5ca0237a8da631d93d5c5Andreas Gampe
555d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Another issue is unavailability of files in the new system. If the partition
556d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // layout changes, otapreopt_chroot may not know about this. Then files from that
557d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // partition will not be available and fail to build. This is problematic, as
558d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // this tool will wipe the OTA artifact cache and try again (for robustness after
559d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // a failed OTA with remaining cache artifacts).
560d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (access(package_parameters_[kApkPathIndex], F_OK) != 0) {
561d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(WARNING) << "Skipping preopt of non-existing package "
562d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                         << package_parameters_[kApkPathIndex];
563d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return true;
564d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
565d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
566d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return false;
567d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
568d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
569d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    int RunPreopt() {
570d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (ShouldSkipPreopt()) {
571d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 0;
572d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
573d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
574d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        int dexopt_result = dexopt(package_parameters_);
575d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (dexopt_result == 0) {
576d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return 0;
577d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
578d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
579d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // If the dexopt failed, we may have a stale boot image from a previous OTA run.
580d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        // Try to delete and retry.
581d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
582d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        if (!PrepareBootImage(/* force */ true)) {
583d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            LOG(ERROR) << "Forced boot image creating failed. Original error return was "
584d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                         << dexopt_result;
585d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            return dexopt_result;
586d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        }
587d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
588d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
589548bdb930895d8fe6651eaada0bc5739ee5248c8Andreas Gampe        return dexopt(package_parameters_);
59073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
59173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
59273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    ////////////////////////////////////
59373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Helpers, mostly taken from ART //
59473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    ////////////////////////////////////
59573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
59673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Wrapper on fork/execv to run a command in a subprocess.
597d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
5986db8db9f3369c48de87f97f4d4636d446837fe32Andreas Gampe        const std::string command_line = Join(arg_vector, ' ');
59973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
60073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_GE(arg_vector.size(), 1U) << command_line;
60173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
60273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // Convert the args to char pointers.
60373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        const char* program = arg_vector[0].c_str();
60473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::vector<char*> args;
60573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        for (size_t i = 0; i < arg_vector.size(); ++i) {
60673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            const std::string& arg = arg_vector[i];
60773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            char* arg_str = const_cast<char*>(arg.c_str());
60873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            CHECK(arg_str != nullptr) << i;
60973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            args.push_back(arg_str);
61073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
61173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        args.push_back(nullptr);
61273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
61373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // Fork and exec.
61473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        pid_t pid = fork();
61573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (pid == 0) {
61673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            // No allocation allowed between fork and exec.
61773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
61873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            // Change process groups, so we don't get reaped by ProcessManager.
61973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            setpgid(0, 0);
62073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
62173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            execv(program, &args[0]);
62273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
62373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            PLOG(ERROR) << "Failed to execv(" << command_line << ")";
62473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            // _exit to avoid atexit handlers in child.
62573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            _exit(1);
62673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        } else {
62773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (pid == -1) {
62873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
62973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                        command_line.c_str(), strerror(errno));
63073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return false;
63173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
63273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
63373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            // wait for subprocess to finish
63473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            int status;
63573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
63673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (got_pid != pid) {
63773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
63873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                        "wanted %d, got %d: %s",
63973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                        command_line.c_str(), pid, got_pid, strerror(errno));
64073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return false;
64173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
64273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
64373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
64473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                        command_line.c_str());
64573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                return false;
64673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
64773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
64873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return true;
64973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
65073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
65173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
65273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
65373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        constexpr size_t kPageSize = PAGE_SIZE;
65473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_EQ(min_delta % kPageSize, 0u);
65573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_EQ(max_delta % kPageSize, 0u);
65673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_LT(min_delta, max_delta);
65773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
65873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::default_random_engine generator;
65973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        generator.seed(GetSeed());
66073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta);
66173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        int32_t r = distribution(generator);
66273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (r % 2 == 0) {
66373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            r = RoundUp(r, kPageSize);
66473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        } else {
66573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            r = RoundDown(r, kPageSize);
66673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
66773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_LE(min_delta, r);
66873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_GE(max_delta, r);
66973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        CHECK_EQ(r % kPageSize, 0u);
67073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return r;
67173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
67273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
67373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    static uint64_t GetSeed() {
67473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#ifdef __BIONIC__
67573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        // Bionic exposes arc4random, use it.
67673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        uint64_t random_data;
67773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        arc4random_buf(&random_data, sizeof(random_data));
67873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return random_data;
67973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#else
68073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#error "This is only supposed to run with bionic. Otherwise, implement..."
68173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe#endif
68273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
68373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
68473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    void AddCompilerOptionFromSystemProperty(const char* system_property,
68573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            const char* prefix,
68673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            bool runtime,
687d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe            std::vector<std::string>& out) const {
688d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        const std::string* value = system_properties_.GetProperty(system_property);
68973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        if (value != nullptr) {
69073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (runtime) {
69173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                out.push_back("--runtime-arg");
69273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
69373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            if (prefix != nullptr) {
69473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                out.push_back(StringPrintf("%s%s", prefix, value->c_str()));
69573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            } else {
69673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                out.push_back(*value);
69773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            }
69873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        }
69973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
70073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
701d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
702d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
703d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static constexpr const char* kAndroidDataPathPropertyName = "ANDROID_DATA";
704d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    // The index of the instruction-set string inside the package parameters. Needed for
705d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    // some special-casing that requires knowledge of the instruction-set.
706d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    static constexpr size_t kISAIndex = 3;
707d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
70873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Stores the system properties read out of the B partition. We need to use these properties
70973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // to compile, instead of the A properties we could get from init/get_property.
71073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    SystemProperties system_properties_;
71173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
712d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    // Some select properties that are always needed.
713d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string target_slot_;
714d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string android_root_;
715d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string android_data_;
716d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string boot_classpath_;
717d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string asec_mountpoint_;
718d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe
719548bdb930895d8fe6651eaada0bc5739ee5248c8Andreas Gampe    const char* package_parameters_[DEXOPT_PARAM_COUNT];
72073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
72173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Store environment values we need to set.
72273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::vector<std::string> environ_;
72373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe};
72473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
72573dae11162aa61396c06cbdb05b954764e944e02Andreas GampeOTAPreoptService gOps;
72673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
72773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe////////////////////////
72873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe// Plug-in functions. //
72973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe////////////////////////
73073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
73173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeint get_property(const char *key, char *value, const char *default_value) {
73273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return gOps.GetProperty(key, value, default_value);
73373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
73473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
73573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe// Compute the output path of
73673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
73773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                             const char *apk_path,
73873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                             const char *instruction_set) {
7399c8f93a2a6ed6a764de7a617fe7a01657d0f4479Dan Austin    const char *file_name_start;
7409c8f93a2a6ed6a764de7a617fe7a01657d0f4479Dan Austin    const char *file_name_end;
74173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
74273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    file_name_start = strrchr(apk_path, '/');
74373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (file_name_start == nullptr) {
74473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
74573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
74673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
74773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    file_name_end = strrchr(file_name_start, '.');
74873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (file_name_end == nullptr) {
74973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("apk_path '%s' has no extension\n", apk_path);
75073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
75173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
75273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
75373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // Calculate file_name
75473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    file_name_start++;  // Move past '/', is valid as file_name_end is valid.
75573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    size_t file_name_len = file_name_end - file_name_start;
75673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::string file_name(file_name_start, file_name_len);
75773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
75873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
759d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    snprintf(path,
760d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             PKG_PATH_MAX,
761d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             "%s/%s/%s.odex.%s",
762d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             oat_dir,
763d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             instruction_set,
764d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             file_name.c_str(),
765d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe             gOps.GetTargetSlot().c_str());
76673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return true;
76773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
76873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
76973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe/*
77073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * Computes the odex file for the given apk_path and instruction_set.
77173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
77273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe *
77373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe * Returns false if it failed to determine the odex file path.
77473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe */
77573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
77673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                              const char *instruction_set) {
77773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    const char *path_end = strrchr(apk_path, '/');
77873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (path_end == nullptr) {
77973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
78073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
78173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
78273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::string path_component(apk_path, path_end - apk_path);
78373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
78473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    const char *name_begin = path_end + 1;
78573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    const char *extension_start = strrchr(name_begin, '.');
78673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (extension_start == nullptr) {
78773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("apk_path '%s' has no extension.\n", apk_path);
78873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
78973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
79073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::string name_component(name_begin, extension_start - name_begin);
79173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
792d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    std::string new_path = StringPrintf("%s/oat/%s/%s.odex.%s",
79373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                                        path_component.c_str(),
79473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                                        instruction_set,
795d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                                        name_component.c_str(),
796d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                                        gOps.GetTargetSlot().c_str());
797d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    if (new_path.length() >= PKG_PATH_MAX) {
798d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        LOG(ERROR) << "apk_path of " << apk_path << " is too long: " << new_path;
799d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe        return false;
800d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe    }
80173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    strcpy(path, new_path.c_str());
80273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return true;
80373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
80473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
80573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampebool create_cache_path(char path[PKG_PATH_MAX],
80673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                       const char *src,
80773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                       const char *instruction_set) {
80873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    size_t srclen = strlen(src);
80973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
81073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        /* demand that we are an absolute path */
81173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
81273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
81373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
81473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
81573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
81673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
81773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
81873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
81973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::string from_src = std::string(src + 1);
82073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::replace(from_src.begin(), from_src.end(), '/', '@');
82173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
82273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
823d089ca1703769854356a263ca640d3e07ab8548dAndreas Gampe                                              gOps.GetOTADataDirectory().c_str(),
82473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                                              DALVIK_CACHE,
82573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                                              instruction_set,
82673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe                                              from_src.c_str(),
827249c1796a2e62f8751348e5bafce9f40e6538cbaDavid Brazdil                                              DALVIK_CACHE_POSTFIX);
82873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
82973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (assembled_path.length() + 1 > PKG_PATH_MAX) {
83073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        return false;
83173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
83273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    strcpy(path, assembled_path.c_str());
83373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
83473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return true;
83573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
83673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
83773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic int log_callback(int type, const char *fmt, ...) {
83873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    va_list ap;
83973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    int priority;
84073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
84173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    switch (type) {
84273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        case SELINUX_WARNING:
84373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            priority = ANDROID_LOG_WARN;
84473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            break;
84573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        case SELINUX_INFO:
84673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            priority = ANDROID_LOG_INFO;
84773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            break;
84873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        default:
84973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            priority = ANDROID_LOG_ERROR;
85073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe            break;
85173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
85273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    va_start(ap, fmt);
85373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    LOG_PRI_VA(priority, "SELinux", fmt, ap);
85473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    va_end(ap);
85573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return 0;
85673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
85773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
85873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampestatic int otapreopt_main(const int argc, char *argv[]) {
85973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    int selinux_enabled = (is_selinux_enabled() > 0);
86073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
86173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    setenv("ANDROID_LOG_TAGS", "*:v", 1);
86273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    android::base::InitLogging(argv);
86373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
86473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (argc < 2) {
86573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("Expecting parameters");
86673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        exit(1);
86773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
86873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
86973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    union selinux_callback cb;
87073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    cb.func_log = log_callback;
87173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    selinux_set_callback(SELINUX_CB_LOG, cb);
87273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
87373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    if (selinux_enabled && selinux_status_open(true) < 0) {
87473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        ALOGE("Could not open selinux status; exiting.\n");
87573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe        exit(1);
87673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    }
87773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
87873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    int ret = android::installd::gOps.Main(argc, argv);
87973dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
88073dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return ret;
88173dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
88273dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
88373dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}  // namespace installd
88473dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}  // namespace android
88573dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe
88673dae11162aa61396c06cbdb05b954764e944e02Andreas Gampeint main(const int argc, char *argv[]) {
88773dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe    return android::installd::otapreopt_main(argc, argv);
88873dae11162aa61396c06cbdb05b954764e944e02Andreas Gampe}
889