Handle a potential race when verifying dex files in the background.

In case the runtime has verified a class already, explicitly still
perform another verification in order to get the verifier_deps
populated.

Test: test.py
Change-Id: I17dcec9545dab1b0cae170b584cd091f00145344
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 82b644d..0f5f139 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -148,6 +148,7 @@
 #include "transaction.h"
 #include "vdex_file.h"
 #include "verifier/class_verifier.h"
+#include "verifier/verifier_deps.h"
 #include "well_known_classes.h"
 
 #include "interpreter/interpreter_mterp_impl.h"
@@ -4560,6 +4561,22 @@
     // Don't attempt to re-verify if already verified.
     if (klass->IsVerified()) {
       EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
+      if (verifier_deps != nullptr &&
+          verifier_deps->ContainsDexFile(klass->GetDexFile()) &&
+          !verifier_deps->HasRecordedVerifiedStatus(klass->GetDexFile(), *klass->GetClassDef()) &&
+          !Runtime::Current()->IsAotCompiler()) {
+        // If the klass is verified, but `verifier_deps` did not record it, this
+        // means we are running background verification of a secondary dex file.
+        // Re-run the verifier to populate `verifier_deps`.
+        // No need to run the verification when running on the AOT Compiler, as
+        // the driver handles those multithreaded cases already.
+        std::string error_msg;
+        verifier::FailureKind failure =
+            PerformClassVerification(self, verifier_deps, klass, log_level, &error_msg);
+        // We could have soft failures, so just check that we don't have a hard
+        // failure.
+        DCHECK_NE(failure, verifier::FailureKind::kHardFailure) << error_msg;
+      }
       return verifier::FailureKind::kNoFailure;
     }
 
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index c9128f8..c416c3d 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -308,6 +308,13 @@
   dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
 }
 
+bool VerifierDeps::HasRecordedVerifiedStatus(const DexFile& dex_file,
+                                             const dex::ClassDef& class_def) {
+  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
+  DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
+  return dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)];
+}
+
 void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
                                             const DexFile& dex_file,
                                             const dex::ClassDef& class_def,
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 2e8ef4e..0c448f8 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -124,10 +124,18 @@
     return GetDexFileDeps(dex_file)->verified_classes_;
   }
 
+  // Whether this `verifier_deps` has recorded that the given class is verified.
+  bool HasRecordedVerifiedStatus(const DexFile& dex_file, const dex::ClassDef& class_def)
+      REQUIRES(!Locks::verifier_deps_lock_);
+
   bool OutputOnly() const {
     return output_only_;
   }
 
+  bool ContainsDexFile(const DexFile& dex_file) const {
+    return GetDexFileDeps(dex_file) != nullptr;
+  }
+
   // Parses raw VerifierDeps data to extract bitvectors of which class def indices
   // were verified or not. The given `dex_files` must match the order and count of
   // dex files used to create the VerifierDeps.