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

Commit 93a2daf1 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Set array element keys"

parents c5f23bfc 0f7da5ed
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -133,11 +133,10 @@ class MapFlattenVisitor : public ValueVisitor {
  }

  void Visit(Array* array) override {
    for (auto& item : array->elements) {
      ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
      FlattenValue(item.get(), out_entry);
      out_entry->value.size = util::HostToDevice16(sizeof(out_entry->value));
      entry_count_++;
    const size_t count = array->elements.size();
    for (size_t i = 0; i < count; i++) {
      Reference key(android::ResTable_map::ATTR_MIN + i);
      FlattenEntry(&key, array->elements[i].get());
    }
  }

+58 −0
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
#include "format/binary/TableFlattener.h"

#include "android-base/stringprintf.h"
#include "androidfw/TypeWrappers.h"

#include "ResChunkPullParser.h"
#include "ResourceUtils.h"
#include "SdkConstants.h"
#include "format/binary/BinaryResourceParser.h"
@@ -236,6 +238,62 @@ TEST_F(TableFlattenerTest, FlattenMinMaxAttributes) {
  EXPECT_EQ(attr.max_int, actual_attr->max_int);
}

TEST_F(TableFlattenerTest, FlattenArray) {
  auto array = util::make_unique<Array>();
  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
                                                               1u));
  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
                                                               2u));
  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .SetPackageId("android", 0x01)
          .AddValue("android:array/foo", ResourceId(0x01010000), std::move(array))
          .Build();

  std::string result;
  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &result));

  // Parse the flattened resource table
  ResChunkPullParser parser(result.data(), result.size());
  ASSERT_TRUE(parser.IsGoodEvent(parser.Next()));
  ASSERT_EQ(util::DeviceToHost16(parser.chunk()->type), RES_TABLE_TYPE);

  // Retrieve the package of the entry
  ResChunkPullParser table_parser(GetChunkData(parser.chunk()), GetChunkDataLen(parser.chunk()));
  const ResChunk_header* package_chunk = nullptr;
  while (table_parser.IsGoodEvent(table_parser.Next())) {
    if (util::DeviceToHost16(table_parser.chunk()->type) == RES_TABLE_PACKAGE_TYPE) {
      package_chunk = table_parser.chunk();
      break;
    }
  }

  // Retrieve the type that proceeds the array entry
  ASSERT_NE(package_chunk, nullptr);
  ResChunkPullParser package_parser(GetChunkData(table_parser.chunk()),
                                    GetChunkDataLen(table_parser.chunk()));
  const ResChunk_header* type_chunk = nullptr;
  while (package_parser.IsGoodEvent(package_parser.Next())) {
    if (util::DeviceToHost16(package_parser.chunk()->type) == RES_TABLE_TYPE_TYPE) {
      type_chunk = package_parser.chunk();
      break;
    }
  }

  // Retrieve the array entry
  ASSERT_NE(type_chunk, nullptr);
  TypeVariant typeVariant((const ResTable_type*) type_chunk);
  auto entry = (const ResTable_map_entry*)*typeVariant.beginEntries();
  ASSERT_EQ(util::DeviceToHost16(entry->count), 2u);

  // Check that the value and name of the array entries are correct
  auto values = (const ResTable_map*)(((const uint8_t *)entry) + entry->size);
  ASSERT_EQ(values->value.data, 1u);
  ASSERT_EQ(values->name.ident, android::ResTable_map::ATTR_MIN);
  ASSERT_EQ((values+1)->value.data, 2u);
  ASSERT_EQ((values+1)->name.ident, android::ResTable_map::ATTR_MIN + 1);
}

static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
    IAaptContext* context, const ConfigDescription& sparse_config, float load) {
  std::unique_ptr<ResourceTable> table =