blob: 99e08146b9b0ed58a5c49ef37840dc34861feea5 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "odr_dexopt.h"
#include <vector>
#include "android-base/logging.h"
#include <android-base/result.h>
#include "android-base/strings.h"
#include "exec_utils.h"
#include "log/log.h"
#include "odr_config.h"
#include "libdexopt.h"
#include "aidl/com/android/art/DexoptBcpExtArgs.h"
#include "aidl/com/android/art/DexoptSystemServerArgs.h"
namespace art {
namespace odrefresh {
using aidl::com::android::art::DexoptBcpExtArgs;
using aidl::com::android::art::DexoptSystemServerArgs;
using android::base::Result;
namespace {
int ExecAndReturnCode(ExecUtils* exec_utils,
std::vector<std::string>& cmdline,
time_t timeout_secs,
/*out*/ bool* timed_out,
/*out*/ std::string* error_msg) {
LOG(DEBUG) << "odr_dexopt cmdline: " << android::base::Join(cmdline, ' ') << " [timeout "
<< timeout_secs << "s]";
return exec_utils->ExecAndReturnCode(cmdline, timeout_secs, timed_out, error_msg);
}
class OdrDexoptLocal final : public OdrDexopt {
public:
static OdrDexoptLocal* Create(const std::string& dex2oat_path,
std::unique_ptr<ExecUtils> exec_utils) {
return new OdrDexoptLocal(dex2oat_path, std::move(exec_utils));
}
int DexoptBcpExtension(const DexoptBcpExtArgs& args,
time_t timeout_secs,
/*out*/ bool* timed_out,
/*out*/ std::string* error_msg) override {
std::vector<std::string> cmdline = { dex2oat_path_ };
auto result = art::AddDex2oatArgsFromBcpExtensionArgs(args, cmdline);
if (!result.ok()) {
LOG(ERROR) << "Dexopt (local) failed: " << result.error().message() << ", cmdline: "
<< android::base::Join(cmdline, ' ');
return -1;
}
return ExecAndReturnCode(exec_utils_.get(), cmdline, timeout_secs, timed_out, error_msg);
}
int DexoptSystemServer(const DexoptSystemServerArgs& args,
time_t timeout_secs,
/*out*/ bool* timed_out,
/*out*/ std::string* error_msg) override {
std::vector<std::string> cmdline = { dex2oat_path_ };
auto result = art::AddDex2oatArgsFromSystemServerArgs(args, cmdline);
if (!result.ok()) {
LOG(ERROR) << "Dexopt (local) failed: " << result.error().message() << ", cmdline: "
<< android::base::Join(cmdline, ' ');
return -1;
}
return ExecAndReturnCode(exec_utils_.get(), cmdline, timeout_secs, timed_out, error_msg);
}
private:
OdrDexoptLocal(const std::string& dex2oat_path, std::unique_ptr<ExecUtils> exec_utils)
: dex2oat_path_(dex2oat_path), exec_utils_(std::move(exec_utils)) {}
std::string dex2oat_path_;
std::unique_ptr<ExecUtils> exec_utils_;
};
class OdrDexoptCompilationOS final : public OdrDexopt {
public:
static OdrDexoptCompilationOS* Create(int cid, std::unique_ptr<ExecUtils> exec_utils) {
return new OdrDexoptCompilationOS(cid, std::move(exec_utils));
}
int DexoptBcpExtension(const DexoptBcpExtArgs& args,
time_t timeout_secs,
/*out*/ bool* timed_out,
/*out*/ std::string* error_msg) override {
std::vector<int> input_fds, output_fds;
collectFdsFromDexoptBcpExtensionArgs(input_fds, output_fds, args);
std::vector<std::string> cmdline;
AppendPvmExecArgs(cmdline, input_fds, output_fds);
// Original dex2oat flags
cmdline.push_back("/apex/com.android.art/bin/dex2oat64");
auto result = AddDex2oatArgsFromBcpExtensionArgs(args, cmdline);
if (!result.ok()) {
LOG(ERROR) << "Dexopt (CompOS) failed: " << result.error().message() << ", cmdline: "
<< android::base::Join(cmdline, ' ');
return -1;
}
return ExecAndReturnCode(exec_utils_.get(), cmdline, timeout_secs, timed_out, error_msg);
}
int DexoptSystemServer(const DexoptSystemServerArgs& args,
time_t timeout_secs,
/*out*/ bool* timed_out,
/*out*/ std::string* error_msg) override {
std::vector<int> input_fds, output_fds;
collectFdsFromDexoptSystemServerArgs(input_fds, output_fds, args);
std::vector<std::string> cmdline;
AppendPvmExecArgs(cmdline, input_fds, output_fds);
// Original dex2oat flags
cmdline.push_back("/apex/com.android.art/bin/dex2oat64");
auto result = AddDex2oatArgsFromSystemServerArgs(args, cmdline);
if (!result.ok()) {
LOG(ERROR) << "Dexopt (CompOS) failed: " << result.error().message() << ", cmdline: "
<< android::base::Join(cmdline, ' ');
return -1;
}
LOG(DEBUG) << "DexoptSystemServer cmdline: " << android::base::Join(cmdline, ' ')
<< " [timeout " << timeout_secs << "s]";
return ExecAndReturnCode(exec_utils_.get(), cmdline, timeout_secs, timed_out, error_msg);
}
private:
OdrDexoptCompilationOS(int cid, std::unique_ptr<ExecUtils> exec_utils)
: cid_(cid), exec_utils_(std::move(exec_utils)) {}
void AppendPvmExecArgs(/*inout*/ std::vector<std::string>& cmdline,
const std::vector<int>& input_fds,
const std::vector<int>& output_fds) {
cmdline.emplace_back("/apex/com.android.compos/bin/pvm_exec");
cmdline.emplace_back("--cid=" + std::to_string(cid_));
cmdline.emplace_back("--in-fd=" + android::base::Join(input_fds, ','));
cmdline.emplace_back("--out-fd=" + android::base::Join(output_fds, ','));
cmdline.emplace_back("--");
}
void collectFdsFromDexoptBcpExtensionArgs(/*inout*/ std::vector<int>& input_fds,
/*inout*/ std::vector<int>& output_fds,
const DexoptBcpExtArgs& args) {
// input
insertOnlyNonNegative(input_fds, args.dexFds);
insertIfNonNegative(input_fds, args.profileFd);
insertIfNonNegative(input_fds, args.dirtyImageObjectsFd);
insertOnlyNonNegative(input_fds, args.bootClasspathFds);
// output
insertIfNonNegative(output_fds, args.imageFd);
insertIfNonNegative(output_fds, args.vdexFd);
insertIfNonNegative(output_fds, args.oatFd);
}
void collectFdsFromDexoptSystemServerArgs(/*inout*/ std::vector<int>& input_fds,
/*inout*/ std::vector<int>& output_fds,
const DexoptSystemServerArgs& args) {
// input
insertIfNonNegative(input_fds, args.dexFd);
insertIfNonNegative(input_fds, args.profileFd);
insertOnlyNonNegative(input_fds, args.bootClasspathFds);
insertOnlyNonNegative(input_fds, args.bootClasspathImageFds);
insertOnlyNonNegative(input_fds, args.bootClasspathVdexFds);
insertOnlyNonNegative(input_fds, args.bootClasspathOatFds);
insertOnlyNonNegative(input_fds, args.classloaderFds);
// output
insertIfNonNegative(output_fds, args.imageFd);
insertIfNonNegative(output_fds, args.vdexFd);
insertIfNonNegative(output_fds, args.oatFd);
}
void insertIfNonNegative(/*inout*/ std::vector<int>& vec, int n) {
if (n < 0) {
return;
}
vec.emplace_back(n);
}
void insertOnlyNonNegative(/*inout*/ std::vector<int>& vec, const std::vector<int>& ns) {
std::copy_if(ns.begin(), ns.end(), std::back_inserter(vec), [](int n) { return n >= 0; });
}
int cid_;
std::unique_ptr<ExecUtils> exec_utils_;
};
} // namespace
// static
std::unique_ptr<OdrDexopt> OdrDexopt::Create(const OdrConfig& config,
std::unique_ptr<ExecUtils> exec_utils) {
if (config.UseCompilationOs()) {
int cid = config.GetCompilationOsAddress();
return std::unique_ptr<OdrDexopt>(OdrDexoptCompilationOS::Create(cid, std::move(exec_utils)));
} else {
return std::unique_ptr<OdrDexopt>(OdrDexoptLocal::Create(config.GetDex2Oat(),
std::move(exec_utils)));
}
}
} // namespace odrefresh
} // namespace art