AAPT2: allow regexes for extensions to not compress

Change-Id: I09d2ad1d1466643ca7628c6480224e16b9002ee5
Fixes: 67575899
Test: added + manual
This commit is contained in:
Izabela Orlowska
2018-06-01 12:06:31 +01:00
parent 854a76c870
commit 0faba5fdfa
7 changed files with 81 additions and 1 deletions

View File

@@ -268,6 +268,7 @@ struct ResourceFileFlattenerOptions {
bool update_proguard_spec = false;
OutputFormat output_format = OutputFormat::kApk;
std::unordered_set<std::string> extensions_to_not_compress;
Maybe<std::regex> regex_to_not_compress;
};
// A sampling of public framework resource IDs.
@@ -377,11 +378,18 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions&
}
}
// TODO(rtmitchell): turn this function into a variable that points to a method that retrieves the
// compression flag
uint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
if (options_.do_not_compress_anything) {
return 0;
}
if (options_.regex_to_not_compress
&& std::regex_search(str.to_string(), options_.regex_to_not_compress.value())) {
return 0;
}
for (const std::string& extension : options_.extensions_to_not_compress) {
if (util::EndsWith(str, extension)) {
return 0;
@@ -1530,7 +1538,11 @@ class Linker {
for (auto& entry : merged_assets) {
uint32_t compression_flags = ArchiveEntry::kCompress;
std::string extension = file::GetExtension(entry.first).to_string();
if (options_.extensions_to_not_compress.count(extension) > 0) {
if (options_.do_not_compress_anything
|| options_.extensions_to_not_compress.count(extension) > 0
|| (options_.regex_to_not_compress
&& std::regex_search(extension, options_.regex_to_not_compress.value()))) {
compression_flags = 0u;
}
@@ -1558,6 +1570,7 @@ class Linker {
file_flattener_options.keep_raw_values = keep_raw_values;
file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
file_flattener_options.regex_to_not_compress = options_.regex_to_not_compress;
file_flattener_options.no_auto_version = options_.no_auto_version;
file_flattener_options.no_version_vectors = options_.no_version_vectors;
file_flattener_options.no_version_transitions = options_.no_version_transitions;
@@ -2165,6 +2178,20 @@ int LinkCommand::Action(const std::vector<std::string>& args) {
}
}
if (no_compress_regex) {
std::string regex = no_compress_regex.value();
if (util::StartsWith(regex, "@")) {
const std::string path = regex.substr(1, regex.size() -1);
std::string error;
if (!file::AppendSetArgsFromFile(path, &options_.extensions_to_not_compress, &error)) {
context.GetDiagnostics()->Error(DiagMessage(path) << error);
return 1;
}
} else {
options_.regex_to_not_compress = GetRegularExpression(no_compress_regex.value());
}
}
// Populate some default no-compress extensions that are already compressed.
options_.extensions_to_not_compress.insert(
{".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg",

View File

@@ -17,6 +17,8 @@
#ifndef AAPT2_LINK_H
#define AAPT2_LINK_H
#include <regex>
#include "Command.h"
#include "Diagnostics.h"
#include "Resource.h"
@@ -63,6 +65,7 @@ struct LinkOptions {
bool no_xml_namespaces = false;
bool do_not_compress_anything = false;
std::unordered_set<std::string> extensions_to_not_compress;
Maybe<std::regex> regex_to_not_compress;
// Static lib options.
bool no_static_lib_packages = false;
@@ -250,6 +253,11 @@ class LinkCommand : public Command {
&options_.do_not_compress_anything);
AddOptionalSwitch("--keep-raw-values", "Preserve raw attribute values in xml files.",
&options_.keep_raw_values);
AddOptionalFlag("--no-compress-regex",
"Do not compress extensions matching the regular expression. Remember to\n"
" use the '$' symbol for end of line. Uses a non case-sensitive\n"
" ECMAScript regular expression grammar.",
&no_compress_regex);
AddOptionalSwitch("--warn-manifest-validation",
"Treat manifest validation errors as warnings.",
&options_.manifest_fixer_options.warn_validation);
@@ -283,6 +291,7 @@ class LinkCommand : public Command {
std::vector<std::string> configs_;
Maybe<std::string> preferred_density_;
Maybe<std::string> product_list_;
Maybe<std::string> no_compress_regex;
bool legacy_x_flag_ = false;
bool require_localization_ = false;
bool verbose_ = false;

View File

@@ -435,4 +435,11 @@ void SetLongVersionCode(xml::Element* manifest, uint64_t version) {
}
}
std::regex GetRegularExpression(const std::string &input) {
// Standard ECMAScript grammar plus case insensitive.
std::regex case_insensitive(
input, std::regex_constants::icase | std::regex_constants::ECMAScript);
return case_insensitive;
}
} // namespace aapt

View File

@@ -17,6 +17,8 @@
#ifndef AAPT_SPLIT_UTIL_H
#define AAPT_SPLIT_UTIL_H
#include <regex>
#include "androidfw/StringPiece.h"
#include "AppInfo.h"
@@ -72,6 +74,9 @@ std::string MakePackageSafeName(const std::string &name);
// versionCodeMajor if the version code requires more than 32 bits.
void SetLongVersionCode(xml::Element* manifest, uint64_t version_code);
// Returns a case insensitive regular expression based on the input.
std::regex GetRegularExpression(const std::string &input);
} // namespace aapt
#endif /* AAPT_SPLIT_UTIL_H */

View File

@@ -383,4 +383,12 @@ TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
}
TEST(UtilTest, RegularExperssions) {
std::string valid(".bc$");
std::regex expression = GetRegularExpression(valid);
EXPECT_TRUE(std::regex_search("file.abc", expression));
EXPECT_TRUE(std::regex_search("file.123bc", expression));
EXPECT_FALSE(std::regex_search("abc.zip", expression));
}
} // namespace aapt

View File

@@ -251,6 +251,25 @@ bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_a
return true;
}
bool AppendSetArgsFromFile(const StringPiece& path, std::unordered_set<std::string>* out_argset,
std::string* out_error) {
std::string contents;
if(!ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
if (out_error) {
*out_error = "failed to read argument-list file";
}
return false;
}
for (StringPiece line : util::Tokenize(contents, ' ')) {
line = util::TrimWhitespace(line);
if (!line.empty()) {
out_argset->insert(line.to_string());
}
}
return true;
}
bool FileFilter::SetPattern(const StringPiece& pattern) {
pattern_tokens_ = util::SplitAndLowercase(pattern, ':');
return true;

View File

@@ -19,6 +19,7 @@
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include "android-base/macros.h"
@@ -86,6 +87,10 @@ Maybe<android::FileMap> MmapPath(const std::string& path, std::string* out_error
bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist,
std::string* out_error);
// Reads the file at path and appends each line to the outargset set.
bool AppendSetArgsFromFile(const android::StringPiece& path,
std::unordered_set<std::string>* out_argset, std::string* out_error);
// Filter that determines which resource files/directories are
// processed by AAPT. Takes a pattern string supplied by the user.
// Pattern format is specified in the FileFilter::SetPattern() method.