Fix buildbots hidden_api_test

Target buildbots set /system to be the runtime module root because they
are running without an apex. The test assumes that /system dex files are assigned
to the application domain but here they get assigned to the core-platform domain.

Adjust the domain setting logic to check if the runtime module root is
distict from the android root (as a proxy for 'is running with apex').
If not (as is the case with the buildbots), skip checks against apex
locations.

Test: m test-art-target-gtest-hidden_api_test
Change-Id: Iff3890ec69cb04a1e4ed5bc2a3b5c652ada05f36
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 1f8457a..865c8a6 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -334,6 +334,16 @@
   return android::base::StartsWith(full_path, framework_path);
 }
 
+bool RuntimeModuleRootDistinctFromAndroidRoot() {
+  std::string error_msg;
+  std::string android_root = GetAndroidRootSafe(&error_msg);
+  const char* runtime_root =
+      GetAndroidDirSafe(kRuntimeApexEnvVar, kRuntimeApexDefaultPath, &error_msg);
+  return !android_root.empty()
+      && (runtime_root != nullptr)
+      && (android_root != std::string_view(runtime_root));
+}
+
 int DupCloexec(int fd) {
 #if defined(__linux__)
   return fcntl(fd, F_DUPFD_CLOEXEC, 0);
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index 1da19c8..c5e55d1 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -90,6 +90,10 @@
 // Return whether the location is on /apex/.
 bool LocationIsOnApex(const char* location);
 
+// Compare the runtime module root against android root. Returns true if they are
+// both known and distinct. This is meant to be a proxy for 'running with apex'.
+bool RuntimeModuleRootDistinctFromAndroidRoot();
+
 // dup(2), except setting the O_CLOEXEC flag atomically, when possible.
 int DupCloexec(int fd);
 
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 23e2e1f..4ef3842 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -76,20 +76,23 @@
 static Domain DetermineDomainFromPath_Impl(const std::string& path,
                                            const std::string& dex_location,
                                            ObjPtr<mirror::ClassLoader> class_loader) {
-  // We check /system/framework before the runtime module location, because the
-  // runtime module location in a testing environment could be /system.
+  // If running with APEX, check `path` against known APEX locations.
+  // These checks will be skipped on target buildbots where ANDROID_RUNTIME_ROOT
+  // is set to "/system".
+  if (RuntimeModuleRootDistinctFromAndroidRoot()) {
+    if (LocationIsOnRuntimeModule(path.c_str()) || LocationIsOnConscryptModule(path.c_str())) {
+      return Domain::kCorePlatform;
+    }
+
+    if (LocationIsOnApex(path.c_str())) {
+      return Domain::kPlatform;
+    }
+  }
+
   if (LocationIsOnSystemFramework(path.c_str())) {
     return Domain::kPlatform;
   }
 
-  if (LocationIsOnRuntimeModule(path.c_str()) || LocationIsOnConscryptModule(path.c_str())) {
-    return Domain::kCorePlatform;
-  }
-
-  if (LocationIsOnApex(path.c_str())) {
-    return Domain::kPlatform;
-  }
-
   if (class_loader.IsNull()) {
     LOG(WARNING) << "DexFile " << dex_location
         << " is in boot class path but its path " << path << " is not in a known location";
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index be64079..70fafe6 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -17,6 +17,7 @@
 #include "hidden_api.h"
 
 #include <fstream>
+#include <sstream>
 
 #include "base/file_utils.h"
 #include "base/sdk_version.h"
@@ -431,20 +432,25 @@
 
 static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
                                      const std::vector<std::unique_ptr<const DexFile>>& dex_files,
-                                     hiddenapi::Domain expected_domain)
+                                     hiddenapi::Domain expected_domain,
+                                     /* out */ std::string* error_msg)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   for (const auto& dex_file : dex_files) {
     hiddenapi::AccessContext context(loader, dex_file.get());
     if (context.GetDomain() != expected_domain) {
-      LOG(ERROR) << dex_file->GetLocation() << ": access context domain does not match "
+      std::stringstream ss;
+      ss << dex_file->GetLocation() << ": access context domain does not match "
           << "(expected=" << static_cast<uint32_t>(expected_domain)
           << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
+      *error_msg = ss.str();
       return false;
     }
     if (dex_file->GetHiddenapiDomain() != expected_domain) {
-      LOG(ERROR) << dex_file->GetLocation() << ": dex file domain does not match "
+      std::stringstream ss;
+      ss << dex_file->GetLocation() << ": dex file domain does not match "
           << "(expected=" << static_cast<uint32_t>(expected_domain)
           << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
+      *error_msg = ss.str();
       return false;
     }
   }
@@ -466,7 +472,10 @@
   ASSERT_TRUE(LoadDexFiles(data_location_path, soa, &dex_files, &class_loader, &error_msg))
       << error_msg;
   ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kApplication));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kApplication,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(data_location_path.c_str()));
@@ -486,7 +495,10 @@
   ASSERT_TRUE(LoadDexFiles(system_location_path, soa, &dex_files, &class_loader, &error_msg))
       << error_msg;
   ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kApplication));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kApplication,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(system_location_path.c_str()));
@@ -510,7 +522,10 @@
                            &class_loader,
                            &error_msg)) << error_msg;
   ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kPlatform));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kPlatform,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
@@ -531,7 +546,10 @@
   ASSERT_TRUE(LoadDexFiles(data_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
       << error_msg;
   ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kApplication));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kApplication,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
@@ -553,7 +571,10 @@
   ASSERT_TRUE(LoadDexFiles(system_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
       << error_msg;
   ASSERT_GT(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kApplication));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kApplication,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
@@ -579,7 +600,10 @@
                            &class_loader,
                            &error_msg)) << error_msg;
   ASSERT_GT(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader, dex_files, hiddenapi::Domain::kPlatform));
+  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                       dex_files,
+                                       hiddenapi::Domain::kPlatform,
+                                       &error_msg)) << error_msg;
 
   dex_files.clear();
   ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));