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

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

Merge "AAPT2: Store BinaryPrimatives in protos as oneofs"

parents f5e25a30 d06f1f38
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -306,10 +306,25 @@ message FileReference {
}

// A value that represents a primitive data type (float, int, boolean, etc.).
// Corresponds to the fields (type/data) of the C struct android::Res_value.
message Primitive {
  uint32 type = 1;
  uint32 data = 2;
  message NullType {
  }
  message EmptyType {
  }
  oneof oneof_value {
    NullType null_value = 1;
    EmptyType empty_value = 2;
    float float_value = 3;
    float dimension_value = 4;
    float fraction_value = 5;
    int32 int_decimal_value = 6;
    uint32 int_hexidecimal_value = 7;
    bool boolean_value = 8;
    uint32 color_argb8_value = 9;
    uint32 color_rgb8_value = 10;
    uint32 color_argb4_value = 11;
    uint32 color_rgb4_value = 12;
  }
}

// A value that represents an XML attribute and what values it accepts.
+61 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "Locale.h"
#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"

using ::android::ResStringPool;
@@ -761,8 +762,66 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,

    case pb::Item::kPrim: {
      const pb::Primitive& pb_prim = pb_item.prim();
      return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
                                                pb_prim.data());
      android::Res_value val = {};
      switch (pb_prim.oneof_value_case()) {
        case pb::Primitive::kNullValue: {
          val.dataType = android::Res_value::TYPE_NULL;
          val.data = android::Res_value::DATA_NULL_UNDEFINED;
        } break;
        case pb::Primitive::kEmptyValue: {
          val.dataType = android::Res_value::TYPE_NULL;
          val.data = android::Res_value::DATA_NULL_EMPTY;
        } break;
        case pb::Primitive::kFloatValue: {
          val.dataType = android::Res_value::TYPE_FLOAT;
          float float_val = pb_prim.float_value();
          val.data = *(uint32_t*)&float_val;
        } break;
        case pb::Primitive::kDimensionValue: {
          val.dataType = android::Res_value::TYPE_DIMENSION;
          float dimen_val = pb_prim.dimension_value();
          val.data = *(uint32_t*)&dimen_val;
        } break;
        case pb::Primitive::kFractionValue: {
          val.dataType = android::Res_value::TYPE_FRACTION;
          float fraction_val = pb_prim.fraction_value();
          val.data = *(uint32_t*)&fraction_val;
        } break;
        case pb::Primitive::kIntDecimalValue: {
          val.dataType = android::Res_value::TYPE_INT_DEC;
          val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
        } break;
        case pb::Primitive::kIntHexidecimalValue: {
          val.dataType = android::Res_value::TYPE_INT_HEX;
          val.data = pb_prim.int_hexidecimal_value();
        } break;
        case pb::Primitive::kBooleanValue: {
          val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
          val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0;
        } break;
        case pb::Primitive::kColorArgb8Value: {
          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
          val.data = pb_prim.color_argb8_value();
        } break;
        case pb::Primitive::kColorRgb8Value: {
          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
          val.data = pb_prim.color_rgb8_value();
        } break;
        case pb::Primitive::kColorArgb4Value: {
          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
          val.data = pb_prim.color_argb4_value();
        } break;
        case pb::Primitive::kColorRgb4Value: {
          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
          val.data = pb_prim.color_rgb4_value();
        } break;
        default: {
          LOG(FATAL) << "Unexpected Primitive type: "
                     << static_cast<uint32_t>(pb_prim.oneof_value_case());
          return {};
        } break;
      }
      return util::make_unique<BinaryPrimitive>(val);
    } break;

    case pb::Item::kId: {
+45 −2
Original line number Diff line number Diff line
@@ -436,8 +436,51 @@ class ValueSerializer : public ConstValueVisitor {
    prim->Flatten(&val);

    pb::Primitive* pb_prim = out_value_->mutable_item()->mutable_prim();
    pb_prim->set_type(val.dataType);
    pb_prim->set_data(val.data);

    switch (val.dataType) {
      case android::Res_value::TYPE_NULL: {
        if (val.data == android::Res_value::DATA_NULL_UNDEFINED) {
          pb_prim->set_allocated_null_value(new pb::Primitive_NullType());
        } else if (val.data == android::Res_value::DATA_NULL_EMPTY) {
          pb_prim->set_allocated_empty_value(new pb::Primitive_EmptyType());
        } else {
          LOG(FATAL) << "Unexpected data value for TYPE_NULL BinaryPrimitive: " << val.data;
        }
      } break;
      case android::Res_value::TYPE_FLOAT: {
        pb_prim->set_float_value(*(float*)&val.data);
      } break;
      case android::Res_value::TYPE_DIMENSION: {
        pb_prim->set_dimension_value(*(float*)&val.data);
      } break;
      case android::Res_value::TYPE_FRACTION: {
        pb_prim->set_fraction_value(*(float*)&val.data);
      } break;
      case android::Res_value::TYPE_INT_DEC: {
        pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data));
      } break;
      case android::Res_value::TYPE_INT_HEX: {
        pb_prim->set_int_hexidecimal_value(val.data);
      } break;
      case android::Res_value::TYPE_INT_BOOLEAN: {
        pb_prim->set_boolean_value(static_cast<bool>(val.data));
      } break;
      case android::Res_value::TYPE_INT_COLOR_ARGB8: {
        pb_prim->set_color_argb8_value(val.data);
      } break;
      case android::Res_value::TYPE_INT_COLOR_RGB8: {
        pb_prim->set_color_rgb8_value(val.data);
      } break;
      case android::Res_value::TYPE_INT_COLOR_ARGB4: {
        pb_prim->set_color_argb4_value(val.data);
      } break;
      case android::Res_value::TYPE_INT_COLOR_RGB4: {
        pb_prim->set_color_rgb4_value(val.data);
      } break;
      default:
        LOG(FATAL) << "Unexpected BinaryPrimitive type: " << val.dataType;
        break;
    }
  }

  void Visit(const Attribute* attr) override {
+105 −0
Original line number Diff line number Diff line
@@ -254,6 +254,111 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeXml) {
  EXPECT_THAT(child_text->text, StrEq("woah there"));
}

TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) {
  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .AddValue("android:bool/boolean_true",
                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true))
          .AddValue("android:bool/boolean_false",
                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false))
          .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC"))
          .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344"))
          .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF"))
          .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678"))
          .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444"))
          .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333"))
          .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD"))
          .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm"))
          .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%"))
          .AddValue("android:integer/null", ResourceUtils::MakeEmpty())
          .Build();

  pb::ResourceTable pb_table;
  SerializeTableToPb(*table, &pb_table);

  test::TestFile file_a("res/layout/main.xml");
  MockFileCollection files;
  EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
      .WillRepeatedly(::testing::Return(&file_a));

  ResourceTable new_table;
  std::string error;
  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
  EXPECT_THAT(error, IsEmpty());

  BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
      &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
      &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
      &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
      &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data));

  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null",
                                                          ConfigDescription::DefaultConfig(), "");
  ASSERT_THAT(bp, NotNull());
  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL));
  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data));
}

static void ExpectConfigSerializes(const StringPiece& config_str) {
  const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
  pb::Configuration pb_config;