Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adc0b87e authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AssetManager2: Fix list function

List was skipping directories. Include them, and add tests to ensure
the order and precedence is correct.

Bug: 72511641
Test: make libandroidfw_tests
Test: atest CtsContentTestCases:AssetManagerTest
Change-Id: Iadf45883283d3e4aae93bd7c3343745912e34fa0
parent 1b6f5155
Loading
Loading
Loading
Loading
+12 −20
Original line number Diff line number Diff line
@@ -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.
+10 −6
Original line number Diff line number Diff line
@@ -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.
+70 −2
Original line number Diff line number Diff line
@@ -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 {
@@ -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:
@@ -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) {
@@ -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
+264 B (1.37 KiB)

File changed.

No diff preview for this file type.

+1 −0
Original line number Diff line number Diff line
app file
Loading