Commit 86259392 authored by Mohamed Heikal's avatar Mohamed Heikal Committed by Commit Bot

[Android] Remove most resource names in resources.arsc

resource names are stored in the resources.arsc file to allow for
getIdentifier with the string name of the resource to work. This cl
obfuscates all of those resources to one name (and thus stored only
once) for all resources that are not accessed via getIdentifier.

This improves binary size by about 200KB.

Bug: 894208

Change-Id: I28c440c22b90cd045f53017073fdb88c7410d530
Reviewed-on: https://chromium-review.googlesource.com/c/1265897
Commit-Queue: Mohamed Heikal <mheikal@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603229}
parent 2779a9b0
string/license_activity_title#no_obfuscate
......@@ -29,6 +29,9 @@ public class LicenseActivity extends Activity {
String.format("content://%s.%s", packageName, LICENSES_URI_SUFFIX);
intent.setDataAndType(Uri.parse(licenseUri), LICENSES_CONTENT_TYPE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
// Resources are accessed via getIdentifier because resource ids in the standalone system
// webview apk have incorrect package_ids. Accessing resources via getIdentifier needs to be
// whitelisted in //android_webview/aapt2.config. see https://crbug.com/894208
final int titleId =
getResources().getIdentifier("license_activity_title", "string", packageName);
if (titleId != 0) {
......
......@@ -327,8 +327,9 @@ def main(args):
resource_infos = resource_apk.infolist()
# 1. AndroidManifest.xml
assert resource_infos[0].filename == 'AndroidManifest.xml'
copy_resource(resource_infos[0], out_dir=apk_manifest_dir)
copy_resource(
resource_apk.getinfo('AndroidManifest.xml'),
out_dir=apk_manifest_dir)
# 2. Assets
if options.write_asset_list:
......@@ -376,7 +377,8 @@ def main(args):
build_utils.AddToZipHermetic(out_apk, apk_path, data='')
# 5. Resources
for info in resource_infos[1:]:
for info in resource_infos:
if info.filename != 'AndroidManifest.xml':
copy_resource(info)
# 6. Java resources that should be accessible via
......
......@@ -141,6 +141,17 @@ def _ParseArgs(args):
action='store_true',
help='Whether to strip xml namespaces from processed '
'xml resources')
input_opts.add_argument(
'--resources-config-path', help='Path to aapt2 resources config file.')
input_opts.add_argument(
'--optimize-resources',
default=False,
action='store_true',
help='Whether to run the `aapt2 optimize` step on the resources.')
input_opts.add_argument(
'--unoptimized-resources-path',
help='Path to output the intermediate apk before running '
'`aapt2 optimize`.')
input_opts.add_argument(
'--check-resources-pkg-id', type=_PackageIdArgument,
......@@ -306,7 +317,6 @@ def _CreateLinkApkArgs(options):
'--version-name', options.version_name,
'--auto-add-overlay',
'--no-version-vectors',
'-o', options.apk_path,
]
for j in options.include_resources:
......@@ -481,7 +491,11 @@ def _CompileDeps(aapt2_path, dep_subdirs, temp_dir):
partial_path = os.path.join(partials_dir, dirname + '.zip')
compile_command = (partial_compile_command +
['--dir', directory, '-o', partial_path])
build_utils.CheckOutput(compile_command)
build_utils.CheckOutput(
compile_command,
stderr_filter=lambda output:
build_utils.FilterLines(
output, r'ignoring configuration .* for styleable'))
# Sorting the files in the partial ensures deterministic output from the
# aapt2 link step which uses order of files in the partial.
......@@ -541,7 +555,15 @@ def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
for directory in dep_subdirs:
renamed_paths.update(_MoveImagesToNonMdpiFolders(directory))
if options.optimize_resources:
if options.unoptimized_resources_path:
unoptimized_apk_path = options.unoptimized_resources_path
else:
unoptimized_apk_path = os.path.join(gen_dir, 'intermediate.ap_')
else:
unoptimized_apk_path = options.apk_path
link_command = _CreateLinkApkArgs(options)
link_command += ['-o', unoptimized_apk_path]
link_command += ['--output-text-symbols', r_txt_path]
# TODO(digit): Is this below actually required for R.txt generation?
link_command += ['--java', gen_dir]
......@@ -557,6 +579,26 @@ def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
# Also creates R.txt
build_utils.CheckOutput(
link_command, print_stdout=False, print_stderr=False)
if options.optimize_resources:
# Optimize the resources.arsc file by obfuscating resource names and only
# allow usage via R.java constant.
optimize_command = [
options.aapt2_path,
'optimize',
'--enable-resource-obfuscation',
'-o',
options.apk_path,
unoptimized_apk_path,
]
if options.resources_config_path:
optimize_command += [
'--resources-config-path',
options.resources_config_path,
]
build_utils.CheckOutput(
optimize_command, print_stdout=False, print_stderr=False)
_CreateResourceInfoFile(
renamed_paths, options.apk_info_path, options.dependencies_res_zips)
......@@ -645,6 +687,7 @@ def main(args):
options.srcjar_out,
options.proguard_file,
options.proguard_file_main_dex,
options.unoptimized_resources_path,
]
output_paths = [x for x in possible_output_paths if x]
......@@ -658,6 +701,7 @@ def main(args):
str(options.png_to_webp),
str(options.support_zh_hk),
str(options.no_xml_namespaces),
str(options.optimize_resources),
]
input_strings.extend(_CreateLinkApkArgs(options))
......@@ -674,6 +718,7 @@ def main(args):
options.android_manifest,
debug_temp_resources_dir,
options.shared_resources_whitelist,
options.resources_config_path,
]
possible_input_paths += options.include_resources
input_paths = [x for x in possible_input_paths if x]
......
......@@ -50,6 +50,10 @@ def _ParseArgs(args):
help='Output bundle zip archive.')
parser.add_argument('--module-zips', required=True,
help='GN-list of module zip archives.')
parser.add_argument(
'--rtxt-in-paths', action='append', help='GN-list of module R.txt files.')
parser.add_argument(
'--rtxt-out-path', help='Path to combined R.txt file for bundle.')
parser.add_argument('--uncompressed-assets', action='append',
help='GN-list of uncompressed assets.')
parser.add_argument('--uncompress-shared-libraries', action='append',
......@@ -63,6 +67,7 @@ def _ParseArgs(args):
options = parser.parse_args(args)
options.module_zips = build_utils.ParseGnList(options.module_zips)
options.rtxt_in_paths = build_utils.ExpandFileArgs(options.rtxt_in_paths)
if len(options.module_zips) == 0:
raise Exception('The module zip list cannot be empty.')
......@@ -285,6 +290,14 @@ def main(args):
shutil.move(tmp_bundle, options.out_bundle)
if options.rtxt_out_path:
with open(options.rtxt_out_path, 'w') as rtxt_out:
for rtxt_in_path in options.rtxt_in_paths:
with open(rtxt_in_path, 'r') as rtxt_in:
rtxt_out.write('-- Contents of {}\n'.format(
os.path.basename(rtxt_in_path)))
rtxt_out.write(rtxt_in.read())
if __name__ == '__main__':
main(sys.argv[1:])
......@@ -348,6 +348,10 @@ dependencies for this APK.
The path of an zip archive containing the APK's resources compiled to the
protocol buffer format (instead of regular binary xml + resources.arsc).
* `deps_info['module_rtxt_path']`:
The path of the R.txt file generated when compiling the resources for the bundle
module.
* `native['libraries']`
List of native libraries for the primary ABI to be embedded in this APK.
E.g. [ "libchrome.so" ] (i.e. this doesn't include any ABI sub-directory
......@@ -871,6 +875,9 @@ def main(argv):
parser.add_option('--apk-proto-resources',
help='Path to resources compiled in protocol buffer format '
' for this apk.')
parser.add_option(
'--module-rtxt-path',
help='Path to R.txt file for resources in a bundle module.')
parser.add_option('--generate-markdown-format-doc', action='store_true',
help='Dump the Markdown .build_config format documentation '
......@@ -919,6 +926,10 @@ def main(argv):
if options.type != 'android_app_bundle_module':
raise Exception('--apk-proto-resources can only be used with '
'--type=android_app_bundle_module')
if options.module_rtxt_path:
if options.type != 'android_app_bundle_module':
raise Exception('--module-rxt-path can only be used with '
'--type=android_app_bundle_module')
is_apk_or_module_target = options.type in ('android_apk',
'android_app_bundle_module')
......@@ -1028,6 +1039,9 @@ def main(argv):
if options.apk_proto_resources:
deps_info['proto_resources_path'] = options.apk_proto_resources
if options.module_rtxt_path:
deps_info['module_rtxt_path'] = options.module_rtxt_path
if is_java_target:
deps_info['requires_android'] = bool(options.requires_android)
deps_info['supports_android'] = bool(options.supports_android)
......
......@@ -320,6 +320,11 @@ template("write_build_config") {
args += [ "--apk-proto-resources=$_rebased_proto_resources" ]
}
if (defined(invoker.module_rtxt_path)) {
_rebased_rtxt_path = rebase_path(invoker.module_rtxt_path, root_build_dir)
args += [ "--module-rtxt-path=$_rebased_rtxt_path" ]
}
if (defined(invoker.shared_libraries_runtime_deps_file)) {
# Don't list shared_libraries_runtime_deps_file as an input in order to
# avoid having to depend on the runtime_deps target. See comment in
......@@ -1976,14 +1981,15 @@ if (enable_java_templates) {
outputs = []
_android_aapt_path = android_default_aapt_path
if (_proto_format) {
_android_aapt2_path = android_sdk_tools_bundle_aapt2
if (_proto_format) {
depfile = "$target_gen_dir/${invoker.target_name}_3.d"
}
inputs = [
invoker.build_config,
_android_aapt_path,
_android_aapt2_path,
]
_rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
......@@ -1994,19 +2000,13 @@ if (enable_java_templates) {
"--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)",
"--aapt-path",
rebase_path(_android_aapt_path, root_build_dir),
"--aapt2-path",
rebase_path(_android_aapt2_path, root_build_dir),
"--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
"--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
"--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
]
if (_proto_format) {
inputs += [ _android_aapt2_path ]
args += [
"--aapt2-path",
rebase_path(_android_aapt2_path, root_build_dir),
]
}
inputs += [ invoker.android_manifest ]
args += [
"--android-manifest",
......@@ -2043,6 +2043,25 @@ if (enable_java_templates) {
]
}
if (defined(invoker.optimize_resources) && invoker.optimize_resources) {
args += [ "--optimize-resources" ]
if (defined(invoker.resources_config_path)) {
inputs += [ invoker.resources_config_path ]
args += [
"--resources-config-path",
rebase_path(invoker.resources_config_path, root_build_dir),
]
}
if (defined(invoker.unoptimized_resources_path)) {
args += [
"--unoptimized-resources-path",
rebase_path(invoker.unoptimized_resources_path, root_build_dir),
]
outputs += [ invoker.unoptimized_resources_path ]
}
}
# Useful to have android:debuggable in the manifest even for Release
# builds. Just omit it for officai
if (debuggable_apks) {
......@@ -2492,6 +2511,13 @@ if (enable_java_templates) {
get_label_info(_incremental_compile_resources_target_name,
"target_gen_dir") + "/AndroidManifest.xml"
if (defined(invoker.unoptimized_resources_path)) {
_incremental_packaged_resources_path =
invoker.unoptimized_resources_path
} else {
_incremental_packaged_resources_path = invoker.packaged_resources_path
}
_rebased_build_config =
rebase_path(invoker.assets_build_config, root_build_dir)
......@@ -2502,7 +2528,7 @@ if (enable_java_templates) {
inputs = [
_android_manifest,
invoker.assets_build_config,
invoker.packaged_resources_path,
_incremental_packaged_resources_path,
]
outputs = [
# Output the non-compiled manifest for easy debugging (as opposed to
......@@ -2517,7 +2543,7 @@ if (enable_java_templates) {
"--out-manifest",
rebase_path(_incremental_android_manifest, root_build_dir),
"--in-apk",
rebase_path(invoker.packaged_resources_path, root_build_dir),
rebase_path(_incremental_packaged_resources_path, root_build_dir),
"--out-apk",
rebase_path(_incremental_compiled_resources_path, root_build_dir),
"--aapt-path",
......@@ -3129,7 +3155,11 @@ if (enable_java_templates) {
])
}
if (type == "android_app_bundle_module") {
forward_variables_from(invoker, [ "proto_resources_path" ])
forward_variables_from(invoker,
[
"proto_resources_path",
"module_rtxt_path",
])
}
build_config = _build_config
is_prebuilt = _is_prebuilt
......
......@@ -1884,6 +1884,10 @@ if (enable_java_templates) {
# uncompress_shared_libraries: True if shared libraries should be stored
# uncompressed in the APK. Must be unset or true if load_library_from_apk
# is set to true.
# optimize_resources: True if resource names should be stripped from the
# resources.arsc file in the apk or module.
# resources_config_path: Path to the aapt2 optimize config file that tags
# resources with acceptable/non-acceptable optimizations.
template("android_apk_or_module") {
forward_variables_from(invoker, [ "testonly" ])
......@@ -1913,10 +1917,11 @@ if (enable_java_templates) {
if (defined(invoker.final_apk_path)) {
_final_apk_path = invoker.final_apk_path
} else if (!_is_bundle_module) {
_final_apk_path = "$root_build_dir/apks/${invoker.name}.apk"
} else {
_final_apk_path = "$root_build_dir/bundle_modules/${invoker.name}"
_final_apk_path = "$root_build_dir/apks/${invoker.name}.apk"
}
if (!_is_bundle_module) {
_final_rtxt_path = "${_final_apk_path}.R.txt"
}
_final_apk_path_no_ext_list =
process_file_template([ _final_apk_path ],
......@@ -2123,7 +2128,16 @@ if (enable_java_templates) {
_android_sdk_dep = "//third_party/android_tools:android_sdk_java"
}
_optimize_resources =
defined(invoker.optimize_resources) && invoker.optimize_resources
if (_optimize_resources) {
_unoptimized_resources_path =
"$target_out_dir/$_template_name.unoptimized.ap_"
}
_compile_resources_target = "${_template_name}__compile_resources"
_compile_resources_rtxt_out =
"${target_gen_dir}/${_compile_resources_target}_R.txt"
compile_resources(_compile_resources_target) {
forward_variables_from(invoker,
[
......@@ -2133,6 +2147,7 @@ if (enable_java_templates) {
"aapt_locale_whitelist",
"resource_blacklist_regex",
"resource_blacklist_exceptions",
"resources_config_path",
"png_to_webp",
"no_xml_namespaces",
])
......@@ -2144,12 +2159,16 @@ if (enable_java_templates) {
post_process_script = invoker.post_process_package_resources_script
}
srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
r_text_out_path = "${target_gen_dir}/${target_name}_R.txt"
r_text_out_path = _compile_resources_rtxt_out
proguard_file = _generated_proguard_config
if (_enable_multidex) {
proguard_file_main_dex = _generated_proguard_main_dex_config
}
output = _packaged_resources_path
if (_optimize_resources) {
optimize_resources = true
unoptimized_resources_path = _unoptimized_resources_path
}
build_config = _build_config
deps = _deps + [
......@@ -2182,6 +2201,28 @@ if (enable_java_templates) {
}
}
if (!_is_bundle_module) {
# Output the R.txt file to a more easily discoverable location for
# archiving. This is necessary when stripping resource names so that we
# have an archive of resource names to ids for shipped apks (for
# debugging purposes). We copy the file rather than change the location
# of the original because other targets rely on the location of the R.txt
# file.
_copy_rtxt_target = "${_template_name}__copy_rtxt"
copy(_copy_rtxt_target) {
deps = [
":$_compile_resources_target",
]
sources = [
_compile_resources_rtxt_out,
]
outputs = [
_final_rtxt_path,
]
}
_final_deps += [ ":$_copy_rtxt_target" ]
}
if (_is_base_module && _is_bundle_module) {
# Bundle modules have to reference resources from the base module.
# However, to compile the bundle module's resources we have to give it an
......@@ -2365,6 +2406,7 @@ if (enable_java_templates) {
if (_is_bundle_module) {
proto_resources_path = _packaged_resources_path
module_rtxt_path = _compile_resources_rtxt_out
}
if (!_is_bundle_module) {
......@@ -2562,6 +2604,9 @@ if (enable_java_templates) {
if (_incremental_allowed) {
android_manifest = _android_manifest
base_path = _base_path
if (_optimize_resources) {
unoptimized_resources_path = _unoptimized_resources_path
}
}
# Incremental apk does not use native libs nor final dex.
......@@ -2835,6 +2880,7 @@ if (enable_java_templates) {
"never_incremental",
"no_build_hooks",
"no_xml_namespaces",
"optimize_resources",
"png_to_webp",
"post_process_package_resources_script",
"product_version_resources_dep",
......@@ -2843,6 +2889,7 @@ if (enable_java_templates) {
"proguard_jar_path",
"resource_blacklist_regex",
"resource_blacklist_exceptions",
"resources_config_path",
"secondary_abi_loadable_modules",
"secondary_abi_shared_libraries",
"secondary_native_lib_placeholders",
......@@ -2932,6 +2979,7 @@ if (enable_java_templates) {
"native_lib_version_rule",
"negative_main_dex_globs",
"no_xml_namespaces",
"optimize_resources",
"png_to_webp",
"product_version_resources_dep",
"proguard_configs",
......@@ -2939,6 +2987,7 @@ if (enable_java_templates) {
"proguard_jar_path",
"resource_blacklist_regex",
"resource_blacklist_exceptions",
"resources_config_path",
"secondary_abi_loadable_modules",
"secondary_abi_shared_libraries",
"secondary_native_lib_placeholders",
......@@ -3856,6 +3905,7 @@ if (enable_java_templates) {
_all_create_module_targets += [
":$_create_module_target",
_module_build_config_target,
"${_module_target}__compile_resources",
]
_all_module_zip_paths += [ _module_zip_path ]
_all_module_build_configs += [ _module_build_config ]
......@@ -3914,6 +3964,7 @@ if (enable_java_templates) {
deps = _all_create_module_targets + [ ":$_build_config_target" ]
args = [
"--out-bundle=$_rebased_bundle_path",
"--rtxt-out-path=$_rebased_bundle_path.R.txt",
"--module-zips=$_all_rebased_module_zip_paths",
]
if (_sign_bundle) {
......@@ -3936,6 +3987,8 @@ if (enable_java_templates) {
"$_rebased_build_config:uncompressed_assets)",
"--uncompress-shared-libraries=@FileArg(" +
"$_rebased_build_config:native:uncompress_shared_libraries)",
"--rtxt-in-paths=@FileArg(" +
"$_rebased_build_config:deps_info:module_rtxt_path)",
]
}
}
......
......@@ -107,6 +107,8 @@ template("chrome_public_common_apk_or_module_tmpl") {
# Use zh-TW strings for zh-HK (https://crbug.com/780847).
support_zh_hk = true
optimize_resources = true
if (defined(shared_libraries) && shared_libraries != []) {
_native_lib_file =
rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir)
......@@ -227,6 +229,9 @@ template("monochrome_public_common_apk_or_module_tmpl") {
# Webview supports all locales (has no omitted ones).
aapt_locale_whitelist = locales
# Resources config for blocklisting resource names from obfuscation
resources_config_path = "//android_webview/aapt2.config"
if (!defined(invoker.target_type) || invoker.target_type == "android_apk") {
# Incremental install doesn't work for monochrome. See crbug.com/663492.
never_incremental = true
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment