Merge "Expose '--force-sparse-encoding' flag for 'optimize' and 'convert' commands."

This commit is contained in:
Iurii Makhno
2022-09-23 11:40:45 +00:00
committed by Android (Google) Code Review
9 changed files with 97 additions and 24 deletions

View File

@@ -395,6 +395,12 @@ int ConvertCommand::Action(const std::vector<std::string>& args) {
<< output_format_.value());
return 1;
}
if (enable_sparse_encoding_) {
table_flattener_options_.sparse_entries = SparseEntriesMode::Enabled;
}
if (force_sparse_encoding_) {
table_flattener_options_.sparse_entries = SparseEntriesMode::Forced;
}
return Convert(&context, apk.get(), writer.get(), format, table_flattener_options_,
xml_flattener_options_);

View File

@@ -34,10 +34,18 @@ class ConvertCommand : public Command {
AddOptionalFlag("--output-format", android::base::StringPrintf("Format of the output. "
"Accepted values are '%s' and '%s'. When not set, defaults to '%s'.",
kOutputFormatProto, kOutputFormatBinary, kOutputFormatBinary), &output_format_);
AddOptionalSwitch("--enable-sparse-encoding",
AddOptionalSwitch(
"--enable-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.",
&table_flattener_options_.use_sparse_entries);
"This decreases APK size at the cost of resource retrieval performance.\n"
"Only applies sparse encoding to Android O+ resources or all resources if minSdk of "
"the APK is O+",
&enable_sparse_encoding_);
AddOptionalSwitch("--force-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.\n"
"Applies sparse encoding to all resources regardless of minSdk.",
&force_sparse_encoding_);
AddOptionalSwitch("--keep-raw-values",
android::base::StringPrintf("Preserve raw attribute values in xml files when using the"
" '%s' output format", kOutputFormatBinary),
@@ -56,6 +64,8 @@ class ConvertCommand : public Command {
std::string output_path_;
std::optional<std::string> output_format_;
bool verbose_ = false;
bool enable_sparse_encoding_ = false;
bool force_sparse_encoding_ = false;
};
int Convert(IAaptContext* context, LoadedApk* input, IArchiveWriter* output_writer,

View File

@@ -2419,6 +2419,9 @@ int LinkCommand::Action(const std::vector<std::string>& args) {
<< "the --merge-only flag can be only used when building a static library");
return 1;
}
if (options_.use_sparse_encoding) {
options_.table_flattener_options.sparse_entries = SparseEntriesMode::Enabled;
}
// The default build type.
context.SetPackageType(PackageType::kApp);

View File

@@ -69,6 +69,7 @@ struct LinkOptions {
bool no_resource_removal = false;
bool no_xml_namespaces = false;
bool do_not_compress_anything = false;
bool use_sparse_encoding = false;
std::unordered_set<std::string> extensions_to_not_compress;
std::optional<std::regex> regex_to_not_compress;
@@ -156,8 +157,8 @@ class LinkCommand : public Command {
"defaults. Use this only when building runtime resource overlay packages.",
&options_.no_resource_removal);
AddOptionalSwitch("--enable-sparse-encoding",
"This decreases APK size at the cost of resource retrieval performance.",
&options_.table_flattener_options.use_sparse_entries);
"This decreases APK size at the cost of resource retrieval performance.",
&options_.use_sparse_encoding);
AddOptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
&legacy_x_flag_);
AddOptionalSwitch("-z", "Require localization of strings marked 'suggested'.",

View File

@@ -427,6 +427,13 @@ int OptimizeCommand::Action(const std::vector<std::string>& args) {
return 1;
}
if (options_.enable_sparse_encoding) {
options_.table_flattener_options.sparse_entries = SparseEntriesMode::Enabled;
}
if (options_.force_sparse_encoding) {
options_.table_flattener_options.sparse_entries = SparseEntriesMode::Forced;
}
if (target_densities_) {
// Parse the target screen densities.
for (const StringPiece& config_str : util::Tokenize(target_densities_.value(), ',')) {

View File

@@ -61,6 +61,12 @@ struct OptimizeOptions {
// Path to the output map of original resource paths to shortened paths.
std::optional<std::string> shortened_paths_map_path;
// Whether sparse encoding should be used for O+ resources.
bool enable_sparse_encoding = false;
// Whether sparse encoding should be used for all resources.
bool force_sparse_encoding = false;
};
class OptimizeCommand : public Command {
@@ -96,10 +102,18 @@ class OptimizeCommand : public Command {
"Comma separated list of artifacts to keep. If none are specified,\n"
"all artifacts will be kept.",
&kept_artifacts_);
AddOptionalSwitch("--enable-sparse-encoding",
AddOptionalSwitch(
"--enable-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.",
&options_.table_flattener_options.use_sparse_entries);
"This decreases APK size at the cost of resource retrieval performance.\n"
"Only applies sparse encoding to Android O+ resources or all resources if minSdk of "
"the APK is O+",
&options_.enable_sparse_encoding);
AddOptionalSwitch("--force-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.\n"
"Applies sparse encoding to all resources regardless of minSdk.",
&options_.force_sparse_encoding);
AddOptionalSwitch("--collapse-resource-names",
"Collapses resource names to a single value in the key string pool. Resources can \n"
"be exempted using the \"no_collapse\" directive in a file specified by "

View File

@@ -231,14 +231,14 @@ struct OverlayableChunk {
class PackageFlattener {
public:
PackageFlattener(IAaptContext* context, const ResourceTablePackageView& package,
const std::map<size_t, std::string>* shared_libs, bool use_sparse_entries,
bool collapse_key_stringpool,
const std::map<size_t, std::string>* shared_libs,
SparseEntriesMode sparse_entries, bool collapse_key_stringpool,
const std::set<ResourceName>& name_collapse_exemptions)
: context_(context),
diag_(context->GetDiagnostics()),
package_(package),
shared_libs_(shared_libs),
use_sparse_entries_(use_sparse_entries),
sparse_entries_(sparse_entries),
collapse_key_stringpool_(collapse_key_stringpool),
name_collapse_exemptions_(name_collapse_exemptions) {
}
@@ -367,10 +367,12 @@ class PackageFlattener {
}
}
bool sparse_encode = use_sparse_entries_;
bool sparse_encode = sparse_entries_ == SparseEntriesMode::Enabled ||
sparse_entries_ == SparseEntriesMode::Forced;
if (context_->GetMinSdkVersion() == 0 && config.sdkVersion == 0) {
// Sparse encode if sdk version is not set in context and config.
if (sparse_entries_ == SparseEntriesMode::Forced ||
(context_->GetMinSdkVersion() == 0 && config.sdkVersion == 0)) {
// Sparse encode if forced or sdk version is not set in context and config.
} else {
// Otherwise, only sparse encode if the entries will be read on platforms S_V2+.
sparse_encode = sparse_encode &&
@@ -712,7 +714,7 @@ class PackageFlattener {
android::IDiagnostics* diag_;
const ResourceTablePackageView package_;
const std::map<size_t, std::string>* shared_libs_;
bool use_sparse_entries_;
SparseEntriesMode sparse_entries_;
android::StringPool type_pool_;
android::StringPool key_pool_;
bool collapse_key_stringpool_;
@@ -768,7 +770,7 @@ bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
}
PackageFlattener flattener(context, package, &table->included_packages_,
options_.use_sparse_entries, options_.collapse_key_stringpool,
options_.sparse_entries, options_.collapse_key_stringpool,
options_.name_collapse_exemptions);
if (!flattener.FlattenPackage(&package_buffer)) {
return false;

View File

@@ -29,12 +29,20 @@ namespace aapt {
// preferred.
constexpr const size_t kSparseEncodingThreshold = 60;
enum class SparseEntriesMode {
// Disables sparse encoding for entries.
Disabled,
// Enables sparse encoding for all entries for APKs with O+ minSdk. For APKs with minSdk less
// than O only applies sparse encoding for resource configuration available on O+.
Enabled,
// Enables sparse encoding for all entries regardless of minSdk.
Forced,
};
struct TableFlattenerOptions {
// When true, types for configurations with a sparse set of entries are encoded
// When enabled, types for configurations with a sparse set of entries are encoded
// as a sparse map of entry ID and offset to actual data.
// This is only available on platforms O+ and will only be respected when
// minSdk is O+.
bool use_sparse_entries = false;
SparseEntriesMode sparse_entries = SparseEntriesMode::Disabled;
// When true, the key string pool in the final ResTable
// is collapsed to a single entry. All resource entries

View File

@@ -337,7 +337,7 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithMinSdkO) {
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
TableFlattenerOptions options;
options.use_sparse_entries = true;
options.sparse_entries = SparseEntriesMode::Enabled;
std::string no_sparse_contents;
ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
@@ -380,7 +380,29 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithConfigSdkVersionO) {
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
TableFlattenerOptions options;
options.use_sparse_entries = true;
options.sparse_entries = SparseEntriesMode::Enabled;
std::string no_sparse_contents;
ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
std::string sparse_contents;
ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
EXPECT_GT(no_sparse_contents.size(), sparse_contents.size());
}
TEST_F(TableFlattenerTest, FlattenSparseEntryRegardlessOfMinSdkWhenForced) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder()
.SetCompilationPackage("android")
.SetPackageId(0x01)
.SetMinSdkVersion(SDK_LOLLIPOP)
.Build();
const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB");
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
TableFlattenerOptions options;
options.sparse_entries = SparseEntriesMode::Forced;
std::string no_sparse_contents;
ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
@@ -399,7 +421,7 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithSdkVersionNotSet) {
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
TableFlattenerOptions options;
options.use_sparse_entries = true;
options.sparse_entries = SparseEntriesMode::Enabled;
std::string no_sparse_contents;
ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
@@ -442,7 +464,7 @@ TEST_F(TableFlattenerTest, DoNotUseSparseEntryForDenseConfig) {
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.80f);
TableFlattenerOptions options;
options.use_sparse_entries = true;
options.sparse_entries = SparseEntriesMode::Enabled;
std::string no_sparse_contents;
ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));