summaryrefslogtreecommitdiff
path: root/runtime/hidden_api_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/hidden_api_test.cc')
-rw-r--r--runtime/hidden_api_test.cc210
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