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

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

Merge "Fix support for @empty in style resolution" into oc-dev

parents 8d0ba598 32e7501a
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ public class TypedArray {
    }

    /**
     * Return the number of indices in the array that actually have data.
     * Returns the number of indices in the array that actually have data. Attributes with a value
     * of @empty are included, as this is an explicit indicator.
     *
     * @throws RuntimeException if the TypedArray has already been recycled.
     */
@@ -116,7 +117,8 @@ public class TypedArray {
    }

    /**
     * Returns an index in the array that has data.
     * Returns an index in the array that has data. Attributes with a value of @empty are included,
     * as this is an explicit indicator.
     *
     * @param at The index you would like to returned, ranging from 0 to
     *           {@link #getIndexCount()}.
@@ -1017,7 +1019,7 @@ public class TypedArray {
     * @param outValue TypedValue object in which to place the attribute's
     *                 data.
     *
     * @return {@code true} if the value was retrieved, false otherwise.
     * @return {@code true} if the value was retrieved and not @empty, {@code false} otherwise.
     * @throws RuntimeException if the TypedArray has already been recycled.
     */
    public boolean getValue(@StyleableRes int index, TypedValue outValue) {
+39 −64
Original line number Diff line number Diff line
@@ -44,8 +44,7 @@ class XmlAttributeFinder
};

class BagAttributeFinder
    : public BackTrackingAttributeFinder<BagAttributeFinder,
                                         const ResTable::bag_entry*> {
    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
 public:
  BagAttributeFinder(const ResTable::bag_entry* start,
                     const ResTable::bag_entry* end)
@@ -76,8 +75,7 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
  uint32_t def_style_bag_type_set_flags = 0;
  if (def_style_attr != 0) {
    Res_value value;
    if (theme->getAttribute(def_style_attr, &value,
                            &def_style_bag_type_set_flags) >= 0) {
    if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
      if (value.dataType == Res_value::TYPE_REFERENCE) {
        def_style_res = value.data;
      }
@@ -127,18 +125,14 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
        ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
              value.data);
      }
    }

    if (value.dataType == Res_value::TYPE_NULL) {
      const ResTable::bag_entry* const def_style_entry =
          def_style_attr_finder.Find(cur_ident);
    } else {
      const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
      if (def_style_entry != def_style_end) {
        block = def_style_entry->stringBlock;
        type_set_flags = def_style_type_set_flags;
        value = def_style_entry->map.value;
        if (kDebugStyles) {
          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      }
    }
@@ -146,29 +140,24 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
    uint32_t resid = 0;
    if (value.dataType != Res_value::TYPE_NULL) {
      // Take care of resolving the found resource to its final value.
      ssize_t new_block = theme->resolveAttributeReference(
          &value, block, &resid, &type_set_flags, &config);
      ssize_t new_block =
          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
      if (new_block >= 0) block = new_block;
      if (kDebugStyles) {
        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
              value.data);
        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
      }
    } else {
    } else if (value.data != Res_value::DATA_NULL_EMPTY) {
      // If we still don't have a value for this attribute, try to find
      // it in the theme!
      ssize_t new_block =
          theme->getAttribute(cur_ident, &value, &type_set_flags);
      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
      if (new_block >= 0) {
        if (kDebugStyles) {
          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
        new_block = res.resolveReference(&value, new_block, &resid,
                                         &type_set_flags, &config);
        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
        if (new_block >= 0) block = new_block;
        if (kDebugStyles) {
          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      }
    }
@@ -184,8 +173,7 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
    }

    if (kDebugStyles) {
      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
            value.dataType, value.data);
      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
    }

    // Write the final value back to Java.
@@ -198,7 +186,8 @@ bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
    out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
    out_values[STYLE_DENSITY] = config.density;

    if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
    if (out_indices != nullptr &&
        (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
      indices_idx++;
      out_indices[indices_idx] = ii;
    }
@@ -247,8 +236,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
    ssize_t idx = xml_parser->indexOfStyle();
    if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
      if (value.dataType == value.TYPE_ATTRIBUTE) {
        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) <
            0) {
        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
          value.dataType = Res_value::TYPE_NULL;
        }
      }
@@ -318,41 +306,34 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
      // We found the attribute we were looking for.
      xml_parser->getAttributeValue(xml_attr_idx, &value);
      if (kDebugStyles) {
        ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType,
              value.data);
        ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
      }
    }

    if (value.dataType == Res_value::TYPE_NULL) {
      // Walk through the style class values looking for the requested
      // attribute.
      const ResTable::bag_entry* const style_attr_entry =
          style_attr_finder.Find(cur_ident);
    if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
      // Walk through the style class values looking for the requested attribute.
      const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
      if (style_attr_entry != style_attr_end) {
        // We found the attribute we were looking for.
        block = style_attr_entry->stringBlock;
        type_set_flags = style_type_set_flags;
        value = style_attr_entry->map.value;
        if (kDebugStyles) {
          ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      }
    }

    if (value.dataType == Res_value::TYPE_NULL) {
      // Walk through the default style values looking for the requested
      // attribute.
      const ResTable::bag_entry* const def_style_attr_entry =
          def_style_attr_finder.Find(cur_ident);
    if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
      // Walk through the default style values looking for the requested attribute.
      const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
      if (def_style_attr_entry != def_style_attr_end) {
        // We found the attribute we were looking for.
        block = def_style_attr_entry->stringBlock;
        type_set_flags = style_type_set_flags;
        value = def_style_attr_entry->map.value;
        if (kDebugStyles) {
          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      }
    }
@@ -360,35 +341,29 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
    uint32_t resid = 0;
    if (value.dataType != Res_value::TYPE_NULL) {
      // Take care of resolving the found resource to its final value.
      ssize_t new_block = theme->resolveAttributeReference(
          &value, block, &resid, &type_set_flags, &config);
      ssize_t new_block =
          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
      if (new_block >= 0) {
        block = new_block;
      }

      if (kDebugStyles) {
        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
              value.data);
        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
      }
    } else {
      // If we still don't have a value for this attribute, try to find
      // it in the theme!
      ssize_t new_block =
          theme->getAttribute(cur_ident, &value, &type_set_flags);
    } else if (value.data != Res_value::DATA_NULL_EMPTY) {
      // If we still don't have a value for this attribute, try to find it in the theme!
      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
      if (new_block >= 0) {
        if (kDebugStyles) {
          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
        new_block = res.resolveReference(&value, new_block, &resid,
                                         &type_set_flags, &config);
        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
        if (new_block >= 0) {
          block = new_block;
        }

        if (kDebugStyles) {
          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
                value.data);
          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      }
    }
@@ -404,8 +379,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
    }

    if (kDebugStyles) {
      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
            value.dataType, value.data);
      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
    }

    // Write the final value back to Java.
