Reland: Support pass BCP art/vdex/oat files by FD
The original implementation in odrefresh generated inconsistent number
of files between jars and other files. The code is reworked.
Original description:
This is currently used by odrefresh.
Main runtime changes are:
1. When reading the image header, also tries to read from the FD if
provided.
2. Initialize the art/vdex/odex FDs in the boot image chunk if provided.
This allows them to be opened (in case if the file is not accessible
by path) in LoadComponents.
3. OpenBootDexFiles: accept BCP JARs passed as FD, in case if the file
is not accessible by path.
4. The new FDs are passed from new runtime args,
-Xbootclasspath{art,vdex,oat}fds.
It is used in odrefresh to pass the previous output of BCP extensions to
be used in the next phase, system server compilation.
Bug: 193720426
Test: odrefresh --use-compilation-os=10 --force-compile # exit 80
odrefresh --verify # exit 0 (was 79 previosly)
Test: Verify the checksum of output files are the same, with
--use-compilation-os or not, i.e. regardless where the compilation
happens
Test: mma in art/
Test: odsign_e2e_tests
Change-Id: Ie3ae48c7d70a2779cfbd80b307199a0f327c895c
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index e377308..09cdd50 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -423,6 +423,9 @@
return gc::space::ImageSpace::LoadBootImage(/*boot_class_path=*/ boot_class_path,
/*boot_class_path_locations=*/ libcore_dex_files,
/*boot_class_path_fds=*/ std::vector<int>(),
+ /*boot_class_path_image_fds=*/ std::vector<int>(),
+ /*boot_class_path_vdex_fds=*/ std::vector<int>(),
+ /*boot_class_path_oat_fds=*/ std::vector<int>(),
android::base::Split(image_location, ":"),
kRuntimeISA,
relocate,
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index fbf30c4..e7655b0 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -741,7 +741,7 @@
auto bcp_fds = std::vector<std::string>();
for (const std::string& jar : bcp_jars) {
std::unique_ptr<File> jar_file(OS::OpenFileForReading(jar.c_str()));
- if (!jar_file->IsValid()) {
+ if (!jar_file || !jar_file->IsValid()) {
LOG(ERROR) << "Failed to open a BCP jar " << jar;
return false;
}
@@ -753,6 +753,64 @@
return true;
}
+ static void AddCompiledBootClasspathFdsIfAny(
+ /*inout*/ std::vector<std::string>& args,
+ /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
+ const std::vector<std::string>& bcp_jars,
+ const InstructionSet isa) {
+ std::vector<std::string> bcp_image_fds;
+ std::vector<std::string> bcp_oat_fds;
+ std::vector<std::string> bcp_vdex_fds;
+ std::vector<std::unique_ptr<File>> opened_files;
+ bool added_any = false;
+ for (const std::string& jar : bcp_jars) {
+ std::string image_path = GetApexDataBootImage(jar);
+ image_path = image_path.empty() ? "" : GetSystemImageFilename(image_path.c_str(), isa);
+ std::unique_ptr<File> image_file(OS::OpenFileForReading(image_path.c_str()));
+ if (image_file && image_file->IsValid()) {
+ bcp_image_fds.push_back(std::to_string(image_file->Fd()));
+ opened_files.push_back(std::move(image_file));
+ added_any = true;
+ } else {
+ bcp_image_fds.push_back("-1");
+ }
+
+ std::string oat_path = ReplaceFileExtension(image_path, "oat");
+ std::unique_ptr<File> oat_file(OS::OpenFileForReading(oat_path.c_str()));
+ if (oat_file && oat_file->IsValid()) {
+ bcp_oat_fds.push_back(std::to_string(oat_file->Fd()));
+ opened_files.push_back(std::move(oat_file));
+ added_any = true;
+ } else {
+ bcp_oat_fds.push_back("-1");
+ }
+
+ std::string vdex_path = ReplaceFileExtension(image_path, "vdex");
+ std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_path.c_str()));
+ if (vdex_file && vdex_file->IsValid()) {
+ bcp_vdex_fds.push_back(std::to_string(vdex_file->Fd()));
+ opened_files.push_back(std::move(vdex_file));
+ added_any = true;
+ } else {
+ bcp_vdex_fds.push_back("-1");
+ }
+ }
+ // Add same amount of FDs as BCP JARs, or none.
+ if (added_any) {
+ std::move(opened_files.begin(), opened_files.end(), std::back_inserter(output_files));
+
+ args.emplace_back("--runtime-arg");
+ args.emplace_back(Concatenate({"-Xbootclasspathimagefds:",
+ android::base::Join(bcp_image_fds, ':')}));
+ args.emplace_back("--runtime-arg");
+ args.emplace_back(Concatenate({"-Xbootclasspathoatfds:",
+ android::base::Join(bcp_oat_fds, ':')}));
+ args.emplace_back("--runtime-arg");
+ args.emplace_back(Concatenate({"-Xbootclasspathvdexfds:",
+ android::base::Join(bcp_vdex_fds, ':')}));
+ }
+ }
+
WARN_UNUSED bool VerifySystemServerArtifactsAreUpToDate(bool on_system) const {
std::vector<std::string> classloader_context;
for (const std::string& jar_path : systemserver_compilable_jars_) {
@@ -1288,6 +1346,7 @@
if (!AddBootClasspathFds(args, readonly_files_raii, bcp_jars)) {
return false;
}
+ AddCompiledBootClasspathFdsIfAny(args, readonly_files_raii, bcp_jars, isa);
const std::string context_path = android::base::Join(classloader_context, ':');
args.emplace_back(Concatenate({"--class-loader-context=PCL[", context_path, "]"}));
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 7706a5c..55fdb72 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -263,6 +263,9 @@
const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
const std::vector<int>& boot_class_path_fds,
+ const std::vector<int>& boot_class_path_image_fds,
+ const std::vector<int>& boot_class_path_vdex_fds,
+ const std::vector<int>& boot_class_path_oat_fds,
const std::vector<std::string>& image_file_names,
const InstructionSet image_instruction_set,
CollectorType foreground_collector_type,
@@ -464,6 +467,9 @@
if (space::ImageSpace::LoadBootImage(boot_class_path,
boot_class_path_locations,
boot_class_path_fds,
+ boot_class_path_image_fds,
+ boot_class_path_vdex_fds,
+ boot_class_path_oat_fds,
image_file_names,
image_instruction_set,
runtime->ShouldRelocate(),
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 345109d..27616fb 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -202,6 +202,9 @@
const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
const std::vector<int>& boot_class_path_fds,
+ const std::vector<int>& boot_class_path_image_fds,
+ const std::vector<int>& boot_class_path_vdex_fds,
+ const std::vector<int>& boot_class_path_oat_fds,
const std::vector<std::string>& image_file_names,
InstructionSet image_instruction_set,
CollectorType foreground_collector_type,
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index c1410ce..3930ad5 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1418,11 +1418,17 @@
BootImageLayout(ArrayRef<const std::string> image_locations,
ArrayRef<const std::string> boot_class_path,
ArrayRef<const std::string> boot_class_path_locations,
- ArrayRef<const int> boot_class_path_fds)
+ ArrayRef<const int> boot_class_path_fds,
+ ArrayRef<const int> boot_class_path_image_fds,
+ ArrayRef<const int> boot_class_path_vdex_fds,
+ ArrayRef<const int> boot_class_path_oat_fds)
: image_locations_(image_locations),
boot_class_path_(boot_class_path),
boot_class_path_locations_(boot_class_path_locations),
- boot_class_path_fds_(boot_class_path_fds) {}
+ boot_class_path_fds_(boot_class_path_fds),
+ boot_class_path_image_fds_(boot_class_path_image_fds),
+ boot_class_path_vdex_fds_(boot_class_path_vdex_fds),
+ boot_class_path_oat_fds_(boot_class_path_oat_fds) {}
std::string GetPrimaryImageLocation();
@@ -1537,6 +1543,9 @@
ArrayRef<const std::string> boot_class_path_;
ArrayRef<const std::string> boot_class_path_locations_;
ArrayRef<const int> boot_class_path_fds_;
+ ArrayRef<const int> boot_class_path_image_fds_;
+ ArrayRef<const int> boot_class_path_vdex_fds_;
+ ArrayRef<const int> boot_class_path_oat_fds_;
std::vector<ImageChunk> chunks_;
uint32_t base_address_ = 0u;
@@ -1819,8 +1828,19 @@
DCHECK_LT(bcp_index, boot_class_path_.size());
std::string actual_filename = ExpandLocation(base_filename, bcp_index);
+ int bcp_image_fd = bcp_index < boot_class_path_image_fds_.size()
+ ? boot_class_path_image_fds_[bcp_index]
+ : -1;
ImageHeader header;
- if (!ReadSpecificImageHeader(actual_filename.c_str(), &header, error_msg)) {
+ auto image_file = bcp_image_fd >= 0
+ ? std::make_unique<File>(bcp_image_fd, actual_filename, /*check_usage=*/ false)
+ : std::unique_ptr<File>(OS::OpenFileForReading(actual_filename.c_str()));
+ if (!image_file || !image_file->IsOpened()) {
+ *error_msg = StringPrintf("Unable to open file \"%s\" for reading image header",
+ actual_filename.c_str());
+ return false;
+ }
+ if (!ReadSpecificImageHeader(image_file.get(), actual_filename.c_str(), &header, error_msg)) {
return false;
}
const char* file_description = actual_filename.c_str();
@@ -1842,6 +1862,20 @@
chunk.boot_image_component_count = header.GetBootImageComponentCount();
chunk.boot_image_checksum = header.GetBootImageChecksum();
chunk.boot_image_size = header.GetBootImageSize();
+ // When BCP art/vdex/oat FDs are also passed, initialize the chunk accordingly.
+ if (bcp_index < boot_class_path_image_fds_.size()) {
+ // The FD of .art needs to be duplicated because it'll be owned/used later.
+ int fd = boot_class_path_image_fds_[bcp_index];
+ if (fd >= 0) {
+ chunk.art_fd.reset(dup(fd));
+ }
+ }
+ if (bcp_index < boot_class_path_vdex_fds_.size()) {
+ chunk.vdex_fd.reset(boot_class_path_vdex_fds_[bcp_index]);
+ }
+ if (bcp_index < boot_class_path_oat_fds_.size()) {
+ chunk.oat_fd.reset(boot_class_path_oat_fds_[bcp_index]);
+ }
chunks_.push_back(std::move(chunk));
next_bcp_index_ = bcp_index + header.GetComponentCount();
total_component_count_ += header.GetComponentCount();
@@ -2227,6 +2261,9 @@
BootImageLoader(const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
const std::vector<int>& boot_class_path_fds,
+ const std::vector<int>& boot_class_path_image_fds,
+ const std::vector<int>& boot_class_path_vdex_fds,
+ const std::vector<int>& boot_class_path_oat_fds,
const std::vector<std::string>& image_locations,
InstructionSet image_isa,
bool relocate,
@@ -2234,6 +2271,9 @@
: boot_class_path_(boot_class_path),
boot_class_path_locations_(boot_class_path_locations),
boot_class_path_fds_(boot_class_path_fds),
+ boot_class_path_image_fds_(boot_class_path_image_fds),
+ boot_class_path_vdex_fds_(boot_class_path_vdex_fds),
+ boot_class_path_oat_fds_(boot_class_path_oat_fds),
image_locations_(image_locations),
image_isa_(image_isa),
relocate_(relocate),
@@ -2245,7 +2285,10 @@
BootImageLayout layout(image_locations_,
boot_class_path_,
boot_class_path_locations_,
- boot_class_path_fds_);
+ boot_class_path_fds_,
+ boot_class_path_image_fds_,
+ boot_class_path_vdex_fds_,
+ boot_class_path_oat_fds_);
std::string image_location = layout.GetPrimaryImageLocation();
std::string system_filename;
bool found_image = FindImageFilenameImpl(image_location.c_str(),
@@ -2869,6 +2912,7 @@
executable_,
/*low_4gb=*/ false,
dex_filenames,
+ dex_fds,
image_reservation,
error_msg));
// We no longer need the file descriptors and they will be closed by
@@ -3127,6 +3171,9 @@
const ArrayRef<const std::string> boot_class_path_;
const ArrayRef<const std::string> boot_class_path_locations_;
const ArrayRef<const int> boot_class_path_fds_;
+ const ArrayRef<const int> boot_class_path_image_fds_;
+ const ArrayRef<const int> boot_class_path_vdex_fds_;
+ const ArrayRef<const int> boot_class_path_oat_fds_;
const ArrayRef<const std::string> image_locations_;
const InstructionSet image_isa_;
const bool relocate_;
@@ -3144,7 +3191,10 @@
BootImageLayout layout(image_locations_,
boot_class_path_,
boot_class_path_locations_,
- boot_class_path_fds_);
+ boot_class_path_fds_,
+ boot_class_path_image_fds_,
+ boot_class_path_vdex_fds_,
+ boot_class_path_oat_fds_);
if (!layout.LoadFromSystem(image_isa_, error_msg)) {
return false;
}
@@ -3172,7 +3222,10 @@
BootImageLayout layout(ArrayRef<const std::string>(runtime->GetImageLocations()),
ArrayRef<const std::string>(runtime->GetBootClassPath()),
ArrayRef<const std::string>(runtime->GetBootClassPathLocations()),
- ArrayRef<const int>(runtime->GetBootClassPathFds()));
+ ArrayRef<const int>(runtime->GetBootClassPathFds()),
+ ArrayRef<const int>(runtime->GetBootClassPathImageFds()),
+ ArrayRef<const int>(runtime->GetBootClassPathVdexFds()),
+ ArrayRef<const int>(runtime->GetBootClassPathOatFds()));
const std::string image_location = layout.GetPrimaryImageLocation();
std::unique_ptr<ImageHeader> image_header;
std::string error_msg;
@@ -3195,6 +3248,9 @@
const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
const std::vector<int>& boot_class_path_fds,
+ const std::vector<int>& boot_class_path_image_fds,
+ const std::vector<int>& boot_class_path_vdex_fds,
+ const std::vector<int>& boot_class_path_odex_fds,
const std::vector<std::string>& image_locations,
const InstructionSet image_isa,
bool relocate,
@@ -3217,6 +3273,9 @@
BootImageLoader loader(boot_class_path,
boot_class_path_locations,
boot_class_path_fds,
+ boot_class_path_image_fds,
+ boot_class_path_vdex_fds,
+ boot_class_path_odex_fds,
image_locations,
image_isa,
relocate,
@@ -3488,7 +3547,10 @@
BootImageLayout layout(image_locations,
boot_class_path.SubArray(/*pos=*/ 0u, bcp_size),
boot_class_path_locations.SubArray(/*pos=*/ 0u, bcp_size),
- bcp_fds);
+ bcp_fds,
+ /*boot_class_path_image_fds=*/ ArrayRef<const int>(),
+ /*boot_class_path_vdex_fds=*/ ArrayRef<const int>(),
+ /*boot_class_path_oat_fds=*/ ArrayRef<const int>());
std::string primary_image_location = layout.GetPrimaryImageLocation();
std::string system_filename;
bool has_system = false;
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index c8879cb..28cc795 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -125,6 +125,9 @@
const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
const std::vector<int>& boot_class_path_fds,
+ const std::vector<int>& boot_class_path_image_fds,
+ const std::vector<int>& boot_class_path_vdex_fds,
+ const std::vector<int>& boot_class_path_oat_fds,
const std::vector<std::string>& image_locations,
const InstructionSet image_isa,
bool relocate,
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index 5e1bc11..973bf5e 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -137,6 +137,9 @@
return ImageSpace::LoadBootImage(bcp,
bcp_locations,
/*boot_class_path_fds=*/ std::vector<int>(),
+ /*boot_class_path_image_fds=*/ std::vector<int>(),
+ /*boot_class_path_vdex_fds=*/ std::vector<int>(),
+ /*boot_class_path_oat_fds=*/ std::vector<int>(),
full_image_locations,
kRuntimeISA,
/*relocate=*/ false,
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 179cfc9..347b58f 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -127,6 +127,7 @@
bool executable,
bool low_4gb,
ArrayRef<const std::string> dex_filenames,
+ ArrayRef<const int> dex_fds,
/*inout*/MemMap* reservation, // Where to load if not null.
/*out*/std::string* error_msg);
@@ -248,6 +249,7 @@
bool executable,
bool low_4gb,
ArrayRef<const std::string> dex_filenames,
+ ArrayRef<const int> dex_fds,
/*inout*/MemMap* reservation,
/*out*/std::string* error_msg) {
std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
@@ -271,7 +273,7 @@
return nullptr;
}
- if (!ret->Setup(zip_fd, dex_filenames, /*dex_fds=*/ArrayRef<const int>(), error_msg)) {
+ if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
return nullptr;
}
@@ -1831,6 +1833,7 @@
bool executable,
bool low_4gb,
ArrayRef<const std::string> dex_filenames,
+ ArrayRef<const int> dex_fds,
/*inout*/MemMap* reservation,
/*out*/std::string* error_msg) {
CHECK(!oat_location.empty()) << oat_location;
@@ -1846,6 +1849,7 @@
executable,
low_4gb,
dex_filenames,
+ dex_fds,
reservation,
error_msg);
return with_internal;
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index beb231c..5c98176 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -154,6 +154,7 @@
bool executable,
bool low_4gb,
ArrayRef<const std::string> dex_filenames,
+ ArrayRef<const int> dex_fds,
/*inout*/MemMap* reservation, // Where to load if not null.
/*out*/std::string* error_msg);
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 67ee940..109769c 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -877,6 +877,7 @@
executable,
/*low_4gb=*/ false,
dex_locations,
+ /*dex_fds=*/ ArrayRef<const int>(),
/*reservation=*/ nullptr,
&error_msg));
}
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index af45213..f27947e 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -115,6 +115,15 @@
.Define("-Xbootclasspathfds:_")
.WithType<ParseIntList<':'>>()
.IntoKey(M::BootClassPathFds)
+ .Define("-Xbootclasspathimagefds:_")
+ .WithType<ParseIntList<':'>>()
+ .IntoKey(M::BootClassPathImageFds)
+ .Define("-Xbootclasspathvdexfds:_")
+ .WithType<ParseIntList<':'>>()
+ .IntoKey(M::BootClassPathVdexFds)
+ .Define("-Xbootclasspathoatfds:_")
+ .WithType<ParseIntList<':'>>()
+ .IntoKey(M::BootClassPathOatFds)
.Define("-Xcheck:jni")
.IntoKey(M::CheckJni)
.Define("-Xms_")
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 91cbd67..1a0826ce 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1206,6 +1206,7 @@
static size_t OpenBootDexFiles(ArrayRef<const std::string> dex_filenames,
ArrayRef<const std::string> dex_locations,
+ ArrayRef<const int> dex_fds,
std::vector<std::unique_ptr<const DexFile>>* dex_files) {
DCHECK(dex_files != nullptr) << "OpenDexFiles: out-param is nullptr";
size_t failure_count = 0;
@@ -1213,20 +1214,23 @@
for (size_t i = 0; i < dex_filenames.size(); i++) {
const char* dex_filename = dex_filenames[i].c_str();
const char* dex_location = dex_locations[i].c_str();
+ const int dex_fd = i < dex_fds.size() ? dex_fds[i] : -1;
static constexpr bool kVerifyChecksum = true;
std::string error_msg;
- if (!OS::FileExists(dex_filename)) {
+ if (!OS::FileExists(dex_filename) && dex_fd < 0) {
LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'";
continue;
}
bool verify = Runtime::Current()->IsVerificationEnabled();
if (!dex_file_loader.Open(dex_filename,
+ dex_fd,
dex_location,
verify,
kVerifyChecksum,
&error_msg,
dex_files)) {
- LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg;
+ LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "' / fd " << dex_fd
+ << ": " << error_msg;
++failure_count;
}
}
@@ -1413,6 +1417,16 @@
return false;
}
+ boot_class_path_image_fds_ = runtime_options.ReleaseOrDefault(Opt::BootClassPathImageFds);
+ boot_class_path_vdex_fds_ = runtime_options.ReleaseOrDefault(Opt::BootClassPathVdexFds);
+ boot_class_path_oat_fds_ = runtime_options.ReleaseOrDefault(Opt::BootClassPathOatFds);
+ CHECK(boot_class_path_image_fds_.empty() ||
+ boot_class_path_image_fds_.size() == boot_class_path_fds_.size());
+ CHECK(boot_class_path_vdex_fds_.empty() ||
+ boot_class_path_vdex_fds_.size() == boot_class_path_fds_.size());
+ CHECK(boot_class_path_oat_fds_.empty() ||
+ boot_class_path_oat_fds_.size() == boot_class_path_fds_.size());
+
class_path_string_ = runtime_options.ReleaseOrDefault(Opt::ClassPath);
properties_ = runtime_options.ReleaseOrDefault(Opt::PropertiesList);
@@ -1537,6 +1551,9 @@
GetBootClassPath(),
GetBootClassPathLocations(),
GetBootClassPathFds(),
+ GetBootClassPathImageFds(),
+ GetBootClassPathVdexFds(),
+ GetBootClassPathOatFds(),
image_locations_,
instruction_set_,
// Override the collector type to CC if the read barrier config.
@@ -1744,8 +1761,12 @@
if (runtime_options.Exists(Opt::BootClassPathDexList)) {
extra_boot_class_path.swap(*runtime_options.GetOrDefault(Opt::BootClassPathDexList));
} else {
+ ArrayRef<const int> bcp_fds = start < GetBootClassPathFds().size()
+ ? ArrayRef<const int>(GetBootClassPathFds()).SubArray(start)
+ : ArrayRef<const int>();
OpenBootDexFiles(ArrayRef<const std::string>(GetBootClassPath()).SubArray(start),
ArrayRef<const std::string>(GetBootClassPathLocations()).SubArray(start),
+ bcp_fds,
&extra_boot_class_path);
}
class_linker_->AddExtraBootDexFiles(self, std::move(extra_boot_class_path));
@@ -1764,6 +1785,7 @@
} else {
OpenBootDexFiles(ArrayRef<const std::string>(GetBootClassPath()),
ArrayRef<const std::string>(GetBootClassPathLocations()),
+ ArrayRef<const int>(GetBootClassPathFds()),
&boot_class_path);
}
if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index eb313e0..221bcaf 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -292,6 +292,18 @@
return boot_class_path_fds_;
}
+ const std::vector<int>& GetBootClassPathImageFds() const {
+ return boot_class_path_image_fds_;
+ }
+
+ const std::vector<int>& GetBootClassPathVdexFds() const {
+ return boot_class_path_vdex_fds_;
+ }
+
+ const std::vector<int>& GetBootClassPathOatFds() const {
+ return boot_class_path_oat_fds_;
+ }
+
// Returns the checksums for the boot image, extensions and extra boot class path dex files,
// based on the image spaces and boot class path dex files loaded in memory.
const std::string& GetBootClassPathChecksums() const {
@@ -1139,6 +1151,9 @@
std::vector<std::string> boot_class_path_locations_;
std::string boot_class_path_checksums_;
std::vector<int> boot_class_path_fds_;
+ std::vector<int> boot_class_path_image_fds_;
+ std::vector<int> boot_class_path_vdex_fds_;
+ std::vector<int> boot_class_path_oat_fds_;
std::string class_path_string_;
std::vector<std::string> properties_;
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index f5085e0..209c3d8 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -41,6 +41,9 @@
RUNTIME_OPTIONS_KEY (ParseStringList<':'>,BootClassPath) // std::vector<std::string>
RUNTIME_OPTIONS_KEY (ParseStringList<':'>,BootClassPathLocations) // std::vector<std::string>
RUNTIME_OPTIONS_KEY (ParseIntList<':'>, BootClassPathFds) // std::vector<int>
+RUNTIME_OPTIONS_KEY (ParseIntList<':'>, BootClassPathImageFds) // std::vector<int>
+RUNTIME_OPTIONS_KEY (ParseIntList<':'>, BootClassPathVdexFds) // std::vector<int>
+RUNTIME_OPTIONS_KEY (ParseIntList<':'>, BootClassPathOatFds) // std::vector<int>
RUNTIME_OPTIONS_KEY (std::string, ClassPath)
RUNTIME_OPTIONS_KEY (ParseStringList<':'>,Image)
RUNTIME_OPTIONS_KEY (Unit, CheckJni)