From 458b877488c12ea4336d8fc00a95d9c0298bd6d0 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Mon, 25 Apr 2016 14:20:21 -0700 Subject: AAPT2: Add diff command Adds the diff command and various small fixes to issues discovered when diffing old AAPT built APKs with new AAPT2 built APKS. Bug:22775504 Change-Id: I682a7fe1cf4b3efa7cbd5d18b333cf2d1046fe1b --- tools/aapt2/ResourceValues.cpp | 172 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 14 deletions(-) (limited to 'tools/aapt2/ResourceValues.cpp') diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index dd7ff013e524..c10b134cb36e 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -39,6 +39,14 @@ void BaseItem::accept(RawValueVisitor* visitor) { RawString::RawString(const StringPool::Ref& ref) : value(ref) { } +bool RawString::equals(const Value* value) const { + const RawString* other = valueCast(value); + if (!other) { + return false; + } + return *this->value == *other->value; +} + RawString* RawString::clone(StringPool* newPool) const { RawString* rs = new RawString(newPool->makeRef(*value)); rs->mComment = mComment; @@ -66,6 +74,15 @@ Reference::Reference(const ResourceNameRef& n, Type t) : Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) { } +bool Reference::equals(const Value* value) const { + const Reference* other = valueCast(value); + if (!other) { + return false; + } + return referenceType == other->referenceType && privateReference == other->privateReference && + id == other->id && name == other->name; +} + bool Reference::flatten(android::Res_value* outValue) const { outValue->dataType = (referenceType == Reference::Type::kResource) ? android::Res_value::TYPE_REFERENCE : android::Res_value::TYPE_ATTRIBUTE; @@ -97,6 +114,10 @@ void Reference::print(std::ostream* out) const { } } +bool Id::equals(const Value* value) const { + return valueCast(value) != nullptr; +} + bool Id::flatten(android::Res_value* out) const { out->dataType = android::Res_value::TYPE_INT_BOOLEAN; out->data = util::hostToDevice32(0); @@ -111,15 +132,15 @@ void Id::print(std::ostream* out) const { *out << "(id)"; } -String::String(const StringPool::Ref& ref) : value(ref), mTranslateable(true) { -} - -void String::setTranslateable(bool val) { - mTranslateable = val; +String::String(const StringPool::Ref& ref) : value(ref) { } -bool String::isTranslateable() const { - return mTranslateable; +bool String::equals(const Value* value) const { + const String* other = valueCast(value); + if (!other) { + return false; + } + return *this->value == *other->value; } bool String::flatten(android::Res_value* outValue) const { @@ -144,15 +165,24 @@ void String::print(std::ostream* out) const { *out << "(string) \"" << *value << "\""; } -StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref), mTranslateable(true) { +StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) { } -void StyledString::setTranslateable(bool val) { - mTranslateable = val; -} +bool StyledString::equals(const Value* value) const { + const StyledString* other = valueCast(value); + if (!other) { + return false; + } -bool StyledString::isTranslateable() const { - return mTranslateable; + if (*this->value->str == *other->value->str) { + const std::vector& spansA = this->value->spans; + const std::vector& spansB = other->value->spans; + return std::equal(spansA.begin(), spansA.end(), spansB.begin(), + [](const StringPool::Span& a, const StringPool::Span& b) -> bool { + return *a.name == *b.name && a.firstChar == b.firstChar && a.lastChar == b.lastChar; + }); + } + return false; } bool StyledString::flatten(android::Res_value* outValue) const { @@ -174,11 +204,22 @@ StyledString* StyledString::clone(StringPool* newPool) const { void StyledString::print(std::ostream* out) const { *out << "(styled string) \"" << *value->str << "\""; + for (const StringPool::Span& span : value->spans) { + *out << " "<< *span.name << ":" << span.firstChar << "," << span.lastChar; + } } FileReference::FileReference(const StringPool::Ref& _path) : path(_path) { } +bool FileReference::equals(const Value* value) const { + const FileReference* other = valueCast(value); + if (!other) { + return false; + } + return *path == *other->path; +} + bool FileReference::flatten(android::Res_value* outValue) const { if (path.getIndex() > std::numeric_limits::max()) { return false; @@ -209,6 +250,14 @@ BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) { value.data = data; } +bool BinaryPrimitive::equals(const Value* value) const { + const BinaryPrimitive* other = valueCast(value); + if (!other) { + return false; + } + return this->value.dataType == other->value.dataType && this->value.data == other->value.data; +} + bool BinaryPrimitive::flatten(android::Res_value* outValue) const { outValue->dataType = value.dataType; outValue->data = util::hostToDevice32(value.data); @@ -228,7 +277,7 @@ void BinaryPrimitive::print(std::ostream* out) const { *out << "(integer) " << static_cast(value.data); break; case android::Res_value::TYPE_INT_HEX: - *out << "(integer) " << std::hex << value.data << std::dec; + *out << "(integer) 0x" << std::hex << value.data << std::dec; break; case android::Res_value::TYPE_INT_BOOLEAN: *out << "(boolean) " << (value.data != 0 ? "true" : "false"); @@ -253,6 +302,21 @@ Attribute::Attribute(bool w, uint32_t t) : mWeak = w; } +bool Attribute::equals(const Value* value) const { + const Attribute* other = valueCast(value); + if (!other) { + return false; + } + + return this->typeMask == other->typeMask && this->minInt == other->minInt && + this->maxInt == other->maxInt && + std::equal(this->symbols.begin(), this->symbols.end(), + other->symbols.begin(), + [](const Symbol& a, const Symbol& b) -> bool { + return a.symbol.equals(&b.symbol) && a.value == b.value; + }); +} + Attribute* Attribute::clone(StringPool* /*newPool*/) const { return new Attribute(*this); } @@ -365,6 +429,14 @@ void Attribute::print(std::ostream* out) const { << "]"; } + if (minInt != std::numeric_limits::min()) { + *out << " min=" << minInt; + } + + if (maxInt != std::numeric_limits::max()) { + *out << " max=" << maxInt; + } + if (isWeak()) { *out << " [weak]"; } @@ -445,6 +517,21 @@ bool Attribute::matches(const Item* item, DiagMessage* outMsg) const { return true; } +bool Style::equals(const Value* value) const { + const Style* other = valueCast