diff options
Diffstat (limited to 'runtime/hidden_api_test.cc')
-rw-r--r-- | runtime/hidden_api_test.cc | 210 |
1 files changed, 210 insertions, 0 deletions
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 |