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

Commit 5703a0e4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "LoadedArsc: Support feature splits."

parents f0ccd9bd c6aada9c
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -116,7 +116,10 @@ bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTab
                              LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
                              uint32_t* out_flags) const {
  ATRACE_CALL();
  const TypeSpecPtr& ptr = type_specs_[type_idx];

  // If the type IDs are offset in this package, we need to take that into account when searching
  // for a type.
  const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_];
  if (ptr == nullptr) {
    return false;
  }
@@ -334,6 +337,15 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
    loaded_package->dynamic_ = true;
  }

  if (header->header.headerSize >= sizeof(ResTable_package)) {
    uint32_t type_id_offset = dtohl(header->typeIdOffset);
    if (type_id_offset > std::numeric_limits<uint8_t>::max()) {
      LOG(ERROR) << "Type ID offset in RES_TABLE_PACKAGE_TYPE is too large.";
      return {};
    }
    loaded_package->type_id_offset_ = static_cast<int>(type_id_offset);
  }

  util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
                                  &loaded_package->package_name_);

@@ -385,7 +397,6 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
            LOG(ERROR) << "Too many type configurations, overflow detected.";
            return {};
          }

          loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);

          types_builder = {};
@@ -403,6 +414,12 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
          return {};
        }

        if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) >
            std::numeric_limits<uint8_t>::max()) {
          LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has out of range ID.";
          return {};
        }

        // The data portion of this chunk contains entry_count 32bit entries,
        // each one representing a set of flags.
        // Here we only validate that the chunk is well formed.
+1 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ class LoadedPackage {
  std::string package_name_;
  int package_id_ = -1;
  bool dynamic_ = false;
  int type_id_offset_ = 0;

  ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
  std::vector<DynamicPackageEntry> dynamic_package_map_;
+30 −0
Original line number Diff line number Diff line
@@ -139,6 +139,36 @@ TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
}

TEST(LoadedArscTest, LoadFeatureSplit) {
  std::string contents;
  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
                                      &contents));
  std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
  ASSERT_NE(nullptr, loaded_arsc);

  ResTable_config desired_config;
  memset(&desired_config, 0, sizeof(desired_config));

  LoadedArscEntry entry;
  ResTable_config selected_config;
  uint32_t flags;

  ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry,
                                     &selected_config, &flags));

  size_t len;
  const char16_t* type_name16 = entry.type_string_ref.string16(&len);
  ASSERT_NE(nullptr, type_name16);
  ASSERT_NE(0u, len);

  size_t utf8_len = utf16_to_utf8_length(type_name16, len);
  std::string type_name;
  type_name.resize(utf8_len);
  utf16_to_utf8(type_name16, len, &*type_name.begin(), utf8_len + 1);

  EXPECT_EQ(std::string("string"), type_name);
}

// structs with size fields (like Res_value, ResTable_entry) should be
// backwards and forwards compatible (aka checking the size field against
// sizeof(Res_value) might not be backwards compatible.