@@ -418,7 +392,7 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s
    out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
    out_values[STYLE_DENSITY] = config.density;

    if (value.dataType != Res_value::TYPE_NULL) {
    if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) {
      indices_idx++;

      // out_indices must NOT be nullptr.
@@ -502,7 +476,8 @@ bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
    out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
    out_values[STYLE_DENSITY] = config.density;

    if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
    if (out_indices != nullptr &&
        (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
      indices_idx++;
      out_indices[indices_idx] = ii;
    }
+4 −2
Original line number Diff line number Diff line
@@ -3538,7 +3538,8 @@ status_t ResTable::Theme::applyStyle(uint32_t resID, bool force)
                    attrRes, bag->map.value.dataType, bag->map.value.data,
                    curEntry->value.dataType);
        }
        if (force || curEntry->value.dataType == Res_value::TYPE_NULL) {
        if (force || (curEntry->value.dataType == Res_value::TYPE_NULL
                && curEntry->value.data != Res_value::DATA_NULL_EMPTY)) {
            curEntry->stringBlock = bag->stringBlock;
            curEntry->typeSpecFlags |= bagTypeSpecFlags;
            curEntry->value = bag->map.value;
@@ -3674,7 +3675,8 @@ ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue,
                            }
                            ALOGW("Too many attribute references, stopped at: 0x%08x\n", resID);
                            return BAD_INDEX;
                        } else if (type != Res_value::TYPE_NULL) {
                        } else if (type != Res_value::TYPE_NULL
                                || te.value.data == Res_value::DATA_NULL_EMPTY) {
                            *outValue = te.value;
                            return te.stringBlock;
                        }
+6 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {

  const ResolvedBag* bag_two = assetmanager.GetBag(app::R::style::StyleTwo);
  ASSERT_NE(nullptr, bag_two);
  ASSERT_EQ(5u, bag_two->entry_count);
  ASSERT_EQ(6u, bag_two->entry_count);

  // attr_one is inherited from StyleOne.
  EXPECT_EQ(app::R::attr::attr_one, bag_two->entries[0].key);
@@ -295,6 +295,11 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
  EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_two->entries[4].value.dataType);
  EXPECT_EQ(3u, bag_two->entries[4].value.data);
  EXPECT_EQ(0, bag_two->entries[4].cookie);

  EXPECT_EQ(app::R::attr::attr_empty, bag_two->entries[5].key);
  EXPECT_EQ(Res_value::TYPE_NULL, bag_two->entries[5].value.dataType);
  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, bag_two->entries[5].value.data);
  EXPECT_EQ(0, bag_two->entries[5].cookie);
}

TEST_F(AssetManager2Test, ResolveReferenceToResource) {
+44 −12
Original line number Diff line number Diff line
@@ -69,8 +69,8 @@ TEST_F(AttributeResolutionTest, Theme) {
  ResTable::Theme theme(table_);
  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));

  std::array<uint32_t, 4> attrs{
      {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                 R::attr::attr_four, R::attr::attr_empty}};
  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;

  ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
@@ -109,11 +109,21 @@ TEST_F(AttributeResolutionTest, Theme) {
  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);

  // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
  // as the theme.
  values_cursor += STYLE_NUM_ENTRIES;
  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
}

TEST_F(AttributeResolutionXmlTest, XmlParser) {
  std::array<uint32_t, 4> attrs{
      {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                 R::attr::attr_four, R::attr::attr_empty}};
  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;

  ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
@@ -121,7 +131,7 @@ TEST_F(AttributeResolutionXmlTest, XmlParser) {

  uint32_t* values_cursor = values.data();
  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DATA]);
  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
@@ -150,16 +160,24 @@ TEST_F(AttributeResolutionXmlTest, XmlParser) {
  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);

  values_cursor += STYLE_NUM_ENTRIES;
  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]);
  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
}

TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
  ResTable::Theme theme(table_);
  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));

  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                 R::attr::attr_four, R::attr::attr_five}};
  std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                 R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
  std::array<uint32_t, attrs.size()> indices;
  std::array<uint32_t, attrs.size() + 1> indices;

  ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
             attrs.size(), values.data(), indices.data());
@@ -167,12 +185,12 @@ TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
  const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;

  uint32_t* values_cursor = values.data();
  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);

  values_cursor += STYLE_NUM_ENTRIES;
  EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
@@ -203,6 +221,20 @@ TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);

  // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
  // as the theme.
  values_cursor += STYLE_NUM_ENTRIES;
  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);

  // The first element of indices contains the number of indices.
  std::array<uint32_t, 7> expected_indices = {{6u, 0u, 1u, 2u, 3u, 4u, 5u}};
  EXPECT_EQ(expected_indices, indices);
}

} // namespace android
Loading