1# Life of an Android Resource 2 3[TOC] 4 5## Overview 6 7This document describes how [Android Resources][android resources] 8are built in Chromium's build system. It does not mention native resources 9which are [processed differently][native resources]. 10 11[android resources]: https://developer.android.com/guide/topics/resources/providing-resources 12[native resources]: https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide 13 14The steps consume the following files as inputs: 15* `AndroidManifest.xml` 16 * Including `AndroidManifest.xml` files from libraries, which get merged 17 together 18* res/ directories 19 20The steps produce the following intermediate files: 21* `R.srcjar` (contains `R.java` files) 22* `R.txt` 23* `.resources.zip` 24 25The steps produce the following files within an `.apk`: 26* `AndroidManifest.xml` (a binary xml file) 27* `resources.arsc` (contains all values and configuration metadata) 28* `res/**` (drawables and layouts) 29* `classes.dex` (just a small portion of classes from generated `R.java` files) 30 31 32## The Build Steps 33 34Whenever you try to compile an apk or library target, resources go through the 35following steps: 36 37### 1. Constructs .build\_config files: 38 39Inputs: 40* GN target metadata 41* Other `.build_config.json` files 42 43Outputs: 44* Target-specific `.build_config.json` file 45 46`write_build_config.py` is run to record target metadata needed by future steps. 47For more details, see [build_config.md](build_config.md). 48 49 50### 2. Prepares resources: 51 52Inputs: 53* Target-specific `.build_config.json` file 54* Files listed as `sources` 55 56Outputs: 57* Target-specific `resources.zip` (contains all resources listed in `sources`). 58* Target-specific `R.txt` (list of all resources, including dependencies). 59 60`prepare_resources.py` zips up the target-specific resource files and generates 61`R.txt`. No optimizations, crunching, etc are done on the resources. 62 63**The following steps apply only to apk & bundle targets (not to library 64targets).** 65 66### 3. Create target-specific R.java files 67 68Inputs: 69* `R.txt` from dependencies. 70 71Outputs: 72* Target-specific (placeholder) `R.java` file. 73 74A target-specific `R.java` is generated for each `android_library()` target that 75sets `resources_package`. Resource IDs are not known at this phase, so all 76values are set as placeholders. This copy of `R` classes are discarded and 77replaced with new copies at step 4. 78 79Example placeholder R.java file: 80```java 81package org.chromium.mypackage; 82 83public final class R { 84 public static class anim { 85 public static int abc_fade_in = 0; 86 public static int abc_fade_out = 0; 87 ... 88 } 89 ... 90} 91``` 92 93### 4. Finalizes apk resources: 94 95Inputs: 96* Target-specific `.build_config.json` file 97* Dependencies' `R.txt` files 98* Dependencies' `resources.zip` files 99 100Output: 101* Packaged `resources zip` (named `foo.ap_`) containing: 102 * `AndroidManifest.xml` (as binary xml) 103 * `resources.arsc` 104 * `res/**` 105* Final `R.txt` 106 * Contains a list of resources and their ids (including of dependencies). 107* Final `R.java` files 108 * See [What are `R.java` files and how are they generated]( 109 #how-r_java-files-are-generated) 110 111 112#### 4(a). Compiles resources: 113 114For each library / resources target your apk depends on, the following happens: 115* Use a regex (defined in the apk target) to remove select resources (optional). 116* Convert png images to webp for binary size (optional). 117* Move drawables in mdpi to non-mdpi directory ([why?](http://crbug.com/289843)) 118* Use `aapt2 compile` to compile xml resources to binary xml (references to 119 other resources will now use the id rather than the name for faster lookup at 120 runtime). 121* `aapt2 compile` adds headers/metadata to 9-patch images about which parts of 122 the image are stretchable vs static. 123* `aapt2 compile` outputs a zip with the compiled resources (one for each 124 dependency). 125 126 127#### 4(b). Links resources: 128 129After each dependency is compiled into an intermediate `.zip`, all those zips 130are linked by the `aapt2 link` command which does the following: 131* Use the order of dependencies supplied so that some resources clober each 132 other. 133* Compile the `AndroidManifest.xml` to binary xml (references to resources are 134 now using ids rather than the string names) 135* Create a `resources.arsc` file that has the name and values of string 136 resources as well as the name and path of non-string resources (ie. layouts 137 and drawables). 138* Combine the compiled resources into one packaged resources apk (a zip file 139 with an `.ap_` extension) that has all the resources related files. 140 141 142#### 4(c). Optimizes resources: 143 144Targets can opt into the following optimizations: 1451) Resource name collapsing: Maps all resources to the same name. Access to 146 resources via `Resources.getIdentifier()` no longer work unless resources are 147 [allowlisted](#adding-resources-to-the-allowlist). 1482) Resource filename obfuscation: Renames resource file paths from e.g.: 149 `res/drawable/something.png` to `res/a`. Rename mapping is stored alongside 150 APKs / bundles in a `.pathmap` file. Renames are based on hashes, and so are 151 stable between builds (unless a new hash collision occurs). 1523) Unused resource removal: Referenced resources are extracted from the 153 optimized `.dex` and `AndroidManifest.xml`. Resources that are directly or 154 indirectly used by these files are removed. 155 156## App Bundles and Modules: 157 158Processing resources for bundles and modules is slightly different. Each module 159has its resources compiled and linked separately (ie: it goes through the 160entire process for each module). The modules are then combined to form a 161bundle. Moreover, during "Finalizing the apk resources" step, bundle modules 162produce a `resources.proto` file instead of a `resources.arsc` file. 163 164Resources in a dynamic feature module may reference resources in the base 165module. During the link step for feature module resources, the linked resources 166of the base module are passed in. However, linking against resources currently 167works only with `resources.arsc` format. Thus, when building the base module, 168resources are compiled as both `resources.arsc` and `resources.proto`. 169 170## Debugging resource related errors when resource names are obfuscated 171 172An example message from a stacktrace could be something like this: 173``` 174java.lang.IllegalStateException: Could not find CoordinatorLayout descendant 175view with id org.chromium.chrome:id/0_resource_name_obfuscated to anchor view 176android.view.ViewStub{be192d5 G.E...... ......I. 0,0-0,0 #7f0a02ad 177app:id/0_resource_name_obfuscated} 178``` 179 180`0_resource_name_obfuscated` is the resource name for all resources that had 181their name obfuscated/stripped during the optimize resources step. To help with 182debugging, the `R.txt` file is archived. The `R.txt` file contains a mapping 183from resource ids to resource names and can be used to get the original resource 184name from the id. In the above message the id is `0x7f0a02ad`. 185 186For local builds, `R.txt` files are output in the `out/*/apks` directory. 187 188For official builds, Googlers can get archived `R.txt` files next to archived 189apks. 190 191### Adding resources to the allowlist 192 193If a resource is accessed via `getIdentifier()` it needs to be allowed by an 194aapt2 resources config file. The config file looks like this: 195 196``` 197<resource type>/<resource name>#no_obfuscate 198``` 199eg: 200``` 201string/app_name#no_obfuscate 202id/toolbar#no_obfuscate 203``` 204 205The aapt2 config file is passed to the ninja target through the 206`resources_config_paths` variable. To add a resource to the allowlist, check 207where the config is for your target and add a new line for your resource. If 208none exist, create a new config file and pass its path in your target. 209 210### Webview resource ids 211 212The first two bytes of a resource id is the package id. For regular apks, this 213is `0x7f`. However, Webview is a shared library which gets loaded into other 214apks. The package id for webview resources is assigned dynamically at runtime. 215When webview is loaded it calls this [R file's][Base Module R.java File] 216`onResourcesLoaded()` function to have the correct package id. When 217deobfuscating webview resource ids, disregard the first two bytes in the id when 218looking it up in the `R.txt` file. 219 220Monochrome, when loaded as webview, rewrites the package ids of resources used 221by the webview portion to the correct value at runtime, otherwise, its resources 222have package id `0x7f` when run as a regular apk. 223 224[Base Module R.java File]: https://cs.chromium.org/chromium/src/out/android-Debug/gen/android_webview/system_webview_apk/generated_java/gen/base_module/R.java 225 226## How R.java files are generated 227 228`R.java` contain a set of nested static classes, each with static fields 229containing ids. These ids are used in java code to reference resources in 230the apk. 231 232There are three types of `R.java` files in Chrome. 2331. Root / Base Module `R.java` Files 2342. DFM `R.java` Files 2353. Per-Library `R.java` Files 236 237### Root / Base Module `R.java` Files 238Contain base android resources. All `R.java` files can access base module 239resources through inheritance. 240 241Example Root / Base Module `R.java` File: 242```java 243package gen.base_module; 244 245public final class R { 246 public static class anim { 247 public static final int abc_fade_in = 0x7f010000; 248 public static final int abc_fade_out = 0x7f010001; 249 public static final int abc_slide_in_top = 0x7f010007; 250 } 251 public static class animator { 252 public static final int design_appbar_state_list_animator = 0x7f020000; 253 } 254} 255``` 256 257### DFM `R.java` Files 258Extend base module root `R.java` files. This allows DFMs to access their own 259resources as well as the base module's resources. 260 261Example DFM Root `R.java` File 262```java 263package gen.vr_module; 264 265public final class R { 266 public static class anim extends gen.base_module.R.anim { 267 } 268 public static class animator extends gen.base_module.R.animator { 269 public static final int design_appbar_state_list_animator = 0x7f030000; 270 } 271} 272``` 273 274### Per-Library `R.java` Files 275Generated for each `android_library()` target that sets `resources_package`. 276First a placeholder copy is generated in the `android_library()` step, and then 277a final copy is created during finalization. 278 279Example final per-library `R.java`: 280```java 281package org.chromium.chrome.vr; 282 283public final class R { 284 public static final class anim extends 285 gen.vr_module.R.anim {} 286 public static final class animator extends 287 gen.vr_module.R.animator {} 288} 289``` 290