Tolerate not having access or failing to read apex-info-list.xml.

Be more lenient when we fail to read the file, and start executing. The
consequences are likely being unable to load .odex files.

Test: test.py
Change-Id: Ibe9d55db1a086ff966d60ca7c1a4ce0383accd32
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c8464cb..ccd5443 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1291,40 +1291,47 @@
       bcp_apexes.push_back(apex);
     }
   }
-  std::string result;
   static const char* kApexFileName = "/apex/apex-info-list.xml";
-  // When running on host or chroot, we just encode empty markers.
+  // Start with empty markers.
+  apex_versions_ = std::string(bcp_apexes.size(), '/');
+  // When running on host or chroot, we just use empty markers.
   if (!kIsTargetBuild || !OS::FileExists(kApexFileName)) {
-    for (uint32_t i = 0; i < bcp_apexes.size(); ++i) {
-      result += '/';
-    }
-  } else {
+    return;
+  }
 #ifdef ART_TARGET_ANDROID
-    auto info_list = apex::readApexInfoList(kApexFileName);
-    CHECK(info_list.has_value());
-    std::map<std::string_view, const apex::ApexInfo*> apex_infos;
-    for (const apex::ApexInfo& info : info_list->getApexInfo()) {
-      if (info.getIsActive()) {
-        apex_infos.emplace(info.getModuleName(), &info);
-      }
+  if (access(kApexFileName, R_OK) != 0) {
+    PLOG(WARNING) << "Failed to read " << kApexFileName;
+    return;
+  }
+  auto info_list = apex::readApexInfoList(kApexFileName);
+  if (!info_list.has_value()) {
+    LOG(WARNING) << "Failed to parse " << kApexFileName;
+    return;
+  }
+
+  std::string result;
+  std::map<std::string_view, const apex::ApexInfo*> apex_infos;
+  for (const apex::ApexInfo& info : info_list->getApexInfo()) {
+    if (info.getIsActive()) {
+      apex_infos.emplace(info.getModuleName(), &info);
     }
-    for (const std::string_view& str : bcp_apexes) {
-      auto info = apex_infos.find(str);
-      if (info == apex_infos.end() || info->second->getIsFactory()) {
-        result += '/';
-      } else {
-        // In case lastUpdateMillis field is populated in apex-info-list.xml, we
-        // prefer to use it as version scheme. If the field is missing we
-        // fallback to the version code of the APEX.
-        uint64_t version = info->second->hasLastUpdateMillis()
-            ? info->second->getLastUpdateMillis()
-            : info->second->getVersionCode();
-        android::base::StringAppendF(&result, "/%" PRIu64, version);
-      }
+  }
+  for (const std::string_view& str : bcp_apexes) {
+    auto info = apex_infos.find(str);
+    if (info == apex_infos.end() || info->second->getIsFactory()) {
+      result += '/';
+    } else {
+      // In case lastUpdateMillis field is populated in apex-info-list.xml, we
+      // prefer to use it as version scheme. If the field is missing we
+      // fallback to the version code of the APEX.
+      uint64_t version = info->second->hasLastUpdateMillis()
+          ? info->second->getLastUpdateMillis()
+          : info->second->getVersionCode();
+      android::base::StringAppendF(&result, "/%" PRIu64, version);
     }
-#endif
   }
   apex_versions_ = result;
+#endif
 }
 
 void Runtime::ReloadAllFlags(const std::string& caller) {