How Android AAPT Compiles XML to Binary XML
The Android Asset Packaging Tool (AAPT and its successor, AAPT2) converts human-readable XML layouts into optimized binary XML (AXML) to maximize runtime performance and reduce APK size. This compilation process parses standard XML documents, replaces textual attribute names and elements with constant 32-bit integer resource identifiers, extracts all unique strings into an indexed string pool, and writes the data into a chunk-based binary stream. The resulting binary representation eliminates the need for expensive text parsing, schema validation, and dynamic string allocation when Android instantiates layouts at runtime.
1. Lexical Parsing and Validation
AAPT begins by parsing human-readable XML documents using a standard
XML parser. During this phase, it validates the structure against
Android layout rules and verifies that all custom elements, namespaces
(such as http://schemas.android.com/apk/res/android), and
attributes are syntactically correct. It checks whether referenced
drawables, strings, dimensions, and custom view classes exist within the
project or linked libraries.
2. String Pool Extraction and Deduplication
In standard XML, repeated tags and namespace declarations consume
significant space. AAPT strips away structural redundancies by
aggregating all unique strings—including element names, attribute
values, and namespace URIs—into a unified String Pool.
* Every unique string is assigned a zero-based index. * References to
strings throughout the document are replaced with these compact integer
indices. * Deduplication ensures that frequently repeated tokens (such
as match_parent or android) are stored only
once in the final binary file.
3. Resource ID Resolution
Human-readable attribute names are mapped to specific 32-bit integer
identifiers defined in the Android SDK or the project’s compiled
R.java/R.txt symbol tables. * A human-readable
attribute like android:orientation is mapped to its
framework resource ID (e.g., 0x010100c4). * AAPT constructs
a Resource Map Chunk that links the attribute indices
in the string pool directly to their corresponding 32-bit integer
resource IDs. * This mapping allows Android’s AssetManager
and TypedArray implementations to resolve attributes via
direct array indexing rather than hash table lookups or string
comparisons.
4. Value Inlining and Typing
Instead of storing all attribute values as raw strings, AAPT
evaluates and converts literal values into strongly typed binary
representations: * Dimensions (e.g., 16dp), booleans
(true/false), colors (#FFFFFF),
and integers are encoded directly into compact TypedValue
binary structs. * References to other resources (e.g.,
@string/app_name or @color/primary) are
resolved into their corresponding hexadecimal resource IDs (e.g.,
0x7f040001).
5. Chunk-Based Binary Layout Generation
The final output is organized into a stream of standardized,
memory-alignable binary chunks: * Header Chunk:
Identifies the file type (RES_XML_TYPE) and the total file
size. * String Pool Chunk: Contains the string offset
table, string data (encoded in UTF-8 or UTF-16), and style spans. *
Resource Map Chunk: Contains the array of 32-bit
integer resource IDs corresponding to the attribute names in the string
pool. * Node Chunks: Hierarchical tokens that represent
the document structure: * RES_XML_START_NAMESPACE_TYPE and
RES_XML_END_NAMESPACE_TYPE define scope boundaries. *
RES_XML_START_ELEMENT_TYPE contains the element name index,
attribute count, and an array of serialized attribute structs (holding
namespace index, name index, typed value, and resolved resource ID). *
RES_XML_END_ELEMENT_TYPE marks the closure of view
hierarchies.
Runtime Impact
When an application calls setContentView() or
LayoutInflater.inflate(), the Android OS memory-maps the
compiled binary XML directly from the APK. The native
ResXMLTree parser iterates over fixed-size binary chunks
and reads attributes via offset arithmetic, bypassing string
tokenization and character decoding entirely to achieve
near-instantaneous layout inflation.