return result;
}
-// Java: dalvik.system.DexFile.UP_TO_DATE
-static const jbyte kUpToDate = 0;
-// Java: dalvik.system.DexFile.DEXOPT_NEEDED
-static const jbyte kPatchoatNeeded = 1;
-// Java: dalvik.system.DexFile.PATCHOAT_NEEDED
-static const jbyte kDexoptNeeded = 2;
-
-static jbyte IsDexOptNeededInternal(JNIEnv* env, const char* filename,
+static jint GetDexOptNeeded(JNIEnv* env, const char* filename,
const char* pkgname, const char* instruction_set, const jboolean defer) {
if ((filename == nullptr) || !OS::FileExists(filename)) {
- LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist";
+ LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist";
ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
const char* message = (filename == nullptr) ? "<empty file name>" : filename;
env->ThrowNew(fnfe.get(), message);
- return kUpToDate;
+ return OatFileAssistant::kNoDexOptNeeded;
}
const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
// Always treat elements of the bootclasspath as up-to-date.
if (oat_file_assistant.IsInBootClassPath()) {
- return kUpToDate;
+ return OatFileAssistant::kNoDexOptNeeded;
}
// TODO: Checking the profile should probably be done in the GetStatus()
if (!defer) {
oat_file_assistant.CopyProfileFile();
}
- return kDexoptNeeded;
+ return OatFileAssistant::kDex2OatNeeded;
} else if (oat_file_assistant.ProfileExists()
&& !oat_file_assistant.OldProfileExists()) {
if (!defer) {
}
}
- OatFileAssistant::Status status = oat_file_assistant.GetStatus();
- switch (status) {
- case OatFileAssistant::kUpToDate: return kUpToDate;
- case OatFileAssistant::kNeedsRelocation: return kPatchoatNeeded;
- case OatFileAssistant::kOutOfDate: return kDexoptNeeded;
- }
- UNREACHABLE();
+ return oat_file_assistant.GetDexOptNeeded();
}
-static jbyte DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring javaFilename,
+static jint DexFile_getDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename,
jstring javaPkgname, jstring javaInstructionSet, jboolean defer) {
ScopedUtfChars filename(env, javaFilename);
if (env->ExceptionCheck()) {
return 0;
}
- return IsDexOptNeededInternal(env, filename.c_str(), pkgname.c_str(),
- instruction_set.c_str(), defer);
+ return GetDexOptNeeded(env, filename.c_str(), pkgname.c_str(),
+ instruction_set.c_str(), defer);
}
// public API, NULL pkgname
static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) {
const char* instruction_set = GetInstructionSetString(kRuntimeISA);
ScopedUtfChars filename(env, javaFilename);
- return kUpToDate != IsDexOptNeededInternal(env, filename.c_str(), nullptr /* pkgname */,
- instruction_set, false /* defer */);
+ jint status = GetDexOptNeeded(env, filename.c_str(), nullptr /* pkgname */,
+ instruction_set, false /* defer */);
+ return (status != OatFileAssistant::kNoDexOptNeeded) ? JNI_TRUE : JNI_FALSE;
}
-
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)V"),
NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;)Ljava/lang/Class;"),
NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"),
NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
- NATIVE_METHOD(DexFile, isDexOptNeededInternal, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)B"),
+ NATIVE_METHOD(DexFile, getDexOptNeeded, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I"),
NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Object;"),
};
return true;
}
-OatFileAssistant::Status OatFileAssistant::GetStatus() {
+OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded() {
// TODO: If the profiling code is ever restored, it's worth considering
// whether we should check to see if the profile is out of date here.
- if (OdexFileIsOutOfDate()) {
- // The DEX file is not pre-compiled.
- // TODO: What if the oat file is not out of date? Could we relocate it
- // from itself?
- return OatFileIsUpToDate() ? kUpToDate : kOutOfDate;
- } else {
- // The DEX file is pre-compiled. If the oat file isn't up to date, we can
- // patch the pre-compiled version rather than recompiling.
- if (OatFileIsUpToDate() || OdexFileIsUpToDate()) {
- return kUpToDate;
- } else {
- return kNeedsRelocation;
- }
+ if (OatFileIsUpToDate() || OdexFileIsUpToDate()) {
+ return kNoDexOptNeeded;
}
+
+ if (OdexFileNeedsRelocation()) {
+ return kPatchOatNeeded;
+ }
+
+ if (OatFileNeedsRelocation()) {
+ return kSelfPatchOatNeeded;
+ }
+
+ return kDex2OatNeeded;
}
bool OatFileAssistant::MakeUpToDate(std::string* error_msg) {
- switch (GetStatus()) {
- case kUpToDate: return true;
- case kNeedsRelocation: return RelocateOatFile(error_msg);
- case kOutOfDate: return GenerateOatFile(error_msg);
+ switch (GetDexOptNeeded()) {
+ case kNoDexOptNeeded: return true;
+ case kDex2OatNeeded: return GenerateOatFile(error_msg);
+ case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
+ case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
}
UNREACHABLE();
}
return GetOdexFile() != nullptr;
}
-OatFileAssistant::Status OatFileAssistant::OdexFileStatus() {
+OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
if (OdexFileIsOutOfDate()) {
- return kOutOfDate;
+ return kOatOutOfDate;
}
if (OdexFileIsUpToDate()) {
- return kUpToDate;
+ return kOatUpToDate;
}
- return kNeedsRelocation;
+ return kOatNeedsRelocation;
}
bool OatFileAssistant::OdexFileIsOutOfDate() {
}
bool OatFileAssistant::OdexFileNeedsRelocation() {
- return OdexFileStatus() == kNeedsRelocation;
+ return OdexFileStatus() == kOatNeedsRelocation;
}
bool OatFileAssistant::OdexFileIsUpToDate() {
return GetOatFile() != nullptr;
}
-OatFileAssistant::Status OatFileAssistant::OatFileStatus() {
+OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
if (OatFileIsOutOfDate()) {
- return kOutOfDate;
+ return kOatOutOfDate;
}
if (OatFileIsUpToDate()) {
- return kUpToDate;
+ return kOatUpToDate;
}
- return kNeedsRelocation;
+ return kOatNeedsRelocation;
}
bool OatFileAssistant::OatFileIsOutOfDate() {
}
bool OatFileAssistant::OatFileNeedsRelocation() {
- return OatFileStatus() == kNeedsRelocation;
+ return OatFileStatus() == kOatNeedsRelocation;
}
bool OatFileAssistant::OatFileIsUpToDate() {
return cached_oat_file_is_up_to_date_;
}
-OatFileAssistant::Status OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
+OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
// TODO: This could cause GivenOatFileIsOutOfDate to be called twice, which
// is more work than we need to do. If performance becomes a concern, and
// this method is actually called, this should be fixed.
if (GivenOatFileIsOutOfDate(file)) {
- return kOutOfDate;
+ return kOatOutOfDate;
}
if (GivenOatFileIsUpToDate(file)) {
- return kUpToDate;
+ return kOatUpToDate;
}
- return kNeedsRelocation;
+ return kOatNeedsRelocation;
}
bool OatFileAssistant::GivenOatFileIsOutOfDate(const OatFile& file) {
}
bool OatFileAssistant::GivenOatFileNeedsRelocation(const OatFile& file) {
- return GivenOatFileStatus(file) == kNeedsRelocation;
+ return GivenOatFileStatus(file) == kOatNeedsRelocation;
}
bool OatFileAssistant::GivenOatFileIsUpToDate(const OatFile& file) {
}
}
-bool OatFileAssistant::RelocateOatFile(std::string* error_msg) {
+bool OatFileAssistant::RelocateOatFile(const std::string* input_file,
+ std::string* error_msg) {
CHECK(error_msg != nullptr);
- if (OdexFileName() == nullptr) {
+ if (input_file == nullptr) {
*error_msg = "Patching of oat file for dex location "
+ std::string(dex_location_)
- + " not attempted because the odex file name could not be determined.";
+ + " not attempted because the input file name could not be determined.";
return false;
}
- const std::string& odex_file_name = *OdexFileName();
+ const std::string& input_file_name = *input_file;
if (OatFileName() == nullptr) {
*error_msg = "Patching of oat file for dex location "
std::vector<std::string> argv;
argv.push_back(runtime->GetPatchoatExecutable());
argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
- argv.push_back("--input-oat-file=" + odex_file_name);
+ argv.push_back("--input-oat-file=" + input_file_name);
argv.push_back("--output-oat-file=" + oat_file_name);
argv.push_back("--patched-image-location=" + image_info->location);
// be restored and tested, or removed.
class OatFileAssistant {
public:
- enum Status {
- // kOutOfDate - An oat file is said to be out of date if the file does not
- // exist, or is out of date with respect to the dex file or boot image.
- kOutOfDate,
-
- // kNeedsRelocation - An oat file is said to need relocation if the code
- // is up to date, but not yet properly relocated for address space layout
- // randomization (ASLR). In this case, the oat file is neither "out of
- // date" nor "up to date".
- kNeedsRelocation,
-
- // kUpToDate - An oat file is said to be up to date if it is not out of
+ enum DexOptNeeded {
+ // kNoDexOptNeeded - The code for this dex location is up to date and can
+ // be used as is.
+ // Matches Java: dalvik.system.DexFile.NO_DEXOPT_NEEDED = 0
+ kNoDexOptNeeded = 0,
+
+ // kDex2OatNeeded - In order to make the code for this dex location up to
+ // date, dex2oat must be run on the dex file.
+ // Matches Java: dalvik.system.DexFile.DEX2OAT_NEEDED = 1
+ kDex2OatNeeded = 1,
+
+ // kPatchOatNeeded - In order to make the code for this dex location up to
+ // date, patchoat must be run on the odex file.
+ // Matches Java: dalvik.system.DexFile.PATCHOAT_NEEDED = 2
+ kPatchOatNeeded = 2,
+
+ // kSelfPatchOatNeeded - In order to make the code for this dex location
+ // up to date, patchoat must be run on the oat file.
+ // Matches Java: dalvik.system.DexFile.SELF_PATCHOAT_NEEDED = 3
+ kSelfPatchOatNeeded = 3,
+ };
+
+ enum OatStatus {
+ // kOatOutOfDate - An oat file is said to be out of date if the file does
+ // not exist, or is out of date with respect to the dex file or boot
+ // image.
+ kOatOutOfDate,
+
+ // kOatNeedsRelocation - An oat file is said to need relocation if the
+ // code is up to date, but not yet properly relocated for address space
+ // layout randomization (ASLR). In this case, the oat file is neither
+ // "out of date" nor "up to date".
+ kOatNeedsRelocation,
+
+ // kOatUpToDate - An oat file is said to be up to date if it is not out of
// date and has been properly relocated for the purposes of ASLR.
- kUpToDate,
+ kOatUpToDate,
};
// Constructs an OatFileAssistant object to assist the oat file
// Typically the dex_location is the absolute path to the original,
// un-optimized dex file.
//
- //
// Note: Currently the dex_location must have an extension.
// TODO: Relax this restriction?
//
// file.
bool Lock(std::string* error_msg);
- // Returns the overall compilation status for the given dex location.
- Status GetStatus();
+ // Return what action needs to be taken to produce up-to-date code for this
+ // dex location.
+ DexOptNeeded GetDexOptNeeded();
// Attempts to generate or relocate the oat file as needed to make it up to
// date.
// determined.
const std::string* OdexFileName();
bool OdexFileExists();
- Status OdexFileStatus();
+ OatStatus OdexFileStatus();
bool OdexFileIsOutOfDate();
bool OdexFileNeedsRelocation();
bool OdexFileIsUpToDate();
// the dex location.
//
// Notes:
- // * To get the overall status of the compiled code for this dex_location,
- // use the GetStatus() method, not the OatFileStatus() method.
// * OatFileName may return null if the oat file name could not be
// determined.
const std::string* OatFileName();
bool OatFileExists();
- Status OatFileStatus();
+ OatStatus OatFileStatus();
bool OatFileIsOutOfDate();
bool OatFileNeedsRelocation();
bool OatFileIsUpToDate();
// These methods return the status for a given opened oat file with respect
// to the dex location.
- Status GivenOatFileStatus(const OatFile& file);
+ OatStatus GivenOatFileStatus(const OatFile& file);
bool GivenOatFileIsOutOfDate(const OatFile& file);
bool GivenOatFileNeedsRelocation(const OatFile& file);
bool GivenOatFileIsUpToDate(const OatFile& file);
// Copy the current profile to the old profile location.
void CopyProfileFile();
- // Generates the oat file by relocation from the odex file.
+ // Generates the oat file by relocation from the named input file.
// This does not check the current status before attempting to relocate the
// oat file.
// Returns true on success.
//
// If there is a failure, the value of error_msg will be set to a string
// describing why there was failure. error_msg must not be nullptr.
- bool RelocateOatFile(std::string* error_msg);
+ bool RelocateOatFile(const std::string* input_file, std::string* error_msg);
// Generate the oat file from the dex file.
// This does not check the current status before attempting to generate the
}
// Case: We have a DEX file, but no OAT file for it.
-// Expect: The oat file status is kOutOfDate.
+// Expect: The status is kDex2OatNeeded.
TEST_F(OatFileAssistantTest, DexNoOat) {
std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
Copy(GetDexSrc1(), dex_location);
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.OdexFileStatus());
+ EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OdexFileStatus());
EXPECT_FALSE(oat_file_assistant.OatFileExists());
EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.OatFileStatus());
+ EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus());
}
// Case: We have no DEX file and no OAT file.
-// Expect: Status is out of date. Loading should fail, but not crash.
+// Expect: Status is kDex2OatNeeded. Loading should fail, but not crash.
TEST_F(OatFileAssistantTest, NoDexNoOat) {
std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
EXPECT_EQ(nullptr, oat_file.get());
}
// Case: We have a DEX file and up-to-date OAT file for it.
-// Expect: The oat file status is kUpToDate.
+// Expect: The status is kNoDexOptNeeded.
TEST_F(OatFileAssistantTest, OatUpToDate) {
std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
Copy(GetDexSrc1(), dex_location);
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
- EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.OatFileStatus());
+ EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
}
// Case: We have a MultiDEX file and up-to-date OAT file for it.
-// Expect: The oat file status is kUpToDate.
+// Expect: The status is kNoDexOptNeeded and we load all dex files.
TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
Copy(GetMultiDexSrc1(), dex_location);
GenerateOatForTest(dex_location.c_str());
- // Verify we can load both dex files.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
+
+ // Verify we can load both dex files.
std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
ASSERT_TRUE(oat_file.get() != nullptr);
EXPECT_TRUE(oat_file->IsExecutable());
// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
// encoded dex locations.
-// Expect: The oat file status is kUpToDate.
+// Expect: The oat file status is kNoDexOptNeeded.
TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
EXPECT_EQ(2u, dex_files.size());
}
-// Case: We have a DEX file and out of date OAT file.
-// Expect: The oat file status is kOutOfDate.
+// Case: We have a DEX file and out-of-date OAT file.
+// Expect: The status is kDex2OatNeeded.
TEST_F(OatFileAssistantTest, OatOutOfDate) {
std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar";
Copy(GetDexSrc2(), dex_location);
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
}
// Case: We have a DEX file and an ODEX file, but no OAT file.
-// Expect: The oat file status is kNeedsRelocation.
+// Expect: The status is kPatchOatNeeded.
TEST_F(OatFileAssistantTest, DexOdexNoOat) {
std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
// Verify the status.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
- EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.OdexFileNeedsRelocation());
EXPECT_FALSE(oat_file_assistant.OatFileExists());
EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
}
// Case: We have a stripped DEX file and an ODEX file, but no OAT file.
-// Expect: The oat file status is kNeedsRelocation.
+// Expect: The status is kPatchOatNeeded
TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
// Verify the status.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
- EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
std::string error_msg;
ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
- EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
EXPECT_EQ(1u, dex_files.size());
}
-// Case: We have a stripped DEX file, an ODEX file, and an out of date OAT file.
-// Expect: The oat file status is kNeedsRelocation.
+// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file.
+// Expect: The status is kPatchOatNeeded.
TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
// Verify the status.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
- EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
std::string error_msg;
ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
- EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
EXPECT_EQ(1u, dex_files.size());
}
+// Case: We have a DEX file, no ODEX file and an OAT file that needs
+// relocation.
+// Expect: The status is kSelfPatchOatNeeded.
+TEST_F(OatFileAssistantTest, SelfRelocation) {
+ std::string dex_location = GetScratchDir() + "/SelfRelocation.jar";
+ std::string oat_location = GetOdexDir() + "/SelfRelocation.oat";
+
+ // Create the dex and odex files
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location, oat_location);
+
+ OatFileAssistant oat_file_assistant(dex_location.c_str(),
+ oat_location.c_str(), kRuntimeISA, true);
+
+ EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
+
+ EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
+ EXPECT_FALSE(oat_file_assistant.OdexFileExists());
+ EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
+ EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
+ EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
+ EXPECT_TRUE(oat_file_assistant.OatFileExists());
+ EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation());
+ EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
+ EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
+
+ // Make the oat file up to date.
+ std::string error_msg;
+ ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
+
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
+
+ EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
+ EXPECT_FALSE(oat_file_assistant.OdexFileExists());
+ EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
+ EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
+ EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
+ EXPECT_TRUE(oat_file_assistant.OatFileExists());
+ EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
+ EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
+ EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
+
+ std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+ ASSERT_TRUE(oat_file.get() != nullptr);
+ EXPECT_TRUE(oat_file->IsExecutable());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
+ EXPECT_EQ(1u, dex_files.size());
+}
+
// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
// OAT files both have patch delta of 0.
-// Expect: It shouldn't crash.
+// Expect: It shouldn't crash, and status is kPatchOatNeeded.
TEST_F(OatFileAssistantTest, OdexOatOverlap) {
std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
OatFileAssistant oat_file_assistant(dex_location.c_str(),
oat_location.c_str(), kRuntimeISA, true);
- EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
}
// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
-// Expect: The oat file status is kUpToDate, because PIC needs no relocation.
+// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
// Verify the status.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_TRUE(oat_file_assistant.OdexFileExists());
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
EXPECT_FALSE(oat_file_assistant.OatFileExists());
EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
EXPECT_FALSE(oat_file_assistant.OatFileExists());
EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());
EXPECT_FALSE(oat_file_assistant.OatFileExists());
EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
}
// Case: Non-standard extension for dex file.
-// Expect: The oat file status is kOutOfDate.
+// Expect: The status is kDex2OatNeeded.
TEST_F(OatFileAssistantTest, LongDexExtension) {
std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
Copy(GetDexSrc1(), dex_location);
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
- EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_FALSE(oat_file_assistant.OdexFileExists());