diff options
| -rw-r--r-- | build/Android.gtest.mk | 2 | ||||
| -rw-r--r-- | libdexfile/dex/art_dex_file_loader.cc | 43 | ||||
| -rw-r--r-- | libdexfile/dex/art_dex_file_loader_test.cc | 178 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 3 | ||||
| -rw-r--r-- | runtime/hidden_api.cc | 69 | ||||
| -rw-r--r-- | runtime/hidden_api.h | 23 | ||||
| -rw-r--r-- | runtime/hidden_api_test.cc | 210 |
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 |