Update DexFile_isDexOptNeeded to handle system.img oat files with classes.dex
Change-Id: I564bacec777b745a9c911a8fe8dd98437b1ddd2d
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a904800..990fb62 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -742,38 +742,58 @@
return oat_dex_file->OpenDexFile();
}
-const DexFile* ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
- const std::string& dex_location,
- uint32_t dex_location_checksum) {
- Runtime* runtime = Runtime::Current();
- const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- uint32_t image_checksum = image_header.GetOatChecksum();
- bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum) {
+ Runtime* runtime = Runtime::Current();
+ const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
+ uint32_t image_checksum = image_header.GetOatChecksum();
+ bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
- const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
- CHECK(oat_dex_file != NULL) << oat_file->GetLocation() << " " << dex_location;
- bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+ const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
+ if (oat_dex_file == NULL) {
+ LOG(ERROR) << ".oat file " << oat_file->GetLocation()
+ << " does not contain contents for " << dex_location;
+ std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles();
+ for (size_t i = 0; i < oat_dex_files.size(); i++) {
+ const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
+ LOG(ERROR) << ".oat file " << oat_file->GetLocation()
+ << " contains contents for " << oat_dex_file->GetDexFileLocation();
+ }
+ return false;
+ }
+ bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
- if (image_check && dex_check) {
- RegisterOatFileLocked(*oat_file);
- return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
- }
+ if (image_check && dex_check) {
+ return true;
+ }
- if (!image_check) {
- std::string image_file(image_header.GetImageRoot(
- ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
- LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << image_file
- << " (" << std::hex << image_checksum << ")";
- }
- if (!dex_check) {
- LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << dex_location
- << " (" << std::hex << dex_location_checksum << ")";
- }
- return NULL;
+ if (!image_check) {
+ std::string image_file(image_header.GetImageRoot(
+ ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << image_file
+ << " (" << std::hex << image_checksum << ")";
+ }
+ if (!dex_check) {
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << dex_location
+ << " (" << std::hex << dex_location_checksum << ")";
+ }
+ return false;
+}
+
+const DexFile* ClassLinker::VerifyAndOpenDexFileFromOatFile(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum) {
+ bool verified = VerifyOatFileChecksums(oat_file, dex_location, dex_location_checksum);
+ if (!verified) {
+ return NULL;
+ }
+ RegisterOatFileLocked(*oat_file);
+ return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
}
const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) {
@@ -798,9 +818,9 @@
RegisterOatFileLocked(*oat_file);
return oat_dex_file->OpenDexFile();
}
- const DexFile* dex_file = VerifyOatFileChecksums(oat_file,
- dex_location,
- dex_location_checksum);
+ const DexFile* dex_file = VerifyAndOpenDexFileFromOatFile(oat_file,
+ dex_location,
+ dex_location_checksum);
if (dex_file != NULL) {
return dex_file;
}
@@ -815,9 +835,9 @@
LOG(WARNING) << "Failed to compute checksum: " << dex_location;
return NULL;
}
- const DexFile* dex_file = VerifyOatFileChecksums(oat_file,
- dex_location,
- dex_location_checksum);
+ const DexFile* dex_file = VerifyAndOpenDexFileFromOatFile(oat_file,
+ dex_location,
+ dex_location_checksum);
if (dex_file != NULL) {
return dex_file;
}
diff --git a/src/class_linker.h b/src/class_linker.h
index 26ce31e..8e474df 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -251,6 +251,11 @@
const DexFile* FindDexFileInOatFileFromDexLocation(const std::string& location);
+ // Returns true if oat file contains the dex file with the given location and checksum
+ static bool VerifyOatFileChecksums(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum);
+
// TODO: replace this with multiple methods that allocate the correct managed type.
template <class T>
ObjectArray<T>* AllocObjectArray(size_t length) {
@@ -402,10 +407,10 @@
const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file);
const OatFile* FindOpenedOatFileFromDexLocation(const std::string& dex_location);
const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location);
- const DexFile* VerifyOatFileChecksums(const OatFile* oat_file,
- const std::string& dex_location,
- uint32_t dex_location_checksum)
- EXCLUSIVE_LOCKS_REQUIRED(dex_lock_);
+ const DexFile* VerifyAndOpenDexFileFromOatFile(const OatFile* oat_file,
+ const std::string& dex_location,
+ uint32_t dex_location_checksum)
+ EXCLUSIVE_LOCKS_REQUIRED(dex_lock_);
Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class);
Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype);
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 3bf0ea5..ef38f00 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -192,17 +192,26 @@
}
}
- // If we have an oat file next to the dex file, assume up-to-date.
- // A user build looks like this, and it will have no classes.dex in
- // the input for checksum validation.
+ // Check if we have an oat file next to the dex file.
std::string oat_filename(OatFile::DexFilenameToOatFilename(filename.c_str()));
UniquePtr<const OatFile> oat_file(
OatFile::Open(oat_filename, oat_filename, NULL, OatFile::kRelocNone));
if (oat_file.get() != NULL && oat_file->GetOatDexFile(filename.c_str()) != NULL) {
- if (debug_logging) {
- LOG(INFO) << "DexFile_isDexOptNeeded ignoring precompiled file: " << filename.c_str();
+ uint32_t location_checksum;
+ // If we have no classes.dex checksum such as in a user build, assume up-to-date.
+ if (!DexFile::GetChecksum(filename.c_str(), location_checksum)) {
+ if (debug_logging) {
+ LOG(INFO) << "DexFile_isDexOptNeeded ignoring precompiled stripped file: " << filename.c_str();
+ }
+ return JNI_FALSE;
}
- return JNI_FALSE;
+ if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum)) {
+ if (debug_logging) {
+ LOG(INFO) << "DexFile_isDexOptNeeded precompiled file " << oat_filename
+ << " is up-to-date checksum compared to " << filename.c_str();
+ }
+ return JNI_FALSE;
+ }
}
// Check if we have an oat file in the cache
@@ -223,26 +232,13 @@
return JNI_TRUE;
}
- const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str());
- if (oat_dex_file == NULL) {
- LOG(ERROR) << "DexFile_isDexOptNeeded cache file " << cache_location
- << " does not contain contents for " << filename.c_str();
- std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles();
- for (size_t i = 0; i < oat_dex_files.size(); i++) {
- const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
- LOG(ERROR) << "DexFile_isDexOptNeeded cache file " << cache_location
- << " contains contents for " << oat_dex_file->GetDexFileLocation();
- }
- return JNI_TRUE;
- }
-
uint32_t location_checksum;
if (!DexFile::GetChecksum(filename.c_str(), location_checksum)) {
LOG(ERROR) << "DexFile_isDexOptNeeded failed to compute checksum of " << filename.c_str();
return JNI_TRUE;
}
- if (location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
+ if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum)) {
LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
<< " has out-of-date checksum compared to " << filename.c_str();
return JNI_TRUE;