art: Fix classlinker and nopatchoat test for PIC case

ClassLinker should not be checking oat data begin and the patch delta
as part of the checksum verification (when PIC is enabled).

Also update nopatchoat test since it needs to be parametric on whether
PIC is used.

(cherry-picked from AOSP master
230faa7c44ec1986d5fa93d205eb23cb8024e333)

Bug: 18035729

(cherry picked from commit 5ef2990c2933152021633e6697d5325103649499)

Change-Id: Ia0a601c657b813767114095c3b7577421e03bde4
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b24ad4b..64f2484 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1097,9 +1097,13 @@
     image_patch_delta = image_header->GetPatchDelta();
   }
   const OatHeader& oat_header = oat_file->GetOatHeader();
-  bool ret = ((oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum)
-              && (oat_header.GetImagePatchDelta() == image_patch_delta)
-              && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin));
+  bool ret = (oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum);
+
+  // If the oat file is PIC, it doesn't care if/how image was relocated. Ignore these checks.
+  if (!oat_file->IsPic()) {
+    ret = ret && (oat_header.GetImagePatchDelta() == image_patch_delta)
+              && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin);
+  }
   if (!ret) {
     *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d, %d) with (0x%x, %" PRIdPTR ", %d)",
                               oat_file->GetLocation().c_str(),
diff --git a/test/117-nopatchoat/expected.txt b/test/117-nopatchoat/expected.txt
index a1293ae..5cc02d1 100644
--- a/test/117-nopatchoat/expected.txt
+++ b/test/117-nopatchoat/expected.txt
@@ -1,9 +1,9 @@
 Run without dex2oat/patchoat
-dex2oat & patchoat are disabled, has oat is true, has executable oat is false.
+dex2oat & patchoat are disabled, has oat is true, has executable oat is expected.
 This is a function call
 Run with dexoat/patchoat
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
 This is a function call
 Run default
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
 This is a function call
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index 5994653..da276f2 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -24,18 +24,41 @@
 
 class NoPatchoatTest {
  public:
-  static bool hasExecutableOat(jclass cls) {
+  static const OatFile::OatDexFile* getOatDexFile(jclass cls) {
     ScopedObjectAccess soa(Thread::Current());
     mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
     const DexFile& dex_file = klass->GetDexFile();
+
     const OatFile::OatDexFile* oat_dex_file =
         Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
+
+    return oat_dex_file;
+  }
+
+  static bool hasExecutableOat(jclass cls) {
+    const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
     return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable();
   }
+
+  static bool isPic(jclass cls) {
+    const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
+    if (oat_dex_file == nullptr) {
+      return false;
+    }
+
+    const OatFile* oat_file = oat_dex_file->GetOatFile();
+    return oat_file->IsPic();
+  }
 };
 
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasExecutableOat(JNIEnv*, jclass cls) {
   return NoPatchoatTest::hasExecutableOat(cls);
 }
 
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isPic(JNIEnv*, jclass cls) {
+  return NoPatchoatTest::isPic(cls);
+}
+
 }  // namespace art
diff --git a/test/117-nopatchoat/src/Main.java b/test/117-nopatchoat/src/Main.java
index f3f91ce..7bc9dbb 100644
--- a/test/117-nopatchoat/src/Main.java
+++ b/test/117-nopatchoat/src/Main.java
@@ -16,9 +16,14 @@
 
 public class Main {
   public static void main(String[] args) {
+    boolean executable_correct = (isPic() ?
+                                  hasExecutableOat() == true :
+                                  hasExecutableOat() == isDex2OatEnabled());
+
     System.out.println(
         "dex2oat & patchoat are " + ((isDex2OatEnabled()) ? "enabled" : "disabled") +
-        ", has oat is " + hasOat() + ", has executable oat is " + hasExecutableOat() + ".");
+        ", has oat is " + hasOat() + ", has executable oat is " + (
+        executable_correct ? "expected" : "not expected") + ".");
 
     if (!hasOat() && isDex2OatEnabled()) {
       throw new Error("Application with dex2oat enabled runs without an oat file");
@@ -42,6 +47,8 @@
 
   private native static boolean isDex2OatEnabled();
 
+  private native static boolean isPic();
+
   private native static boolean hasOat();
 
   private native static boolean hasExecutableOat();