summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk2
-rw-r--r--libdexfile/dex/art_dex_file_loader.cc43
-rw-r--r--libdexfile/dex/art_dex_file_loader_test.cc178
-rw-r--r--runtime/class_linker.cc3
-rw-r--r--runtime/hidden_api.cc69
-rw-r--r--runtime/hidden_api.h23
-rw-r--r--runtime/hidden_api_test.cc210
7 files changed, 308 insertions, 220 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a2a431226e..e602fa6498 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -190,7 +190,7 @@ ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEP
ART_GTEST_dex2oat_image_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics VerifierDeps
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
ART_GTEST_hiddenapi_test_DEX_DEPS := HiddenApi HiddenApiStubs
-ART_GTEST_hidden_api_test_DEX_DEPS := HiddenApiSignatures
+ART_GTEST_hidden_api_test_DEX_DEPS := HiddenApiSignatures Main MultiDex
ART_GTEST_image_test_DEX_DEPS := ImageLayoutA ImageLayoutB DefaultMethods VerifySoftFailDuringClinit
ART_GTEST_imtable_test_DEX_DEPS := IMTA IMTB
ART_GTEST_instrumentation_test_DEX_DEPS := Instrumentation
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index bfae66724a..e1471f126a 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -527,37 +527,18 @@ std::unique_ptr<DexFile> ArtDexFileLoader::OpenCommon(const uint8_t* base,
std::string* error_msg,
std::unique_ptr<DexFileContainer> container,
VerifyResult* verify_result) {
- std::unique_ptr<DexFile> dex_file = DexFileLoader::OpenCommon(base,
- size,
- data_base,
- data_size,
- location,
- location_checksum,
- oat_dex_file,
- verify,
- verify_checksum,
- error_msg,
- std::move(container),
- verify_result);
- if (dex_file != nullptr) {
- // Set hidden API domain based based on location.
- // Location can contain multidex suffix, so fetch its canonical version. Note
- // that this will call `realpath`.
- std::string path = DexFileLoader::GetDexCanonicalLocation(location.c_str());
- // We check /system/framework before the runtime module location, because the
- // runtime module location in a testing environment could be /system.
- if (LocationIsOnSystemFramework(path.c_str())) {
- dex_file->SetHiddenapiDomain(hiddenapi::Domain::kPlatform);
- } else if (LocationIsOnRuntimeModule(path.c_str()) ||
- LocationIsOnConscryptModule(path.c_str())) {
- dex_file->SetHiddenapiDomain(hiddenapi::Domain::kCorePlatform);
- } else if (LocationIsOnApex(path.c_str())) {
- dex_file->SetHiddenapiDomain(hiddenapi::Domain::kPlatform);
- } else {
- dex_file->SetHiddenapiDomain(hiddenapi::Domain::kApplication);
- }
- }
- return dex_file;
+ return DexFileLoader::OpenCommon(base,
+ size,
+ data_base,
+ data_size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ verify,
+ verify_checksum,
+ error_msg,
+ std::move(container),
+ verify_result);
}
} // namespace art
diff --git a/libdexfile/dex/art_dex_file_loader_test.cc b/libdexfile/dex/art_dex_file_loader_test.cc
index 8c9258ba49..be1221c80d 100644
--- a/libdexfile/dex/art_dex_file_loader_test.cc
+++ b/libdexfile/dex/art_dex_file_loader_test.cc
@@ -18,11 +18,9 @@
#include <sys/mman.h>
-#include <fstream>
#include <memory>
#include "base/common_art_test.h"
-#include "base/file_utils.h"
#include "base/mem_map.h"
#include "base/os.h"
#include "base/stl_util.h"
@@ -37,12 +35,6 @@
namespace art {
-static void Copy(const std::string& src, const std::string& dst) {
- std::ifstream src_stream(src, std::ios::binary);
- std::ofstream dst_stream(dst, std::ios::binary);
- dst_stream << src_stream.rdbuf();
-}
-
class ArtDexFileLoaderTest : public CommonArtTest {
void SetUp() override {
CommonArtTest::SetUp();
@@ -320,174 +312,4 @@ TEST_F(ArtDexFileLoaderTest, GetDexCanonicalLocation) {
ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
}
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir) {
- // Load file from a non-system directory and check that it is not flagged as framework.
- std::string data_location_path = android_data_ + "/foo.jar";
- ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
-
- Copy(GetTestDexFileName("Main"), data_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(data_location_path.c_str(),
- data_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GE(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_NE(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(data_location_path.c_str()));
-}
-
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir) {
- // Load file from a system, non-framework directory and check that it is not flagged as framework.
- std::string system_location_path = GetAndroidRoot() + "/foo.jar";
- ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
-
- Copy(GetTestDexFileName("Main"), system_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(system_location_path.c_str(),
- system_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GE(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_NE(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(system_location_path.c_str()));
-}
-
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir) {
- // Load file from a system/framework directory and check that it is flagged as a framework dex.
- std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
- ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
-
- Copy(GetTestDexFileName("Main"), system_framework_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(system_framework_location_path.c_str(),
- system_framework_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GE(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_EQ(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
-}
-
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir_MultiDex) {
- // Load multidex file from a non-system directory and check that it is not flagged as framework.
- std::string data_multi_location_path = android_data_ + "/multifoo.jar";
- ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
-
- Copy(GetTestDexFileName("MultiDex"), data_multi_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(data_multi_location_path.c_str(),
- data_multi_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GT(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_NE(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
-}
-
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir_MultiDex) {
- // Load multidex file from a system, non-framework directory and check that it is not flagged
- // as framework.
- std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
- ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
-
- Copy(GetTestDexFileName("MultiDex"), system_multi_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(system_multi_location_path.c_str(),
- system_multi_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GT(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_NE(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
-}
-
-TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir_MultiDex) {
- // Load multidex file from a system/framework directory and check that it is flagged as a
- // framework dex.
- std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
- ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
-
- Copy(GetTestDexFileName("MultiDex"), system_framework_multi_location_path);
-
- ArtDexFileLoader loader;
- std::vector<std::unique_ptr<const DexFile>> dex_files;
- std::string error_msg;
- bool success = loader.Open(system_framework_multi_location_path.c_str(),
- system_framework_multi_location_path,
- /* verify= */ false,
- /* verify_checksum= */ false,
- &error_msg,
- &dex_files);
- ASSERT_TRUE(success) << error_msg;
-
- ASSERT_GT(dex_files.size(), 1u);
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- ASSERT_EQ(dex_file->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
- }
-
- dex_files.clear();
-
- ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
-}
-
} // namespace art
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index de9d9ca0c5..e5dcc0d989 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3765,6 +3765,9 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
if (initialize_oat_file_data) {
oat_file->InitializeRelocations();
}
+ // Let hiddenapi assign a domain to the newly registered dex file.
+ hiddenapi::InitializeDexFileDomain(dex_file, class_loader);
+
jweak dex_cache_jweak = vm->AddWeakGlobalRef(self, dex_cache);
dex_cache->SetDexFile(&dex_file);
DexCacheData data;
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index b4585827df..23e2e1fb84 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -21,10 +21,12 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/dumpable.h"
+#include "base/file_utils.h"
#include "class_root.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file_loader.h"
#include "mirror/class_ext.h"
+#include "oat_file.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"
#include "well_known_classes.h"
@@ -71,6 +73,73 @@ static inline std::ostream& operator<<(std::ostream& os, const AccessContext& va
return os;
}
+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 (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";
+ return Domain::kPlatform;
+ }
+
+ return Domain::kApplication;
+}
+
+static bool IsAbsoluteLocation(const std::string& str) {
+ return !str.empty() && str[0] == '/';
+}
+
+void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader) {
+ // TODO(dbrazdil): Fix when preopting on host for target. In that case, the dex location
+ // is the target path and functions in file_utils.h check against host system paths.
+
+ const std::string& dex_location = dex_file.GetLocation();
+ const OatDexFile* const oat_dex_file = dex_file.GetOatDexFile();
+
+ Domain dex_domain = Domain::kApplication;
+ if (IsAbsoluteLocation(dex_location)) {
+ // Resolve realpath() of the dex location.
+ dex_domain = DetermineDomainFromPath_Impl(
+ DexFileLoader::GetDexCanonicalLocation(dex_location.c_str()),
+ dex_location,
+ class_loader);
+ } else if (oat_dex_file != nullptr && !oat_dex_file->GetCanonicalDexFileLocation().empty()) {
+ // If the path is relative, we might find the canonical path in the OatDexFile.
+ dex_domain = DetermineDomainFromPath_Impl(
+ oat_dex_file->GetCanonicalDexFileLocation(),
+ dex_location,
+ class_loader);
+ } else if (class_loader.IsNull()) {
+ LOG(WARNING) << "DexFile " << dex_location
+ << " is in boot class path but has no canonical location";
+ dex_domain = Domain::kPlatform;
+ } else {
+ // No canonical path available, not in boot class path. Conservatively
+ // assign application domain.
+ dex_domain = Domain::kApplication;
+ }
+
+ // Assign the domain unless a more permissive domain has already been assigned.
+ // This may happen when DexFile is initialized as trusted.
+ if (IsDomainMoreTrustedThan(dex_domain, dex_file.GetHiddenapiDomain())) {
+ dex_file.SetHiddenapiDomain(dex_domain);
+ }
+}
+
namespace detail {
// Do not change the values of items in this enum, as they are written to the
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 08a9fff5be..7abdb5d989 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -70,6 +70,12 @@ class AccessContext {
dex_file_(GetDexFileFromDexCache(dex_cache)),
domain_(ComputeDomain(class_loader, dex_file_)) {}
+ // Initialize from class loader and dex file (only used by tests).
+ AccessContext(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file)
+ : klass_(nullptr),
+ dex_file_(dex_file),
+ domain_(ComputeDomain(class_loader, dex_file_)) {}
+
// Initialize from Class.
explicit AccessContext(ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -97,20 +103,12 @@ class AccessContext {
return is_trusted ? Domain::kCorePlatform : Domain::kApplication;
}
- static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file) {
if (dex_file == nullptr) {
return ComputeDomain(/* is_trusted= */ class_loader.IsNull());
}
- Domain dex_domain = dex_file->GetHiddenapiDomain();
- if (class_loader.IsNull() && dex_domain == Domain::kApplication) {
- LOG(WARNING) << "DexFile " << dex_file->GetLocation()
- << " is in boot classpath but is assigned the application domain";
- dex_file->SetHiddenapiDomain(Domain::kPlatform);
- dex_domain = Domain::kPlatform;
- }
- return dex_domain;
+ return dex_file->GetHiddenapiDomain();
}
static Domain ComputeDomain(ObjPtr<mirror::Class> klass, const DexFile* dex_file)
@@ -356,6 +354,11 @@ ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtMethod* method)
}
}
+// Called by class linker when a new dex file has been registered. Assigns
+// the AccessContext domain to the newly-registered dex file based on its
+// location and class loader.
+void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader);
+
// Returns true if access to `member` should be denied in the given context.
// The decision is based on whether the caller is in a trusted context or not.
// Because determining the access context can be expensive, a lambda function
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index cfc3b07300..be6407963b 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -16,10 +16,15 @@
#include "hidden_api.h"
+#include <fstream>
+
+#include "base/file_utils.h"
#include "base/sdk_version.h"
+#include "base/stl_util.h"
#include "common_runtime_test.h"
#include "jni/jni_internal.h"
#include "proxy_test.h"
+#include "well_known_classes.h"
namespace art {
@@ -375,4 +380,209 @@ TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) {
ASSERT_EQ("L$Proxy1234;->interfaces:[Ljava/lang/Class;", ss_field.str());
}
+static bool Copy(const std::string& src, const std::string& dst, /*out*/ std::string* error_msg) {
+ std::ifstream src_stream(src, std::ios::binary);
+ std::ofstream dst_stream(dst, std::ios::binary);
+ dst_stream << src_stream.rdbuf();
+ src_stream.close();
+ dst_stream.close();
+ if (src_stream.good() && dst_stream.good()) {
+ return true;
+ } else {
+ *error_msg = "Copy " + src + " => " + dst + " (src_good="
+ + (src_stream.good() ? "true" : "false") + ", dst_good="
+ + (dst_stream.good() ? "true" : "false") + ")";
+ return false;
+ }
+}
+
+static bool LoadDexFiles(const std::string& path,
+ ScopedObjectAccess& soa,
+ /* out */ std::vector<std::unique_ptr<const DexFile>>* dex_files,
+ /* out */ ObjPtr<mirror::ClassLoader>* class_loader,
+ /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (!ArtDexFileLoader().Open(path.c_str(),
+ path,
+ /* verify= */ true,
+ /* verify_checksum= */ true,
+ error_msg,
+ dex_files)) {
+ return false;
+ }
+
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
+
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::Class> h_class = hs.NewHandle(soa.Decode<mirror::Class>(
+ WellKnownClasses::dalvik_system_PathClassLoader));
+ Handle<mirror::ClassLoader> h_loader = hs.NewHandle(linker->CreateWellKnownClassLoader(
+ soa.Self(),
+ MakeNonOwningPointerVector(*dex_files),
+ h_class,
+ /* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
+ /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
+ for (const auto& dex_file : *dex_files) {
+ linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
+ }
+
+ *class_loader = h_loader.Get();
+ return true;
+}
+
+static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
+ const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+ hiddenapi::Domain expected_domain)
+ 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 "
+ << "(expected=" << static_cast<uint32_t>(expected_domain)
+ << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
+ return false;
+ }
+ if (dex_file->GetHiddenapiDomain() != expected_domain) {
+ LOG(ERROR) << dex_file->GetLocation() << ": dex file domain does not match "
+ << "(expected=" << static_cast<uint32_t>(expected_domain)
+ << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+TEST_F(HiddenApiTest, DexDomain_DataDir) {
+ // Load file from a non-system directory and check that it is not flagged as framework.
+ std::string data_location_path = android_data_ + "/foo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("Main"), data_location_path, &error_msg)) << error_msg;
+ 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));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(data_location_path.c_str()));
+}
+
+TEST_F(HiddenApiTest, DexDomain_SystemDir) {
+ // Load file from a system, non-framework directory and check that it is not flagged as framework.
+ std::string system_location_path = GetAndroidRoot() + "/foo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_location_path, &error_msg)) << error_msg;
+ 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));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(system_location_path.c_str()));
+}
+
+TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir) {
+ // Load file from a system/framework directory and check that it is flagged as a framework dex.
+ std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
+ ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_framework_location_path, &error_msg))
+ << error_msg;
+ ASSERT_TRUE(LoadDexFiles(system_framework_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::kPlatform));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
+}
+
+TEST_F(HiddenApiTest, DexDomain_DataDir_MultiDex) {
+ // Load multidex file from a non-system directory and check that it is not flagged as framework.
+ std::string data_multi_location_path = android_data_ + "/multifoo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), data_multi_location_path, &error_msg))
+ << error_msg;
+ 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));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
+}
+
+TEST_F(HiddenApiTest, DexDomain_SystemDir_MultiDex) {
+ // Load multidex file from a system, non-framework directory and check that it is not flagged
+ // as framework.
+ std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
+ ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), system_multi_location_path, &error_msg))
+ << error_msg;
+ 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));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
+}
+
+TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir_MultiDex) {
+ // Load multidex file from a system/framework directory and check that it is flagged as a
+ // framework dex.
+ std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
+ ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
+
+ ScopedObjectAccess soa(Thread::Current());
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ObjPtr<mirror::ClassLoader> class_loader;
+
+ ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"),
+ system_framework_multi_location_path,
+ &error_msg)) << error_msg;
+ ASSERT_TRUE(LoadDexFiles(system_framework_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::kPlatform));
+
+ dex_files.clear();
+ ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
+}
+
} // namespace art