summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt/Resource.cpp17
-rw-r--r--tools/aapt2/AppInfo.h10
-rw-r--r--tools/aapt2/Diagnostics.h6
-rw-r--r--tools/aapt2/Main.cpp2
-rw-r--r--tools/aapt2/NameMangler.h2
-rw-r--r--tools/aapt2/ResourceParser.cpp21
-rw-r--r--tools/aapt2/ResourceUtils.cpp50
-rw-r--r--tools/aapt2/ResourceUtils.h33
-rw-r--r--tools/aapt2/ResourceUtils_test.cpp36
-rw-r--r--tools/aapt2/ResourceValues.cpp10
-rw-r--r--tools/aapt2/Source.h2
-rw-r--r--tools/aapt2/ValueVisitor.h3
-rw-r--r--tools/aapt2/compile/Png.h2
-rw-r--r--tools/aapt2/compile/Pseudolocalizer.h2
-rw-r--r--tools/aapt2/compile/XmlIdCollector.cpp2
-rw-r--r--tools/aapt2/flatten/TableFlattener.h2
-rw-r--r--tools/aapt2/io/FileSystem.h4
-rw-r--r--tools/aapt2/io/ZipArchive.h2
-rw-r--r--tools/aapt2/java/ClassDefinition.h2
-rw-r--r--tools/aapt2/link/Link.cpp383
-rw-r--r--tools/aapt2/link/ManifestFixer.h2
-rw-r--r--tools/aapt2/link/ProductFilter.h2
-rw-r--r--tools/aapt2/link/ReferenceLinker.cpp2
-rw-r--r--tools/aapt2/link/XmlReferenceLinker.cpp2
-rw-r--r--tools/aapt2/process/SymbolTable.h2
-rw-r--r--tools/aapt2/readme.md9
-rw-r--r--tools/aapt2/split/TableSplitter.cpp11
-rw-r--r--tools/aapt2/split/TableSplitter.h2
-rw-r--r--tools/aapt2/split/TableSplitter_test.cpp69
-rw-r--r--tools/aapt2/test/Builders.h28
-rw-r--r--tools/aapt2/test/Common.h2
-rw-r--r--tools/aapt2/test/Context.h2
-rw-r--r--tools/aapt2/util/BigBuffer.h2
-rw-r--r--tools/aapt2/util/Files.h2
-rw-r--r--tools/aapt2/util/Maybe.h8
-rw-r--r--tools/aapt2/util/StringPiece.h4
-rw-r--r--tools/aapt2/util/Util.h20
-rw-r--r--tools/aapt2/xml/XmlPullParser.h2
-rw-r--r--tools/split-select/SplitSelector.h2
39 files changed, 514 insertions, 250 deletions
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index b4c4d05a7397..1e7875d435eb 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1033,7 +1033,6 @@ static ssize_t extractPlatformBuildVersion(AssetManager& assets, Bundle* bundle)
return NO_ERROR;
}
- ResXMLTree tree;
Asset* asset = assets.openNonAsset(cookie, "AndroidManifest.xml", Asset::ACCESS_STREAMING);
if (asset == NULL) {
fprintf(stderr, "ERROR: Platform AndroidManifest.xml not found\n");
@@ -1041,11 +1040,17 @@ static ssize_t extractPlatformBuildVersion(AssetManager& assets, Bundle* bundle)
}
ssize_t result = NO_ERROR;
- if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) {
- fprintf(stderr, "ERROR: Platform AndroidManifest.xml is corrupt\n");
- result = UNKNOWN_ERROR;
- } else {
- result = extractPlatformBuildVersion(tree, bundle);
+
+ // Create a new scope so that ResXMLTree is destroyed before we delete the memory over
+ // which it iterates (asset).
+ {
+ ResXMLTree tree;
+ if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) {
+ fprintf(stderr, "ERROR: Platform AndroidManifest.xml is corrupt\n");
+ result = UNKNOWN_ERROR;
+ } else {
+ result = extractPlatformBuildVersion(tree, bundle);
+ }
}
delete asset;
diff --git a/tools/aapt2/AppInfo.h b/tools/aapt2/AppInfo.h
index 1d39b722b053..a9794a419ca2 100644
--- a/tools/aapt2/AppInfo.h
+++ b/tools/aapt2/AppInfo.h
@@ -37,6 +37,16 @@ struct AppInfo {
* The App's minimum SDK version.
*/
Maybe<std::string> minSdkVersion;
+
+ /**
+ * The Version code of the app.
+ */
+ Maybe<uint32_t> versionCode;
+
+ /**
+ * The revision code of the app.
+ */
+ Maybe<uint32_t> revisionCode;
};
} // namespace aapt
diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h
index e86f2a8830e8..725027c2c45a 100644
--- a/tools/aapt2/Diagnostics.h
+++ b/tools/aapt2/Diagnostics.h
@@ -41,13 +41,13 @@ private:
public:
DiagMessage() = default;
- DiagMessage(const StringPiece& src) : mSource(src) {
+ explicit DiagMessage(const StringPiece& src) : mSource(src) {
}
- DiagMessage(const Source& src) : mSource(src) {
+ explicit DiagMessage(const Source& src) : mSource(src) {
}
- DiagMessage(size_t line) : mSource(Source().withLine(line)) {
+ explicit DiagMessage(size_t line) : mSource(Source().withLine(line)) {
}
template <typename T>
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index a74b5aa2478e..ed55f852c24c 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@ namespace aapt {
static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "0";
+static const char* sMinorVersion = "1";
int printVersion() {
std::cerr << "Android Asset Packaging Tool (aapt) "
diff --git a/tools/aapt2/NameMangler.h b/tools/aapt2/NameMangler.h
index 505a982e5eab..b6aaa4df3bec 100644
--- a/tools/aapt2/NameMangler.h
+++ b/tools/aapt2/NameMangler.h
@@ -43,7 +43,7 @@ private:
NameManglerPolicy mPolicy;
public:
- NameMangler(NameManglerPolicy policy) : mPolicy(policy) {
+ explicit NameMangler(NameManglerPolicy policy) : mPolicy(policy) {
}
Maybe<ResourceName> mangleName(const ResourceName& name) {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index a144c6ab2be7..bcdf401077ee 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -500,8 +500,8 @@ std::unique_ptr<Item> ResourceParser::parseXml(xml::XmlPullParser* parser, const
};
// Process the raw value.
- std::unique_ptr<Item> processedItem = ResourceUtils::parseItemForAttribute(rawValue, typeMask,
- onCreateReference);
+ std::unique_ptr<Item> processedItem = ResourceUtils::tryParseItemForAttribute(
+ rawValue, typeMask, onCreateReference);
if (processedItem) {
// Fix up the reference.
if (Reference* ref = valueCast<Reference>(processedItem.get())) {
@@ -528,20 +528,24 @@ std::unique_ptr<Item> ResourceParser::parseXml(xml::XmlPullParser* parser, const
bool ResourceParser::parseString(xml::XmlPullParser* parser, ParsedResource* outResource) {
bool formatted = true;
if (Maybe<StringPiece> formattedAttr = xml::findAttribute(parser, "formatted")) {
- if (!ResourceUtils::tryParseBool(formattedAttr.value(), &formatted)) {
+ Maybe<bool> maybeFormatted = ResourceUtils::parseBool(formattedAttr.value());
+ if (!maybeFormatted) {
mDiag->error(DiagMessage(outResource->source)
<< "invalid value for 'formatted'. Must be a boolean");
return false;
}
+ formatted = maybeFormatted.value();
}
bool translateable = mOptions.translatable;
if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
- if (!ResourceUtils::tryParseBool(translateableAttr.value(), &translateable)) {
+ Maybe<bool> maybeTranslateable = ResourceUtils::parseBool(translateableAttr.value());
+ if (!maybeTranslateable) {
mDiag->error(DiagMessage(outResource->source)
<< "invalid value for 'translatable'. Must be a boolean");
return false;
}
+ translateable = maybeTranslateable.value();
}
outResource->value = parseXml(parser, android::ResTable_map::TYPE_STRING, kNoRawString);
@@ -590,7 +594,7 @@ bool ResourceParser::parsePublic(xml::XmlPullParser* parser, ParsedResource* out
outResource->name.type = *parsedType;
if (Maybe<StringPiece> maybeIdStr = xml::findNonEmptyAttribute(parser, "id")) {
- Maybe<ResourceId> maybeId = ResourceUtils::tryParseResourceId(maybeIdStr.value());
+ Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(maybeIdStr.value());
if (!maybeId) {
mDiag->error(DiagMessage(outResource->source)
<< "invalid resource ID '" << maybeId.value() << "' in <public>");
@@ -630,7 +634,7 @@ bool ResourceParser::parsePublicGroup(xml::XmlPullParser* parser, ParsedResource
return false;
}
- Maybe<ResourceId> maybeId = ResourceUtils::tryParseResourceId(maybeIdStr.value());
+ Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(maybeIdStr.value());
if (!maybeId) {
mDiag->error(DiagMessage(outResource->source)
<< "invalid resource ID '" << maybeIdStr.value() << "' in <public-group>");
@@ -1058,14 +1062,17 @@ bool ResourceParser::parseArrayImpl(xml::XmlPullParser* parser, ParsedResource*
bool translateable = mOptions.translatable;
if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
- if (!ResourceUtils::tryParseBool(translateableAttr.value(), &translateable)) {
+ Maybe<bool> maybeTranslateable = ResourceUtils::parseBool(translateableAttr.value());
+ if (!maybeTranslateable) {
mDiag->error(DiagMessage(outResource->source)
<< "invalid value for 'translatable'. Must be a boolean");
return false;
}
+ translateable = maybeTranslateable.value();
}
array->setTranslateable(translateable);
+
bool error = false;
const size_t depth = parser->getDepth();
while (xml::XmlPullParser::nextChildNode(parser, depth)) {
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 773616d6aa71..11619fa9c67d 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -124,7 +124,7 @@ bool parseResourceName(const StringPiece& str, ResourceNameRef* outRef, bool* ou
return true;
}
-bool tryParseReference(const StringPiece& str, ResourceNameRef* outRef, bool* outCreate,
+bool parseReference(const StringPiece& str, ResourceNameRef* outRef, bool* outCreate,
bool* outPrivate) {
StringPiece trimmedStr(util::trimWhitespace(str));
if (trimmedStr.empty()) {
@@ -171,10 +171,10 @@ bool tryParseReference(const StringPiece& str, ResourceNameRef* outRef, bool* ou
}
bool isReference(const StringPiece& str) {
- return tryParseReference(str, nullptr, nullptr, nullptr);
+ return parseReference(str, nullptr, nullptr, nullptr);
}
-bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outRef) {
+bool parseAttributeReference(const StringPiece& str, ResourceNameRef* outRef) {
StringPiece trimmedStr(util::trimWhitespace(str));
if (trimmedStr.empty()) {
return false;
@@ -208,7 +208,7 @@ bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outRef)
}
bool isAttributeReference(const StringPiece& str) {
- return tryParseAttributeReference(str, nullptr);
+ return parseAttributeReference(str, nullptr);
}
/*
@@ -271,13 +271,13 @@ Maybe<Reference> parseStyleParentReference(const StringPiece& str, std::string*
std::unique_ptr<Reference> tryParseReference(const StringPiece& str, bool* outCreate) {
ResourceNameRef ref;
bool privateRef = false;
- if (tryParseReference(str, &ref, outCreate, &privateRef)) {
+ if (parseReference(str, &ref, outCreate, &privateRef)) {
std::unique_ptr<Reference> value = util::make_unique<Reference>(ref);
value->privateReference = privateRef;
return value;
}
- if (tryParseAttributeReference(str, &ref)) {
+ if (parseAttributeReference(str, &ref)) {
if (outCreate) {
*outCreate = false;
}
@@ -420,23 +420,26 @@ std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece& str) {
return error ? std::unique_ptr<BinaryPrimitive>() : util::make_unique<BinaryPrimitive>(value);
}
-bool tryParseBool(const StringPiece& str, bool* outValue) {
+Maybe<bool> parseBool(const StringPiece& str) {
StringPiece trimmedStr(util::trimWhitespace(str));
if (trimmedStr == "true" || trimmedStr == "TRUE" || trimmedStr == "True") {
- if (outValue) {
- *outValue = true;
- }
- return true;
+ return Maybe<bool>(true);
} else if (trimmedStr == "false" || trimmedStr == "FALSE" || trimmedStr == "False") {
- if (outValue) {
- *outValue = false;
- }
- return true;
+ return Maybe<bool>(false);
}
- return false;
+ return {};
+}
+
+Maybe<uint32_t> parseInt(const StringPiece& str) {
+ std::u16string str16 = util::utf8ToUtf16(str);
+ android::Res_value value;
+ if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
+ return value.data;
+ }
+ return {};
}
-Maybe<ResourceId> tryParseResourceId(const StringPiece& str) {
+Maybe<ResourceId> parseResourceId(const StringPiece& str) {
StringPiece trimmedStr(util::trimWhitespace(str));
std::u16string str16 = util::utf8ToUtf16(trimmedStr);
@@ -452,7 +455,7 @@ Maybe<ResourceId> tryParseResourceId(const StringPiece& str) {
return {};
}
-Maybe<int> tryParseSdkVersion(const StringPiece& str) {
+Maybe<int> parseSdkVersion(const StringPiece& str) {
StringPiece trimmedStr(util::trimWhitespace(str));
std::u16string str16 = util::utf8ToUtf16(trimmedStr);
@@ -470,12 +473,11 @@ Maybe<int> tryParseSdkVersion(const StringPiece& str) {
}
std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece& str) {
- bool result = false;
- if (tryParseBool(str, &result)) {
+ if (Maybe<bool> maybeResult = parseBool(str)) {
android::Res_value value = {};
value.dataType = android::Res_value::TYPE_INT_BOOLEAN;
- if (result) {
+ if (maybeResult.value()) {
value.data = 0xffffffffu;
} else {
value.data = 0;
@@ -542,7 +544,7 @@ uint32_t androidTypeToAttributeTypeMask(uint16_t type) {
};
}
-std::unique_ptr<Item> parseItemForAttribute(
+std::unique_ptr<Item> tryParseItemForAttribute(
const StringPiece& value,
uint32_t typeMask,
const std::function<void(const ResourceName&)>& onCreateReference) {
@@ -602,11 +604,11 @@ std::unique_ptr<Item> parseItemForAttribute(
* We successively try to parse the string as a resource type that the Attribute
* allows.
*/
-std::unique_ptr<Item> parseItemForAttribute(
+std::unique_ptr<Item> tryParseItemForAttribute(
const StringPiece& str, const Attribute* attr,
const std::function<void(const ResourceName&)>& onCreateReference) {
const uint32_t typeMask = attr->typeMask;
- std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
+ std::unique_ptr<Item> value = tryParseItemForAttribute(str, typeMask, onCreateReference);
if (value) {
return value;
}
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index a57d89dd0233..244047bae117 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -28,11 +28,6 @@
namespace aapt {
namespace ResourceUtils {
-/**
- * Convert an android::ResTable::resource_name to an aapt::ResourceName struct.
- */
-Maybe<ResourceName> toResourceName(const android::ResTable::resource_name& name);
-
/*
* Extracts the package, type, and name from a string of the format:
*
@@ -60,8 +55,8 @@ bool parseResourceName(const StringPiece& str, ResourceNameRef* outResource,
* If '+' was present in the reference, `outCreate` is set to true.
* If '*' was present in the reference, `outPrivate` is set to true.
*/
-bool tryParseReference(const StringPiece& str, ResourceNameRef* outReference,
- bool* outCreate = nullptr, bool* outPrivate = nullptr);
+bool parseReference(const StringPiece& str, ResourceNameRef* outReference,
+ bool* outCreate = nullptr, bool* outPrivate = nullptr);
/*
* Returns true if the string is in the form of a resource reference (@[+][package:]type/name).
@@ -72,7 +67,7 @@ bool isReference(const StringPiece& str);
* Returns true if the string was parsed as an attribute reference (?[package:][type/]name),
* with `outReference` set to the parsed reference.
*/
-bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outReference);
+bool parseAttributeReference(const StringPiece& str, ResourceNameRef* outReference);
/**
* Returns true if the string is in the form of an attribute reference(?[package:][type/]name).
@@ -80,19 +75,29 @@ bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outRefe
bool isAttributeReference(const StringPiece& str);
/**
- * Returns true if the value is a boolean, putting the result in `outValue`.
+ * Convert an android::ResTable::resource_name to an aapt::ResourceName struct.
+ */
+Maybe<ResourceName> toResourceName(const android::ResTable::resource_name& name);
+
+/**
+ * Returns a boolean value if the string is equal to TRUE, true, True, FALSE, false, or False.
+ */
+Maybe<bool> parseBool(const StringPiece& str);
+
+/**
+ * Returns a uint32_t if the string is an integer.
*/
-bool tryParseBool(const StringPiece& str, bool* outValue);
+Maybe<uint32_t> parseInt(const StringPiece& str);
/**
* Returns an ID if it the string represented a valid ID.
*/
-Maybe<ResourceId> tryParseResourceId(const StringPiece& str);
+Maybe<ResourceId> parseResourceId(const StringPiece& str);
/**
* Parses an SDK version, which can be an integer, or a letter from A-Z.
*/
-Maybe<int> tryParseSdkVersion(const StringPiece& str);
+Maybe<int> parseSdkVersion(const StringPiece& str);
/*
* Returns a Reference, or None Maybe instance if the string `str` was parsed as a
@@ -161,11 +166,11 @@ std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* enumAttr,
* The callback function onCreateReference is called when the parsed item is a
* reference to an ID that must be created (@+id/foo).
*/
-std::unique_ptr<Item> parseItemForAttribute(
+std::unique_ptr<Item> tryParseItemForAttribute(
const StringPiece& value, const Attribute* attr,
const std::function<void(const ResourceName&)>& onCreateReference = {});
-std::unique_ptr<Item> parseItemForAttribute(
+std::unique_ptr<Item> tryParseItemForAttribute(
const StringPiece& value, uint32_t typeMask,
const std::function<void(const ResourceName&)>& onCreateReference = {});
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index fb76914cc495..894cfcf72144 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -21,24 +21,12 @@
namespace aapt {
TEST(ResourceUtilsTest, ParseBool) {
- bool val = false;
- EXPECT_TRUE(ResourceUtils::tryParseBool("true", &val));
- EXPECT_TRUE(val);
-
- EXPECT_TRUE(ResourceUtils::tryParseBool("TRUE", &val));
- EXPECT_TRUE(val);
-
- EXPECT_TRUE(ResourceUtils::tryParseBool("True", &val));
- EXPECT_TRUE(val);
-
- EXPECT_TRUE(ResourceUtils::tryParseBool("false", &val));
- EXPECT_FALSE(val);
-
- EXPECT_TRUE(ResourceUtils::tryParseBool("FALSE", &val));
- EXPECT_FALSE(val);
-
- EXPECT_TRUE(ResourceUtils::tryParseBool("False", &val));
- EXPECT_FALSE(val);
+ EXPECT_EQ(Maybe<bool>(true), ResourceUtils::parseBool("true"));
+ EXPECT_EQ(Maybe<bool>(true), ResourceUtils::parseBool("TRUE"));
+ EXPECT_EQ(Maybe<bool>(true), ResourceUtils::parseBool("True"));
+ EXPECT_EQ(Maybe<bool>(false), ResourceUtils::parseBool("false"));
+ EXPECT_EQ(Maybe<bool>(false), ResourceUtils::parseBool("FALSE"));
+ EXPECT_EQ(Maybe<bool>(false), ResourceUtils::parseBool("False"));
}
TEST(ResourceUtilsTest, ParseResourceName) {
@@ -64,7 +52,7 @@ TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) {
ResourceNameRef actual;
bool create = false;
bool privateRef = false;
- EXPECT_TRUE(ResourceUtils::tryParseReference("@color/foo", &actual, &create, &privateRef));
+ EXPECT_TRUE(ResourceUtils::parseReference("@color/foo", &actual, &create, &privateRef));
EXPECT_EQ(expected, actual);
EXPECT_FALSE(create);
EXPECT_FALSE(privateRef);
@@ -75,7 +63,7 @@ TEST(ResourceUtilsTest, ParseReferenceWithPackage) {
ResourceNameRef actual;
bool create = false;
bool privateRef = false;
- EXPECT_TRUE(ResourceUtils::tryParseReference("@android:color/foo", &actual, &create,
+ EXPECT_TRUE(ResourceUtils::parseReference("@android:color/foo", &actual, &create,
&privateRef));
EXPECT_EQ(expected, actual);
EXPECT_FALSE(create);
@@ -87,7 +75,7 @@ TEST(ResourceUtilsTest, ParseReferenceWithSurroundingWhitespace) {
ResourceNameRef actual;
bool create = false;
bool privateRef = false;
- EXPECT_TRUE(ResourceUtils::tryParseReference("\t @android:color/foo\n \n\t", &actual,
+ EXPECT_TRUE(ResourceUtils::parseReference("\t @android:color/foo\n \n\t", &actual,
&create, &privateRef));
EXPECT_EQ(expected, actual);
EXPECT_FALSE(create);
@@ -99,7 +87,7 @@ TEST(ResourceUtilsTest, ParseAutoCreateIdReference) {
ResourceNameRef actual;
bool create = false;
bool privateRef = false;
- EXPECT_TRUE(ResourceUtils::tryParseReference("@+android:id/foo", &actual, &create,
+ EXPECT_TRUE(ResourceUtils::parseReference("@+android:id/foo", &actual, &create,
&privateRef));
EXPECT_EQ(expected, actual);
EXPECT_TRUE(create);
@@ -111,7 +99,7 @@ TEST(ResourceUtilsTest, ParsePrivateReference) {
ResourceNameRef actual;
bool create = false;
bool privateRef = false;
- EXPECT_TRUE(ResourceUtils::tryParseReference("@*android:id/foo", &actual, &create,
+ EXPECT_TRUE(ResourceUtils::parseReference("@*android:id/foo", &actual, &create,
&privateRef));
EXPECT_EQ(expected, actual);
EXPECT_FALSE(create);
@@ -122,7 +110,7 @@ TEST(ResourceUtilsTest, FailToParseAutoCreateNonIdReference) {
bool create = false;
bool privateRef = false;
ResourceNameRef actual;
- EXPECT_FALSE(ResourceUtils::tryParseReference("@+android:color/foo", &actual, &create,
+ EXPECT_FALSE(ResourceUtils::parseReference("@+android:color/foo", &actual, &create,
&privateRef));
}
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 4a865799372d..73682ab110c7 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -449,9 +449,7 @@ void Attribute::print(std::ostream* out) const {
printMask(out);
if (!symbols.empty()) {
- *out << " ["
- << util::joiner(symbols.begin(), symbols.end(), ", ")
- << "]";
+ *out << " [" << util::joiner(symbols, ", ") << "]";
}
if (minInt != std::numeric_limits<int32_t>::min()) {
@@ -600,7 +598,7 @@ void Style::print(std::ostream* out) const {
*out << parent.value().name.value();
}
*out << " ["
- << util::joiner(entries.begin(), entries.end(), ", ")
+ << util::joiner(entries, ", ")
<< "]";
}
@@ -645,7 +643,7 @@ Array* Array::clone(StringPool* newPool) const {
void Array::print(std::ostream* out) const {
*out << "(array) ["
- << util::joiner(items.begin(), items.end(), ", ")
+ << util::joiner(items, ", ")
<< "]";
}
@@ -730,7 +728,7 @@ Styleable* Styleable::clone(StringPool* /*newPool*/) const {
void Styleable::print(std::ostream* out) const {
*out << "(styleable) " << " ["
- << util::joiner(entries.begin(), entries.end(), ", ")
+ << util::joiner(entries, ", ")
<< "]";
}
diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h
index 319528e0ea1b..8a1021d49c39 100644
--- a/tools/aapt2/Source.h
+++ b/tools/aapt2/Source.h
@@ -35,7 +35,7 @@ struct Source {
Source() = default;
- inline Source(const StringPiece& path) : path(path.toString()) {
+ inline Source(const StringPiece& path) : path(path.toString()) { // NOLINT(implicit)
}
inline Source(const StringPiece& path, size_t line) : path(path.toString()), line(line) {
diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h
index b8bc5db7d6e4..9dc6a9c2b0d2 100644
--- a/tools/aapt2/ValueVisitor.h
+++ b/tools/aapt2/ValueVisitor.h
@@ -45,8 +45,9 @@ struct RawValueVisitor {
virtual void visit(Styleable* value) {}
};
+// NOLINT, do not add parentheses around T.
#define DECL_VISIT_COMPOUND_VALUE(T) \
- virtual void visit(T* value) { \
+ virtual void visit(T* value) { /* NOLINT */ \
visitSubValues(value); \
}
diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h
index 345ff6c56870..f835b06e762b 100644
--- a/tools/aapt2/compile/Png.h
+++ b/tools/aapt2/compile/Png.h
@@ -32,7 +32,7 @@ struct PngOptions {
class Png {
public:
- Png(IDiagnostics* diag) : mDiag(diag) {
+ explicit Png(IDiagnostics* diag) : mDiag(diag) {
}
bool process(const Source& source, std::istream* input, BigBuffer* outBuffer,
diff --git a/tools/aapt2/compile/Pseudolocalizer.h b/tools/aapt2/compile/Pseudolocalizer.h
index 7db88de13536..91d17d174d29 100644
--- a/tools/aapt2/compile/Pseudolocalizer.h
+++ b/tools/aapt2/compile/Pseudolocalizer.h
@@ -43,7 +43,7 @@ public:
kBidi,
};
- Pseudolocalizer(Method method);
+ explicit Pseudolocalizer(Method method);
void setMethod(Method method);
std::string start() { return mImpl->start(); }
std::string end() { return mImpl->end(); }
diff --git a/tools/aapt2/compile/XmlIdCollector.cpp b/tools/aapt2/compile/XmlIdCollector.cpp
index 9fc979c34353..3901419636b4 100644
--- a/tools/aapt2/compile/XmlIdCollector.cpp
+++ b/tools/aapt2/compile/XmlIdCollector.cpp
@@ -42,7 +42,7 @@ struct IdCollector : public xml::Visitor {
for (xml::Attribute& attr : element->attributes) {
ResourceNameRef name;
bool create = false;
- if (ResourceUtils::tryParseReference(attr.value, &name, &create, nullptr)) {
+ if (ResourceUtils::parseReference(attr.value, &name, &create, nullptr)) {
if (create && name.type == ResourceType::kId) {
auto iter = std::lower_bound(mOutSymbols->begin(), mOutSymbols->end(),
name, cmpName);
diff --git a/tools/aapt2/flatten/TableFlattener.h b/tools/aapt2/flatten/TableFlattener.h
index 0ab01974044b..b416f202ced5 100644
--- a/tools/aapt2/flatten/TableFlattener.h
+++ b/tools/aapt2/flatten/TableFlattener.h
@@ -26,7 +26,7 @@ class ResourceTable;
class TableFlattener : public IResourceTableConsumer {
public:
- TableFlattener(BigBuffer* buffer) : mBuffer(buffer) {
+ explicit TableFlattener(BigBuffer* buffer) : mBuffer(buffer) {
}
bool consume(IAaptContext* context, ResourceTable* table) override;
diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h
index f0559c03a8b8..72a932a499dd 100644
--- a/tools/aapt2/io/FileSystem.h
+++ b/tools/aapt2/io/FileSystem.h
@@ -29,7 +29,7 @@ namespace io {
*/
class RegularFile : public IFile {
public:
- RegularFile(const Source& source);
+ explicit RegularFile(const Source& source);
std::unique_ptr<IData> openAsData() override;
const Source& getSource() const override;
@@ -42,7 +42,7 @@ class FileCollection;
class FileCollectionIterator : public IFileCollectionIterator {
public:
- FileCollectionIterator(FileCollection* collection);
+ explicit FileCollectionIterator(FileCollection* collection);
bool hasNext() override;
io::IFile* next() override;
diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h
index 5ad119d1d6d4..565588e2db57 100644
--- a/tools/aapt2/io/ZipArchive.h
+++ b/tools/aapt2/io/ZipArchive.h
@@ -47,7 +47,7 @@ class ZipFileCollection;
class ZipFileCollectionIterator : public IFileCollectionIterator {
public:
- ZipFileCollectionIterator(ZipFileCollection* collection);
+ explicit ZipFileCollectionIterator(ZipFileCollection* collection);
bool hasNext() override;
io::IFile* next() override;
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index d45328fedba2..e84c2741e4ce 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -110,7 +110,7 @@ using StringMember = PrimitiveMember<std::string>;
template <typename T>
class PrimitiveArrayMember : public ClassMember {
public:
- PrimitiveArrayMember(const StringPiece& name) :
+ explicit PrimitiveArrayMember(const StringPiece& name) :
mName(name.toString()) {
}
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index ff777a3b60eb..5a2bb6ad9a72 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -59,11 +59,14 @@ struct LinkOptions {
std::string manifestPath;
std::vector<std::string> includePaths;
std::vector<std::string> overlayFiles;
+
+ // Java/Proguard options.
Maybe<std::string> generateJavaClassPath;
Maybe<std::string> customJavaPackage;
std::set<std::string> extraJavaPackages;
Maybe<std::string> generateProguardRulesPath;
Maybe<std::string> generateMainDexProguardRulesPath;
+
bool noAutoVersion = false;
bool noVersionVectors = false;
bool staticLib = false;
@@ -77,7 +80,13 @@ struct LinkOptions {
Maybe<std::string> privateSymbols;
ManifestFixerOptions manifestFixerOptions;
std::unordered_set<std::string> products;
+
+ // Split APK options.
TableSplitterOptions tableSplitterOptions;
+ std::vector<SplitConstraints> splitConstraints;
+ std::vector<std::string> splitPaths;
+
+ // Stable ID options.
std::unordered_map<ResourceName, ResourceId> stableIdMap;
Maybe<std::string> resourceIdMapPath;
};
@@ -585,7 +594,7 @@ static bool loadStableIdMap(IDiagnostics* diag, const std::string& path,
const size_t resIdStrLen = line.size() - resIdStartIdx;
StringPiece resIdStr = util::trimWhitespace(line.substr(resIdStartIdx, resIdStrLen));
- Maybe<ResourceId> maybeId = ResourceUtils::tryParseResourceId(resIdStr);
+ Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(resIdStr);
if (!maybeId) {
diag->error(DiagMessage(Source(path, lineNo)) << "invalid resource ID '"
<< resIdStr << "'");
@@ -597,6 +606,28 @@ static bool loadStableIdMap(IDiagnostics* diag, const std::string& path,
return true;
}
+static bool parseSplitParameter(const StringPiece& arg, IDiagnostics* diag,
+ std::string* outPath, SplitConstraints* outSplit) {
+ std::vector<std::string> parts = util::split(arg, ':');
+ if (parts.size() != 2) {
+ diag->error(DiagMessage() << "invalid split parameter '" << arg << "'");
+ diag->note(DiagMessage() << "should be --split path/to/output.apk:<config>[,<config>...]");
+ return false;
+ }
+ *outPath = parts[0];
+ std::vector<ConfigDescription> configs;
+ for (const StringPiece& configStr : util::tokenize(parts[1], ',')) {
+ configs.push_back({});
+ if (!ConfigDescription::parse(configStr, &configs.back())) {
+ diag->error(DiagMessage() << "invalid config '" << configStr
+ << "' in split parameter '" << arg << "'");
+ return false;
+ }
+ }
+ outSplit->configs.insert(configs.begin(), configs.end());
+ return true;
+}
+
class LinkCommand {
public:
LinkCommand(LinkContext* context, const LinkOptions& options) :
@@ -676,6 +707,30 @@ public:
appInfo.package = packageAttr->value;
+ if (xml::Attribute* versionCodeAttr =
+ manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode")) {
+ Maybe<uint32_t> maybeCode = ResourceUtils::parseInt(versionCodeAttr->value);
+ if (!maybeCode) {
+ diag->error(DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
+ << "invalid android:versionCode '"
+ << versionCodeAttr->value << "'");
+ return {};
+ }
+ appInfo.versionCode = maybeCode.value();
+ }
+
+ if (xml::Attribute* revisionCodeAttr =
+ manifestEl->findAttribute(xml::kSchemaAndroid, "revisionCode")) {
+ Maybe<uint32_t> maybeCode = ResourceUtils::parseInt(revisionCodeAttr->value);
+ if (!maybeCode) {
+ diag->error(DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
+ << "invalid android:revisionCode '"
+ << revisionCodeAttr->value << "'");
+ return {};
+ }
+ appInfo.revisionCode = maybeCode.value();
+ }
+
if (xml::Element* usesSdkEl = manifestEl->findChild({}, "uses-sdk")) {
if (xml::Attribute* minSdk =
usesSdkEl->findAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
@@ -767,11 +822,11 @@ public:
return true;
}
- std::unique_ptr<IArchiveWriter> makeArchiveWriter() {
+ std::unique_ptr<IArchiveWriter> makeArchiveWriter(const StringPiece& out) {
if (mOptions.outputToDirectory) {
- return createDirectoryArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
+ return createDirectoryArchiveWriter(mContext->getDiagnostics(), out);
} else {
- return createZipFileArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
+ return createZipFileArchiveWriter(mContext->getDiagnostics(), out);
}
}
@@ -1179,6 +1234,94 @@ public:
return true;
}
+ std::unique_ptr<xml::XmlResource> generateSplitManifest(const AppInfo& appInfo,
+ const SplitConstraints& constraints) {
+ std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
+
+ std::unique_ptr<xml::Namespace> namespaceAndroid = util::make_unique<xml::Namespace>();
+ namespaceAndroid->namespaceUri = xml::kSchemaAndroid;
+ namespaceAndroid->namespacePrefix = "android";
+
+ std::unique_ptr<xml::Element> manifestEl = util::make_unique<xml::Element>();
+ manifestEl->name = "manifest";
+ manifestEl->attributes.push_back(
+ xml::Attribute{ "", "package", appInfo.package });
+
+ if (appInfo.versionCode) {
+ manifestEl->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid,
+ "versionCode",
+ std::to_string(appInfo.versionCode.value()) });
+ }
+
+ if (appInfo.revisionCode) {
+ manifestEl->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid,
+ "revisionCode", std::to_string(appInfo.revisionCode.value()) });
+ }
+
+ std::stringstream splitName;
+ splitName << "config." << util::joiner(constraints.configs, "_");
+
+ manifestEl->attributes.push_back(
+ xml::Attribute{ "", "split", splitName.str() });
+
+ std::unique_ptr<xml::Element> applicationEl = util::make_unique<xml::Element>();
+ applicationEl->name = "application";
+ applicationEl->attributes.push_back(
+ xml::Attribute{ xml::kSchemaAndroid, "hasCode", "false" });
+
+ manifestEl->addChild(std::move(applicationEl));
+ namespaceAndroid->addChild(std::move(manifestEl));
+ doc->root = std::move(namespaceAndroid);
+ return doc;
+ }
+
+ /**
+ * Writes the AndroidManifest, ResourceTable, and all XML files referenced by the ResourceTable
+ * to the IArchiveWriter.
+ */
+ bool writeApk(IArchiveWriter* writer, proguard::KeepSet* keepSet, xml::XmlResource* manifest,
+ ResourceTable* table) {
+ const bool keepRawValues = mOptions.staticLib;
+ bool result = flattenXml(manifest, "AndroidManifest.xml", {}, keepRawValues, writer,
+ mContext);
+ if (!result) {
+ return false;
+ }
+
+ ResourceFileFlattenerOptions fileFlattenerOptions;
+ fileFlattenerOptions.keepRawValues = keepRawValues;
+ fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
+ fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
+ fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+ fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
+ fileFlattenerOptions.updateProguardSpec =
+ static_cast<bool>(mOptions.generateProguardRulesPath);
+
+ ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, keepSet);
+
+ if (!fileFlattener.flatten(table, writer)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
+ return false;
+ }
+
+ if (mOptions.staticLib) {
+ if (!flattenTableToPb(table, writer)) {
+ mContext->getDiagnostics()->error(DiagMessage()
+ << "failed to write resources.arsc.flat");
+ return false;
+ }
+ } else {
+ if (!flattenTable(table, writer)) {
+ mContext->getDiagnostics()->error(DiagMessage()
+ << "failed to write resources.arsc");
+ return false;
+ }
+ }
+ return true;
+ }
+
int run(const std::vector<std::string>& inputFiles) {
// Load the AndroidManifest.xml
std::unique_ptr<xml::XmlResource> manifestXml = loadXml(mOptions.manifestPath,
@@ -1187,30 +1330,33 @@ public:
return 1;
}
+ // First extract the Package name without modifying it (via --rename-manifest-package).
if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
mContext->getDiagnostics())) {
- AppInfo& appInfo = maybeAppInfo.value();
+ const AppInfo& appInfo = maybeAppInfo.value();
mContext->setCompilationPackage(appInfo.package);
- if (appInfo.minSdkVersion) {
- if (Maybe<int> maybeMinSdkVersion =
- ResourceUtils::tryParseSdkVersion(appInfo.minSdkVersion.value())) {
- mContext->setMinSdkVersion(maybeMinSdkVersion.value());
- }
- }
- } else {
+ }
+
+ ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
+ if (!manifestFixer.consume(mContext, manifestXml.get())) {
return 1;
}
- if (!util::isJavaPackageName(mContext->getCompilationPackage())) {
- mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
- << "invalid package name '"
- << mContext->getCompilationPackage()
- << "'");
+ Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
+ mContext->getDiagnostics());
+ if (!maybeAppInfo) {
return 1;
}
- mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
+ const AppInfo& appInfo = maybeAppInfo.value();
+ if (appInfo.minSdkVersion) {
+ if (Maybe<int> maybeMinSdkVersion =
+ ResourceUtils::parseSdkVersion(appInfo.minSdkVersion.value())) {
+ mContext->setMinSdkVersion(maybeMinSdkVersion.value());
+ }
+ }
+ mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
if (mContext->getCompilationPackage() == "android") {
mContext->setPackageId(0x01);
} else {
@@ -1258,9 +1404,7 @@ public:
DiagMessage() << "failed moving private attributes");
return 1;
}
- }
- if (!mOptions.staticLib) {
// Assign IDs if we are building a regular app.
IdAssigner idAssigner(&mOptions.stableIdMap);
if (!idAssigner.consume(mContext, &mFinalTable)) {
@@ -1304,45 +1448,118 @@ public:
mContext->getExternalSymbols()->prependSource(
util::make_unique<ResourceTableSymbolSource>(&mFinalTable));
- {
- ReferenceLinker linker;
- if (!linker.consume(mContext, &mFinalTable)) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed linking references");
+ ReferenceLinker linker;
+ if (!linker.consume(mContext, &mFinalTable)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed linking references");
+ return 1;
+ }
+
+ if (mOptions.staticLib) {
+ if (!mOptions.products.empty()) {
+ mContext->getDiagnostics()->warn(
+ DiagMessage() << "can't select products when building static library");
+ }
+ } else {
+ ProductFilter productFilter(mOptions.products);
+ if (!productFilter.consume(mContext, &mFinalTable)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
+ return 1;
+ }
+ }
+
+ if (!mOptions.noAutoVersion) {
+ AutoVersioner versioner;
+ if (!versioner.consume(mContext, &mFinalTable)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed versioning styles");
return 1;
}
+ }
+
+ if (!mOptions.staticLib && mContext->getMinSdkVersion() > 0) {
+ if (mContext->verbose()) {
+ mContext->getDiagnostics()->note(
+ DiagMessage() << "collapsing resource versions for minimum SDK "
+ << mContext->getMinSdkVersion());
+ }
- if (mOptions.staticLib) {
- if (!mOptions.products.empty()) {
- mContext->getDiagnostics()->warn(
- DiagMessage() << "can't select products when building static library");
+ VersionCollapser collapser;
+ if (!collapser.consume(mContext, &mFinalTable)) {
+ return 1;
+ }
+ }
+
+ proguard::KeepSet proguardKeepSet;
+ proguard::KeepSet proguardMainDexKeepSet;
+
+ if (mOptions.staticLib) {
+ if (mOptions.tableSplitterOptions.configFilter != nullptr ||
+ mOptions.tableSplitterOptions.preferredDensity) {
+ mContext->getDiagnostics()->warn(
+ DiagMessage() << "can't strip resources when building static library");
+ }
+ } else {
+ // Adjust the SplitConstraints so that their SDK version is stripped if it is less
+ // than or equal to the minSdk. Otherwise the resources that have had their SDK version
+ // stripped due to minSdk won't ever match.
+ std::vector<SplitConstraints> adjustedConstraintsList;
+ adjustedConstraintsList.reserve(mOptions.splitConstraints.size());
+ for (const SplitConstraints& constraints : mOptions.splitConstraints) {
+ SplitConstraints adjustedConstraints;
+ for (const ConfigDescription& config : constraints.configs) {
+ if (config.sdkVersion <= mContext->getMinSdkVersion()) {
+ adjustedConstraints.configs.insert(config.copyWithoutSdkVersion());
+ } else {
+ adjustedConstraints.configs.insert(config);
+ }
}
+ adjustedConstraintsList.push_back(std::move(adjustedConstraints));
+ }
- if (mOptions.tableSplitterOptions.configFilter != nullptr ||
- mOptions.tableSplitterOptions.preferredDensity) {
- mContext->getDiagnostics()->warn(
- DiagMessage() << "can't strip resources when building static library");
+ TableSplitter tableSplitter(adjustedConstraintsList, mOptions.tableSplitterOptions);
+ if (!tableSplitter.verifySplitConstraints(mContext)) {
+ return 1;
+ }
+ tableSplitter.splitTable(&mFinalTable);
+
+ // Now we need to write out the Split APKs.
+ auto pathIter = mOptions.splitPaths.begin();
+ auto splitConstraintsIter = adjustedConstraintsList.begin();
+ for (std::unique_ptr<ResourceTable>& splitTable : tableSplitter.getSplits()) {
+ if (mContext->verbose()) {
+ mContext->getDiagnostics()->note(
+ DiagMessage(*pathIter) << "generating split with configurations '"
+ << util::joiner(splitConstraintsIter->configs, ", ") << "'");
}
- } else {
- ProductFilter productFilter(mOptions.products);
- if (!productFilter.consume(mContext, &mFinalTable)) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
+
+ std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter(*pathIter);
+ if (!archiveWriter) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
+ return 1;
+ }
+
+ // Generate an AndroidManifest.xml for each split.
+ std::unique_ptr<xml::XmlResource> splitManifest =
+ generateSplitManifest(appInfo, *splitConstraintsIter);
+
+ XmlReferenceLinker linker;
+ if (!linker.consume(mContext, splitManifest.get())) {
+ mContext->getDiagnostics()->error(
+ DiagMessage() << "failed to create Split AndroidManifest.xml");
return 1;
}
- // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
- // level.
- TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
- if (!tableSplitter.verifySplitConstraints(mContext)) {
+ if (!writeApk(archiveWriter.get(), &proguardKeepSet, splitManifest.get(),
+ splitTable.get())) {
return 1;
}
- tableSplitter.splitTable(&mFinalTable);
+
+ ++pathIter;
+ ++splitConstraintsIter;
}
}
- proguard::KeepSet proguardKeepSet;
- proguard::KeepSet proguardMainDexKeepSet;
-
- std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter();
+ // Start writing the base APK.
+ std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter(mOptions.outputPath);
if (!archiveWriter) {
mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
return 1;
@@ -1350,11 +1567,6 @@ public:
bool error = false;
{
- ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
- if (!manifestFixer.consume(mContext, manifestXml.get())) {
- error = true;
- }
-
// AndroidManifest.xml has no resource name, but the CallSite is built from the name
// (aka, which package the AndroidManifest.xml is coming from).
// So we give it a package name so it can see local resources.
@@ -1382,13 +1594,6 @@ public:
error = true;
}
}
-
- const bool keepRawValues = mOptions.staticLib;
- bool result = flattenXml(manifestXml.get(), "AndroidManifest.xml", {},
- keepRawValues, archiveWriter.get(), mContext);
- if (!result) {
- error = true;
- }
} else {
error = true;
}
@@ -1399,58 +1604,10 @@ public:
return 1;
}
- if (!mOptions.noAutoVersion) {
- AutoVersioner versioner;
- if (!versioner.consume(mContext, &mFinalTable)) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed versioning styles");
- return 1;
- }
- }
-
- if (!mOptions.staticLib && mContext->getMinSdkVersion() > 0) {
- if (mContext->verbose()) {
- mContext->getDiagnostics()->note(
- DiagMessage() << "collapsing resource versions for minimum SDK "
- << mContext->getMinSdkVersion());
- }
-
- VersionCollapser collapser;
- if (!collapser.consume(mContext, &mFinalTable)) {
- return 1;
- }
- }
-
- // Write out the table to an archive. Optimizations to the table should come before this
- // step.
- ResourceFileFlattenerOptions fileFlattenerOptions;
- fileFlattenerOptions.keepRawValues = mOptions.staticLib;
- fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
- fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
- fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
- fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
- fileFlattenerOptions.updateProguardSpec =
- static_cast<bool>(mOptions.generateProguardRulesPath);
- ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
-
- if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
+ if (!writeApk(archiveWriter.get(), &proguardKeepSet, manifestXml.get(), &mFinalTable)) {
return 1;
}
- if (mOptions.staticLib) {
- if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
- mContext->getDiagnostics()->error(DiagMessage()
- << "failed to write resources.arsc.flat");
- return 1;
- }
- } else {
- if (!flattenTable(&mFinalTable, archiveWriter.get())) {
- mContext->getDiagnostics()->error(DiagMessage()
- << "failed to write resources.arsc");
- return 1;
- }
- }
-
if (mOptions.generateJavaClassPath) {
JavaClassGeneratorOptions options;
options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
@@ -1538,6 +1695,7 @@ int link(const std::vector<StringPiece>& args) {
bool requireLocalization = false;
bool verbose = false;
Maybe<std::string> stableIdFilePath;
+ std::vector<std::string> splitArgs;
Flags flags = Flags()
.requiredFlag("-o", "Output path", &options.outputPath)
.requiredFlag("--manifest", "Path to the Android manifest to build",
@@ -1623,6 +1781,9 @@ int link(const std::vector<StringPiece>& args) {
&options.manifestFixerOptions.renameInstrumentationTargetPackage)
.optionalFlagList("-0", "File extensions not to compress",
&options.extensionsToNotCompress)
+ .optionalFlagList("--split", "Split resources matching a set of configs out to a "
+ "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
+ &splitArgs)
.optionalSwitch("-v", "Enables verbose logging",
&verbose);
@@ -1741,6 +1902,16 @@ int link(const std::vector<StringPiece>& args) {
".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"});
+ // Parse the split parameters.
+ for (const std::string& splitArg : splitArgs) {
+ options.splitPaths.push_back({});
+ options.splitConstraints.push_back({});
+ if (!parseSplitParameter(splitArg, context.getDiagnostics(), &options.splitPaths.back(),
+ &options.splitConstraints.back())) {
+ return 1;
+ }
+ }
+
// Turn off auto versioning for static-libs.
if (options.staticLib) {
options.noAutoVersion = true;
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 55b587e57013..2e81266015e1 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -41,7 +41,7 @@ struct ManifestFixerOptions {
*/
class ManifestFixer : public IXmlResourceConsumer {
public:
- ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
+ explicit ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
}
bool consume(IAaptContext* context, xml::XmlResource* doc) override;
diff --git a/tools/aapt2/link/ProductFilter.h b/tools/aapt2/link/ProductFilter.h
index d2edd38289dc..7724e140427b 100644
--- a/tools/aapt2/link/ProductFilter.h
+++ b/tools/aapt2/link/ProductFilter.h
@@ -29,7 +29,7 @@ class ProductFilter {
public:
using ResourceConfigValueIter = std::vector<std::unique_ptr<ResourceConfigValue>>::iterator;
- ProductFilter(std::unordered_set<std::string> products) : mProducts(products) { }
+ explicit ProductFilter(std::unordered_set<std::string> products) : mProducts(products) { }
ResourceConfigValueIter selectProductToKeep(const ResourceNameRef& name,
const ResourceConfigValueIter begin,
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 6aa9c0edd059..be7aca3ca49f 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -138,7 +138,7 @@ private:
const Attribute* attr) {
if (RawString* rawString = valueCast<RawString>(value.get())) {
std::unique_ptr<Item> transformed =
- ResourceUtils::parseItemForAttribute(*rawString->value, attr);
+ ResourceUtils::tryParseItemForAttribute(*rawString->value, attr);
// If we could not parse as any specific type, try a basic STRING.
if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index a29d8dcfe3c6..59ffe15fd4a4 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -106,7 +106,7 @@ public:
}
const Attribute* attribute = &attr.compiledAttribute.value().attribute;
- attr.compiledValue = ResourceUtils::parseItemForAttribute(attr.value,
+ attr.compiledValue = ResourceUtils::tryParseItemForAttribute(attr.value,
attribute);
if (!attr.compiledValue &&
!(attribute->typeMask & android::ResTable_map::TYPE_STRING)) {
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index bd01b64281d5..bd31416a5cee 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -54,7 +54,7 @@ public:
Symbol() : Symbol(Maybe<ResourceId>{}) {
}
- Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {
+ explicit Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {
}
Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr) :
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 95c0173f921a..a68d6f67324f 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,14 @@
# Android Asset Packaging Tool 2.0 (AAPT2) release notes
+## Version 2.1
+### `aapt2 link ...`
+- Configuration Split APK support: supports splitting resources that match a set of
+ configurations to a separate APK which can be loaded alongside the base APK on
+ API 21+ devices. This is done using the flag
+ `--split path/to/split.apk:<config1>[,<config2>,...]`.
+- SDK version resource filtering: Resources with an SDK version qualifier that is unreachable
+ at runtime due to the minimum SDK level declared by the AndroidManifest.xml are stripped.
+
## Version 2.0
### `aapt2 compile ...`
- Pseudo-localization: generates pseudolocalized versions of default strings when the
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 2dfe2a239900..08b9ee9cbe1b 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -17,6 +17,7 @@
#include "ConfigDescription.h"
#include "ResourceTable.h"
#include "split/TableSplitter.h"
+#include "util/Util.h"
#include <algorithm>
#include <map>
@@ -76,7 +77,6 @@ public:
// in multiple splits.
const ConfigDescription& config = entry.first;
const std::vector<ResourceConfigValue*>& relatedValues = entry.second;
-
auto densityValueIter = mDensityDependentConfigToDensityMap.find(config);
if (densityValueIter != mDensityDependentConfigToDensityMap.end()) {
// Select the best one!
@@ -89,12 +89,12 @@ public:
thisValue->config.isBetterThan(bestValue->config, &targetDensity)) {
bestValue = thisValue;
}
-
- // When we select one of these, they are all claimed such that the base
- // doesn't include any anymore.
- (*claimedValues)[thisValue] = true;
}
assert(bestValue);
+
+ // When we select one of these, they are all claimed such that the base
+ // doesn't include any anymore.
+ (*claimedValues)[bestValue] = true;
selected.push_back(bestValue);
}
}
@@ -135,7 +135,6 @@ static void markNonPreferredDensitiesAsClaimed(uint16_t preferredDensity,
assert(bestValue);
}
}
-
bool TableSplitter::verifySplitConstraints(IAaptContext* context) {
bool error = false;
for (size_t i = 0; i < mSplitConstraints.size(); i++) {
diff --git a/tools/aapt2/split/TableSplitter.h b/tools/aapt2/split/TableSplitter.h
index 15e0764c4259..2fa5c47d5bd6 100644
--- a/tools/aapt2/split/TableSplitter.h
+++ b/tools/aapt2/split/TableSplitter.h
@@ -60,7 +60,7 @@ public:
void splitTable(ResourceTable* originalTable);
- const std::vector<std::unique_ptr<ResourceTable>>& getSplits() {
+ std::vector<std::unique_ptr<ResourceTable>>& getSplits() {
return mSplits;
}
diff --git a/tools/aapt2/split/TableSplitter_test.cpp b/tools/aapt2/split/TableSplitter_test.cpp
index bad02a5cb332..5150e82b6d93 100644
--- a/tools/aapt2/split/TableSplitter_test.cpp
+++ b/tools/aapt2/split/TableSplitter_test.cpp
@@ -52,6 +52,71 @@ TEST(TableSplitterTest, NoSplitPreferredDensity) {
EXPECT_NE(nullptr, test::getValue<Id>(table.get(), "android:string/one"));
}
+TEST(TableSplitterTest, SplitTableByDensity) {
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+ .addFileReference("android:drawable/foo", "res/drawable-mdpi/foo.png",
+ test::parseConfigOrDie("mdpi"))
+ .addFileReference("android:drawable/foo", "res/drawable-hdpi/foo.png",
+ test::parseConfigOrDie("hdpi"))
+ .addFileReference("android:drawable/foo", "res/drawable-xhdpi/foo.png",
+ test::parseConfigOrDie("xhdpi"))
+ .addFileReference("android:drawable/foo", "res/drawable-xxhdpi/foo.png",
+ test::parseConfigOrDie("xxhdpi"))
+ .build();
+
+ std::vector<SplitConstraints> constraints;
+ constraints.push_back(SplitConstraints{ { test::parseConfigOrDie("mdpi") } });
+ constraints.push_back(SplitConstraints{ { test::parseConfigOrDie("hdpi") } });
+ constraints.push_back(SplitConstraints{ { test::parseConfigOrDie("xhdpi") } });
+
+ TableSplitter splitter(constraints, TableSplitterOptions{});
+ splitter.splitTable(table.get());
+
+ ASSERT_EQ(3u, splitter.getSplits().size());
+
+ ResourceTable* splitOne = splitter.getSplits()[0].get();
+ ResourceTable* splitTwo = splitter.getSplits()[1].get();
+ ResourceTable* splitThree = splitter.getSplits()[2].get();
+
+ // Just xxhdpi should be in the base.
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(), "android:drawable/foo",
+ test::parseConfigOrDie("mdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(), "android:drawable/foo",
+ test::parseConfigOrDie("hdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(), "android:drawable/foo",
+ test::parseConfigOrDie("xhdpi")));
+ EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(table.get(), "android:drawable/foo",
+ test::parseConfigOrDie("xxhdpi")));
+
+ // Each split should have one and only one drawable.
+ EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(splitOne, "android:drawable/foo",
+ test::parseConfigOrDie("mdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitOne, "android:drawable/foo",
+ test::parseConfigOrDie("hdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitOne, "android:drawable/foo",
+ test::parseConfigOrDie("xhdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitOne, "android:drawable/foo",
+ test::parseConfigOrDie("xxhdpi")));
+
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitTwo, "android:drawable/foo",
+ test::parseConfigOrDie("mdpi")));
+ EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(splitTwo, "android:drawable/foo",
+ test::parseConfigOrDie("hdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitTwo, "android:drawable/foo",
+ test::parseConfigOrDie("xhdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitTwo, "android:drawable/foo",
+ test::parseConfigOrDie("xxhdpi")));
+
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitThree, "android:drawable/foo",
+ test::parseConfigOrDie("mdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitThree, "android:drawable/foo",
+ test::parseConfigOrDie("hdpi")));
+ EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(splitThree, "android:drawable/foo",
+ test::parseConfigOrDie("xhdpi")));
+ EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(splitThree, "android:drawable/foo",
+ test::parseConfigOrDie("xxhdpi")));
+}
+
TEST(TableSplitterTest, SplitTableByConfigAndDensity) {
ResourceTable table;
@@ -78,12 +143,12 @@ TEST(TableSplitterTest, SplitTableByConfigAndDensity) {
ResourceTable* splitOne = splitter.getSplits()[0].get();
ResourceTable* splitTwo = splitter.getSplits()[1].get();
- // Since a split was defined, all densities should be gone from base.
+ // All but the xxhdpi resource should be gone, since there were closer matches in land-xhdpi.
EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "android:string/foo",
test::parseConfigOrDie("land-hdpi")));
EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "android:string/foo",
test::parseConfigOrDie("land-xhdpi")));
- EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "android:string/foo",
+ EXPECT_NE(nullptr, test::getValueForConfig<Id>(&table, "android:string/foo",
test::parseConfigOrDie("land-xxhdpi")));
EXPECT_NE(nullptr, test::getValueForConfig<Id>(splitOne, "android:string/foo",
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index c0c016032921..637e991a573f 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -46,12 +46,12 @@ public:
return *this;
}
- ResourceTableBuilder& addSimple(const StringPiece& name, const ResourceId id = {}) {
+ ResourceTableBuilder& addSimple(const StringPiece& name, const ResourceId& id = {}) {
return addValue(name, id, util::make_unique<Id>());
}
ResourceTableBuilder& addSimple(const StringPiece& name, const ConfigDescription& config,
- const ResourceId id = {}) {
+ const ResourceId& id = {}) {
return addValue(name, config, id, util::make_unique<Id>());
}
@@ -59,7 +59,7 @@ public:
return addReference(name, {}, ref);
}
- ResourceTableBuilder& addReference(const StringPiece& name, const ResourceId id,
+ ResourceTableBuilder& addReference(const StringPiece& name, const ResourceId& id,
const StringPiece& ref) {
return addValue(name, id, util::make_unique<Reference>(parseNameOrDie(ref)));
}
@@ -68,12 +68,12 @@ public:
return addString(name, {}, str);
}
- ResourceTableBuilder& addString(const StringPiece& name, const ResourceId id,
+ ResourceTableBuilder& addString(const StringPiece& name, const ResourceId& id,
const StringPiece& str) {
return addValue(name, id, util::make_unique<String>(mTable->stringPool.makeRef(str)));
}
- ResourceTableBuilder& addString(const StringPiece& name, const ResourceId id,
+ ResourceTableBuilder& addString(const StringPiece& name, const ResourceId& id,
const ConfigDescription& config, const StringPiece& str) {
return addValue(name, config, id,
util::make_unique<String>(mTable->stringPool.makeRef(str)));
@@ -83,7 +83,7 @@ public:
return addFileReference(name, {}, path);
}
- ResourceTableBuilder& addFileReference(const StringPiece& name, const ResourceId id,
+ ResourceTableBuilder& addFileReference(const StringPiece& name, const ResourceId& id,
const StringPiece& path) {
return addValue(name, id,
util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
@@ -100,13 +100,13 @@ public:
return addValue(name, {}, std::move(value));
}
- ResourceTableBuilder& addValue(const StringPiece& name, const ResourceId id,
+ ResourceTableBuilder& addValue(const StringPiece& name, const ResourceId& id,
std::unique_ptr<Value> value) {
return addValue(name, {}, id, std::move(value));
}
ResourceTableBuilder& addValue(const StringPiece& name, const ConfigDescription& config,
- const ResourceId id, std::unique_ptr<Value> value) {
+ const ResourceId& id, std::unique_ptr<Value> value) {
ResourceName resName = parseNameOrDie(name);
bool result = mTable->addResourceAllowMangled(resName, id, config, {},
std::move(value), &mDiagnostics);
@@ -114,7 +114,7 @@ public:
return *this;
}
- ResourceTableBuilder& setSymbolState(const StringPiece& name, ResourceId id,
+ ResourceTableBuilder& setSymbolState(const StringPiece& name, const ResourceId& id,
SymbolState state) {
ResourceName resName = parseNameOrDie(name);
Symbol symbol;
@@ -130,7 +130,7 @@ public:
};
inline std::unique_ptr<Reference> buildReference(const StringPiece& ref,
- Maybe<ResourceId> id = {}) {
+ const Maybe<ResourceId>& id = {}) {
std::unique_ptr<Reference> reference = util::make_unique<Reference>(parseNameOrDie(ref));
reference->id = id;
return reference;
@@ -151,7 +151,7 @@ private:
public:
template <typename... Args>
- ValueBuilder(Args&&... args) : mValue(new T{ std::forward<Args>(args)... }) {
+ explicit ValueBuilder(Args&&... args) : mValue(new T{ std::forward<Args>(args)... }) {
}
template <typename... Args>
@@ -175,7 +175,7 @@ private:
std::unique_ptr<Attribute> mAttr;
public:
- AttributeBuilder(bool weak = false) : mAttr(util::make_unique<Attribute>(weak)) {
+ explicit AttributeBuilder(bool weak = false) : mAttr(util::make_unique<Attribute>(weak)) {
mAttr->typeMask = android::ResTable_map::TYPE_ANY;
}
@@ -211,7 +211,7 @@ public:
return *this;
}
- StyleBuilder& addItem(const StringPiece& str, ResourceId id, std::unique_ptr<Item> value) {
+ StyleBuilder& addItem(const StringPiece& str, const ResourceId& id, std::unique_ptr<Item> value) {
addItem(str, std::move(value));
mStyle->entries.back().key.id = id;
return *this;
@@ -227,7 +227,7 @@ private:
std::unique_ptr<Styleable> mStyleable = util::make_unique<Styleable>();
public:
- StyleableBuilder& addItem(const StringPiece& str, Maybe<ResourceId> id = {}) {
+ StyleableBuilder& addItem(const StringPiece& str, const Maybe<ResourceId>& id = {}) {
mStyleable->entries.push_back(Reference(parseNameOrDie(str)));
mStyleable->entries.back().id = id;
return *this;
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 624a71a382c9..7fafcbeb1a04 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -104,7 +104,7 @@ private:
Source mSource;
public:
- TestFile(const StringPiece& path) : mSource(path) {}
+ explicit TestFile(const StringPiece& path) : mSource(path) {}
std::unique_ptr<io::IData> openAsData() override {
return {};
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index b053e07eafde..54f16db3d2f9 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -87,7 +87,7 @@ public:
return *this;
}
- ContextBuilder& setNameManglerPolicy(NameManglerPolicy policy) {
+ ContextBuilder& setNameManglerPolicy(const NameManglerPolicy& policy) {
mContext->mNameMangler = NameMangler(policy);
return *this;
}
diff --git a/tools/aapt2/util/BigBuffer.h b/tools/aapt2/util/BigBuffer.h
index cad2a2e63be1..ba8532f829e6 100644
--- a/tools/aapt2/util/BigBuffer.h
+++ b/tools/aapt2/util/BigBuffer.h
@@ -63,7 +63,7 @@ public:
* Create a BigBuffer with block allocation sizes
* of blockSize.
*/
- BigBuffer(size_t blockSize);
+ explicit BigBuffer(size_t blockSize);
BigBuffer(const BigBuffer&) = delete; // No copying.
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index 4d8a1feb63b1..52c2052aec3d 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -109,7 +109,7 @@ bool appendArgsFromFile(const StringPiece& path, std::vector<std::string>* outAr
*/
class FileFilter {
public:
- FileFilter(IDiagnostics* diag) : mDiag(diag) {
+ explicit FileFilter(IDiagnostics* diag) : mDiag(diag) {
}
/*
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index a31bc89fa98b..129f6d9d9716 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -43,12 +43,12 @@ public:
Maybe(const Maybe& rhs);
template <typename U>
- Maybe(const Maybe<U>& rhs);
+ Maybe(const Maybe<U>& rhs); // NOLINT(implicit)
Maybe(Maybe&& rhs);
template <typename U>
- Maybe(Maybe<U>&& rhs);
+ Maybe(Maybe<U>&& rhs); // NOLINT(implicit)
Maybe& operator=(const Maybe& rhs);
@@ -63,12 +63,12 @@ public:
/**
* Construct a Maybe holding a value.
*/
- Maybe(const T& value);
+ Maybe(const T& value); // NOLINT(implicit)
/**
* Construct a Maybe holding a value.
*/
- Maybe(T&& value);
+ Maybe(T&& value); // NOLINT(implicit)
/**
* True if this holds a value, false if
diff --git a/tools/aapt2/util/StringPiece.h b/tools/aapt2/util/StringPiece.h
index f5c985bd9fff..4300a67d3581 100644
--- a/tools/aapt2/util/StringPiece.h
+++ b/tools/aapt2/util/StringPiece.h
@@ -41,8 +41,8 @@ public:
BasicStringPiece();
BasicStringPiece(const BasicStringPiece<TChar>& str);
- BasicStringPiece(const std::basic_string<TChar>& str);
- BasicStringPiece(const TChar* str);
+ BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit)
+ BasicStringPiece(const TChar* str); // NOLINT(implicit)
BasicStringPiece(const TChar* str, size_t len);
BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 4a10987b4400..998ecf7702bd 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -101,12 +101,16 @@ std::unique_ptr<T> make_unique(Args&&... args) {
* Writes a set of items to the std::ostream, joining the times with the provided
* separator.
*/
-template <typename Iterator>
-::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
- const char* sep) {
- return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
- for (auto iter = begin; iter != end; ++iter) {
- if (iter != begin) {
+template <typename Container>
+::std::function<::std::ostream&(::std::ostream&)> joiner(const Container& container,
+ const char* sep) {
+ using std::begin;
+ using std::end;
+ const auto beginIter = begin(container);
+ const auto endIter = end(container);
+ return [beginIter, endIter, sep](::std::ostream& out) -> ::std::ostream& {
+ for (auto iter = beginIter; iter != endIter; ++iter) {
+ if (iter != beginIter) {
out << sep;
}
out << *iter;
@@ -242,7 +246,7 @@ private:
const iterator mEnd;
};
-inline Tokenizer tokenize(StringPiece str, char sep) {
+inline Tokenizer tokenize(const StringPiece& str, char sep) {
return Tokenizer(str, sep);
}
@@ -281,7 +285,7 @@ bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
* In the aapt namespace for lookup.
*/
inline ::std::ostream& operator<<(::std::ostream& out,
- ::std::function<::std::ostream&(::std::ostream&)> f) {
+ const ::std::function<::std::ostream&(::std::ostream&)>& f) {
return f(out);
}
diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h
index ee51b360feb4..a24d109abf34 100644
--- a/tools/aapt2/xml/XmlPullParser.h
+++ b/tools/aapt2/xml/XmlPullParser.h
@@ -60,7 +60,7 @@ public:
static bool skipCurrentElement(XmlPullParser* parser);
static bool isGoodEvent(Event event);
- XmlPullParser(std::istream& in);
+ explicit XmlPullParser(std::istream& in);
~XmlPullParser();
/**
diff --git a/tools/split-select/SplitSelector.h b/tools/split-select/SplitSelector.h
index 193fda7077d3..120354f608f3 100644
--- a/tools/split-select/SplitSelector.h
+++ b/tools/split-select/SplitSelector.h
@@ -29,7 +29,7 @@ namespace split {
class SplitSelector {
public:
SplitSelector();
- SplitSelector(const android::Vector<SplitDescription>& splits);
+ explicit SplitSelector(const android::Vector<SplitDescription>& splits);
android::Vector<SplitDescription> getBestSplits(const SplitDescription& target) const;