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

Commit 5c693f2b authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Propagate SPEC_OVERLAYABLE flag to final APK"

parents f7314652 71be7050
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -1339,9 +1339,13 @@ struct ResTable_typeSpec
    // Number of uint32_t entry configuration masks that follow.
    uint32_t entryCount;

    enum {
    enum : uint32_t {
        // Additional flag indicating an entry is public.
        SPEC_PUBLIC = 0x40000000
        SPEC_PUBLIC = 0x40000000u,

        // Additional flag indicating an entry is overlayable at runtime.
        // Added in Android-P.
        SPEC_OVERLAYABLE = 0x80000000u,
    };
};

+23 −17
Original line number Diff line number Diff line
@@ -294,20 +294,25 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions&
        printer->Print("/");
        printer->Print(entry->name);

        switch (entry->symbol_status.state) {
          case SymbolState::kPublic:
        switch (entry->visibility.level) {
          case Visibility::Level::kPublic:
            printer->Print(" PUBLIC");
            break;
          case SymbolState::kPrivate:
          case Visibility::Level::kPrivate:
            printer->Print(" _PRIVATE_");
            break;
          case SymbolState::kUndefined:
          case Visibility::Level::kUndefined:
            // Print nothing.
            break;
        }

        if (entry->overlayable) {
          printer->Print(" OVERLAYABLE");
        }

        printer->Println();

        if (options.show_values) {
          printer->Indent();
          for (const auto& value : entry->values) {
            printer->Print("(");
@@ -325,6 +330,7 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions&
          }
          printer->Undent();
        }
      }
      printer->Undent();
    }
    printer->Undent();
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ namespace aapt {

struct DebugPrintTableOptions {
  bool show_sources = false;
  bool show_values = true;
};

struct Debug {
+47 −27
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@
#include "util/Util.h"
#include "xml/XmlPullParser.h"

using android::StringPiece;
using ::android::StringPiece;

namespace aapt {

@@ -90,9 +90,12 @@ struct ParsedResource {
  ConfigDescription config;
  std::string product;
  Source source;

  ResourceId id;
  Maybe<SymbolState> symbol_state;
  Visibility::Level visibility_level = Visibility::Level::kUndefined;
  bool allow_new = false;
  bool overlayable = false;

  std::string comment;
  std::unique_ptr<Value> value;
  std::list<ParsedResource> child_resources;
@@ -106,24 +109,41 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed
    res->comment = trimmed_comment.to_string();
  }

  if (res->symbol_state) {
    Symbol symbol;
    symbol.state = res->symbol_state.value();
    symbol.source = res->source;
    symbol.comment = res->comment;
    symbol.allow_new = res->allow_new;
    if (!table->SetSymbolState(res->name, res->id, symbol, diag)) {
  if (res->visibility_level != Visibility::Level::kUndefined) {
    Visibility visibility;
    visibility.level = res->visibility_level;
    visibility.source = res->source;
    visibility.comment = res->comment;
    if (!table->SetVisibilityWithId(res->name, visibility, res->id, diag)) {
      return false;
    }
  }

  if (res->allow_new) {
    AllowNew allow_new;
    allow_new.source = res->source;
    allow_new.comment = res->comment;
    if (!table->SetAllowNew(res->name, allow_new, diag)) {
      return false;
    }
  }

  if (res->overlayable) {
    Overlayable overlayable;
    overlayable.source = res->source;
    overlayable.comment = res->comment;
    if (!table->SetOverlayable(res->name, overlayable, diag)) {
      return false;
    }
  }

  if (res->value) {
  if (res->value != nullptr) {
    // Attach the comment, source and config to the value.
    res->value->SetComment(std::move(res->comment));
    res->value->SetSource(std::move(res->source));

    if (!table->AddResource(res->name, res->id, res->config, res->product, std::move(res->value),
                            diag)) {
    if (!table->AddResourceWithId(res->name, res->id, res->config, res->product,
                                  std::move(res->value), diag)) {
      return false;
    }
  }
@@ -601,8 +621,7 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser,

  // Process the raw value.
  std::unique_ptr<Item> processed_item =
      ResourceUtils::TryParseItemForAttribute(raw_value, type_mask,
                                              on_create_reference);
      ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference);
  if (processed_item) {
    // Fix up the reference.
    if (Reference* ref = ValueCast<Reference>(processed_item.get())) {
@@ -689,8 +708,7 @@ bool ResourceParser::ParseString(xml::XmlPullParser* parser,
  return true;
}

bool ResourceParser::ParsePublic(xml::XmlPullParser* parser,
                                 ParsedResource* out_resource) {
bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) {
  if (out_resource->config != ConfigDescription::DefaultConfig()) {
    diag_->Warn(DiagMessage(out_resource->source)
                << "ignoring configuration '" << out_resource->config << "' for <public> tag");
@@ -728,7 +746,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser,
    out_resource->value = util::make_unique<Id>();
  }

  out_resource->symbol_state = SymbolState::kPublic;
  out_resource->visibility_level = Visibility::Level::kPublic;
  return true;
}

@@ -818,7 +836,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource
      child_resource.id = next_id;
      child_resource.comment = std::move(comment);
      child_resource.source = item_source;
      child_resource.symbol_state = SymbolState::kPublic;
      child_resource.visibility_level = Visibility::Level::kPublic;
      out_resource->child_resources.push_back(std::move(child_resource));

      next_id.id += 1;
@@ -864,7 +882,7 @@ bool ResourceParser::ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out
    return false;
  }

  out_resource->symbol_state = SymbolState::kPrivate;
  out_resource->visibility_level = Visibility::Level::kPrivate;
  return true;
}

@@ -920,8 +938,12 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
        continue;
      }

      // TODO(b/64980941): Mark the symbol as overlayable and allow marking which entity can overlay
      // the resource (system/app).
      ParsedResource child_resource;
      child_resource.name.type = *type;
      child_resource.name.entry = maybe_name.value().to_string();
      child_resource.source = item_source;
      child_resource.overlayable = true;
      out_resource->child_resources.push_back(std::move(child_resource));

      xml::XmlPullParser::SkipCurrentElement(parser);
    } else if (!ShouldIgnoreElement(element_namespace, element_name)) {
@@ -932,10 +954,9 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
  return !error;
}

bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser,
                                      ParsedResource* out_resource) {
bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) {
  if (ParseSymbolImpl(parser, out_resource)) {
    out_resource->symbol_state = SymbolState::kUndefined;
    out_resource->visibility_level = Visibility::Level::kUndefined;
    out_resource->allow_new = true;
    return true;
  }
@@ -1395,9 +1416,8 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser,
                                           ParsedResource* out_resource) {
  out_resource->name.type = ResourceType::kStyleable;

  // Declare-styleable is kPrivate by default, because it technically only
  // exists in R.java.
  out_resource->symbol_state = SymbolState::kPublic;
  // Declare-styleable is kPrivate by default, because it technically only exists in R.java.
  out_resource->visibility_level = Visibility::Level::kPublic;

  // Declare-styleable only ends up in default config;
  if (out_resource->config != ConfigDescription::DefaultConfig()) {
+41 −4
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@
using ::aapt::io::StringInputStream;
using ::aapt::test::StrValueEq;
using ::aapt::test::ValueEq;
using ::android::ResTable_map;
using ::android::Res_value;
using ::android::ResTable_map;
using ::android::StringPiece;
using ::testing::Eq;
using ::testing::IsEmpty;
@@ -38,6 +38,7 @@ using ::testing::IsNull;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::SizeIs;
using ::testing::StrEq;

namespace aapt {

@@ -482,7 +483,7 @@ TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) {
  Maybe<ResourceTable::SearchResult> result =
      table_.FindResource(test::ParseNameOrDie("styleable/foo"));
  ASSERT_TRUE(result);
  EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kPublic));
  EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));

  Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar");
  ASSERT_THAT(attr, NotNull());
@@ -718,6 +719,26 @@ TEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) {
  EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041)));
}

TEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) {
  std::string input = R"(
      <!-- private -->
      <java-symbol type="string" name="foo" />
      <!-- public -->
      <public type="string" name="foo" id="0x01020000" />
      <!-- private2 -->
      <java-symbol type="string" name="foo" />)";
  ASSERT_TRUE(TestParse(input));

  Maybe<ResourceTable::SearchResult> result =
      table_.FindResource(test::ParseNameOrDie("string/foo"));
  ASSERT_TRUE(result);

  ResourceEntry* entry = result.value().entry;
  ASSERT_THAT(entry, NotNull());
  EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kPublic));
  EXPECT_THAT(entry->visibility.comment, StrEq("public"));
}

TEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) {
  ASSERT_TRUE(TestParse(R"(<item type="layout" name="foo">@layout/bar</item>)"));
  ASSERT_FALSE(TestParse(R"(<item type="layout" name="bar">"this is a string"</item>)"));
@@ -731,8 +752,8 @@ TEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol)
  ASSERT_TRUE(result);
  const ResourceEntry* entry = result.value().entry;
  ASSERT_THAT(entry, NotNull());
  EXPECT_THAT(entry->symbol_status.state, Eq(SymbolState::kUndefined));
  EXPECT_TRUE(entry->symbol_status.allow_new);
  EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kUndefined));
  EXPECT_TRUE(entry->allow_new);
}

TEST_F(ResourceParserTest, ParseItemElementWithFormat) {
@@ -833,6 +854,22 @@ TEST_F(ResourceParserTest, ParseOverlayableTagWithSystemPolicy) {
        <item type="string" name="bar" />
      </overlayable>)";
  ASSERT_TRUE(TestParse(input));

  Maybe<ResourceTable::SearchResult> search_result =
      table_.FindResource(test::ParseNameOrDie("string/bar"));
  ASSERT_TRUE(search_result);
  ASSERT_THAT(search_result.value().entry, NotNull());
  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
  EXPECT_TRUE(search_result.value().entry->overlayable);
}

TEST_F(ResourceParserTest, DuplicateOverlayableIsError) {
  std::string input = R"(
      <overlayable>
        <item type="string" name="foo" />
        <item type="string" name="foo" />
      </overlayable>)";
  EXPECT_FALSE(TestParse(input));
}

}  // namespace aapt
Loading