Loading core/jni/android_util_AssetManager.cpp +12 −20 Original line number Diff line number Diff line Loading @@ -403,38 +403,30 @@ static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring return nullptr; } std::vector<std::string> all_file_paths; { StringPiece normalized_path = path_utf8.c_str(); if (normalized_path.data()[0] == '/') { normalized_path = normalized_path.substr(1); } std::string root_path = StringPrintf("assets/%s", normalized_path.data()); ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); for (const ApkAssets* assets : assetmanager->GetApkAssets()) { assets->ForEachFile(root_path, [&](const StringPiece& file_path, FileType type) { if (type == FileType::kFileTypeRegular) { all_file_paths.push_back(file_path.to_string()); } }); } std::unique_ptr<AssetDir> asset_dir = assetmanager->OpenDir(path_utf8.c_str()); if (asset_dir == nullptr) { jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str()); return nullptr; } jobjectArray array = env->NewObjectArray(all_file_paths.size(), g_stringClass, nullptr); const size_t file_count = asset_dir->getFileCount(); jobjectArray array = env->NewObjectArray(file_count, g_stringClass, nullptr); if (array == nullptr) { return nullptr; } jsize index = 0; for (const std::string& file_path : all_file_paths) { jstring java_string = env->NewStringUTF(file_path.c_str()); for (size_t i = 0; i < file_count; i++) { jstring java_string = env->NewStringUTF(asset_dir->getFileName(i).string()); // Check for errors creating the strings (if malformed or no memory). if (env->ExceptionCheck()) { return nullptr; } env->SetObjectArrayElement(array, index++, java_string); env->SetObjectArrayElement(array, i, java_string); // If we have a large amount of string in our array, we might overflow the // local reference table of the VM. Loading libs/androidfw/ApkAssets.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -231,14 +231,18 @@ bool ApkAssets::ForEachFile(const std::string& root_path, while ((result = ::Next(cookie, &entry, &name)) == 0) { StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length); StringPiece leaf_file_path = full_file_path.substr(root_path_full.size()); if (!leaf_file_path.empty()) { auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/'); if (iter != leaf_file_path.end()) { dirs.insert( leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string()); } else if (!leaf_file_path.empty()) { std::string dir = leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string(); dirs.insert(std::move(dir)); } else { f(leaf_file_path, kFileTypeRegular); } } } ::EndIteration(cookie); // Now present the unique directories. Loading libs/androidfw/tests/AssetManager2_test.cpp +70 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,10 @@ namespace lib_one = com::android::lib_one; namespace lib_two = com::android::lib_two; namespace libclient = com::android::libclient; using ::testing::Eq; using ::testing::NotNull; using ::testing::StrEq; namespace android { class AssetManager2Test : public ::testing::Test { Loading Loading @@ -64,6 +68,9 @@ class AssetManager2Test : public ::testing::Test { system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/); ASSERT_NE(nullptr, system_assets_); app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk"); ASSERT_THAT(app_assets_, NotNull()); } protected: Loading @@ -75,6 +82,7 @@ class AssetManager2Test : public ::testing::Test { std::unique_ptr<const ApkAssets> libclient_assets_; std::unique_ptr<const ApkAssets> appaslib_assets_; std::unique_ptr<const ApkAssets> system_assets_; std::unique_ptr<const ApkAssets> app_assets_; }; TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { Loading Loading @@ -465,8 +473,68 @@ TEST_F(AssetManager2Test, GetResourceId) { assetmanager.GetResourceId("main", "layout", "com.android.basic")); } TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {} TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get()}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/)); ASSERT_THAT(data, NotNull()); EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n")); } TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/)); ASSERT_THAT(data, NotNull()); EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n")); } TEST_F(AssetManager2Test, OpenDir) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get()}); TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {} std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(2u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir"))); EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory)); asset_dir = assetmanager.OpenDir("subdir"); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(1u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); } TEST_F(AssetManager2Test, OpenDirFromManyApks) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(3u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt"))); EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir"))); EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory)); } } // namespace android libs/androidfw/tests/data/app/app.apk +264 B (1.37 KiB) File changed.No diff preview for this file type. View original file View changed file libs/androidfw/tests/data/app/assets/app_file.txt 0 → 100644 +1 −0 Original line number Diff line number Diff line app file Loading
core/jni/android_util_AssetManager.cpp +12 −20 Original line number Diff line number Diff line Loading @@ -403,38 +403,30 @@ static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring return nullptr; } std::vector<std::string> all_file_paths; { StringPiece normalized_path = path_utf8.c_str(); if (normalized_path.data()[0] == '/') { normalized_path = normalized_path.substr(1); } std::string root_path = StringPrintf("assets/%s", normalized_path.data()); ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); for (const ApkAssets* assets : assetmanager->GetApkAssets()) { assets->ForEachFile(root_path, [&](const StringPiece& file_path, FileType type) { if (type == FileType::kFileTypeRegular) { all_file_paths.push_back(file_path.to_string()); } }); } std::unique_ptr<AssetDir> asset_dir = assetmanager->OpenDir(path_utf8.c_str()); if (asset_dir == nullptr) { jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str()); return nullptr; } jobjectArray array = env->NewObjectArray(all_file_paths.size(), g_stringClass, nullptr); const size_t file_count = asset_dir->getFileCount(); jobjectArray array = env->NewObjectArray(file_count, g_stringClass, nullptr); if (array == nullptr) { return nullptr; } jsize index = 0; for (const std::string& file_path : all_file_paths) { jstring java_string = env->NewStringUTF(file_path.c_str()); for (size_t i = 0; i < file_count; i++) { jstring java_string = env->NewStringUTF(asset_dir->getFileName(i).string()); // Check for errors creating the strings (if malformed or no memory). if (env->ExceptionCheck()) { return nullptr; } env->SetObjectArrayElement(array, index++, java_string); env->SetObjectArrayElement(array, i, java_string); // If we have a large amount of string in our array, we might overflow the // local reference table of the VM. Loading
libs/androidfw/ApkAssets.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -231,14 +231,18 @@ bool ApkAssets::ForEachFile(const std::string& root_path, while ((result = ::Next(cookie, &entry, &name)) == 0) { StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length); StringPiece leaf_file_path = full_file_path.substr(root_path_full.size()); if (!leaf_file_path.empty()) { auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/'); if (iter != leaf_file_path.end()) { dirs.insert( leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string()); } else if (!leaf_file_path.empty()) { std::string dir = leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string(); dirs.insert(std::move(dir)); } else { f(leaf_file_path, kFileTypeRegular); } } } ::EndIteration(cookie); // Now present the unique directories. Loading
libs/androidfw/tests/AssetManager2_test.cpp +70 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,10 @@ namespace lib_one = com::android::lib_one; namespace lib_two = com::android::lib_two; namespace libclient = com::android::libclient; using ::testing::Eq; using ::testing::NotNull; using ::testing::StrEq; namespace android { class AssetManager2Test : public ::testing::Test { Loading Loading @@ -64,6 +68,9 @@ class AssetManager2Test : public ::testing::Test { system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/); ASSERT_NE(nullptr, system_assets_); app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk"); ASSERT_THAT(app_assets_, NotNull()); } protected: Loading @@ -75,6 +82,7 @@ class AssetManager2Test : public ::testing::Test { std::unique_ptr<const ApkAssets> libclient_assets_; std::unique_ptr<const ApkAssets> appaslib_assets_; std::unique_ptr<const ApkAssets> system_assets_; std::unique_ptr<const ApkAssets> app_assets_; }; TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { Loading Loading @@ -465,8 +473,68 @@ TEST_F(AssetManager2Test, GetResourceId) { assetmanager.GetResourceId("main", "layout", "com.android.basic")); } TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {} TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get()}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/)); ASSERT_THAT(data, NotNull()); EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n")); } TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/)); ASSERT_THAT(data, NotNull()); EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n")); } TEST_F(AssetManager2Test, OpenDir) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get()}); TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {} std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(2u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir"))); EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory)); asset_dir = assetmanager.OpenDir("subdir"); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(1u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); } TEST_F(AssetManager2Test, OpenDirFromManyApks) { AssetManager2 assetmanager; assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); ASSERT_THAT(asset_dir->getFileCount(), Eq(3u)); EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt"))); EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt"))); EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular)); EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir"))); EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory)); } } // namespace android
libs/androidfw/tests/data/app/app.apk +264 B (1.37 KiB) File changed.No diff preview for this file type. View original file View changed file
libs/androidfw/tests/data/app/assets/app_file.txt 0 → 100644 +1 −0 Original line number Diff line number Diff line app file