How Chromium on Android Dynamically Loads Feature Modules
This article provides an overview of how the Chromium browser on Android minimizes its initial download size by utilizing Dynamic Feature Modules (DFMs). By leveraging Android App Bundles and the Google Play Core library, Chromium strips non-essential features—such as Augmented Reality (AR), Virtual Reality (VR), and specific enterprise tools—out of the base installation. When a user triggers one of these features, the browser dynamically downloads, links, and executes the required Java code, native C++ libraries, and UI resources on the fly without requiring an application restart.
The Architecture of Split APKs
To keep the initial download small, Chromium compiles its codebase
into an Android App Bundle (AAB) rather than a single monolithic APK.
This bundle is divided into a "base" module, which contains the core web
rendering engine and essential browser UI, and multiple "feature
splits." Each split is an independent APK that packages the compiled
Java bytecode (DEX files), native C++ libraries (.so
files), and Android resources required for a specific, less-commonly
used feature.
Requesting Modules on Demand
In the Chromium codebase, features packaged as DFMs are gated behind an internal module installer API that communicates with the Google Play Core library.
- Detection: A user navigates to a website or clicks a UI element that requires a specific capability, such as WebXR.
- Verification: Chromium checks with the Android Package Manager to see if the required split APK is already installed on the device.
- Download: If the module is missing, Chromium initiates an asynchronous network request to the Google Play Store. The Play Store downloads and installs the specific split APK in the background while the user continues browsing.
Isolated Splits and Java ClassLoading
Once the Play Store installs the module, Chromium must load the new Java code into the currently running application process. On modern Android versions, Chromium relies on an Android manifest configuration called Isolated Splits.
Instead of merging the new code into the base application's
ClassLoader—which would require restarting the app or
triggering expensive runtime verification—Android creates a separate,
dedicated ClassLoader just for the downloaded feature
module.
These classloaders are arranged in a tree hierarchy. The feature
module's ClassLoader delegates to the base module's
ClassLoader, allowing the feature to directly reference
core browser classes. Because the base module cannot directly see the
feature module's classes at compile time, Chromium uses Java reflection
to instantiate a single entry-point class in the feature module, which
then hooks into pre-defined Java interfaces in the base module.
Dynamic Linking of Native C++ Code
Because the majority of Chromium is written in C++, loading Java code is only half the process. Feature modules often contain their own compiled C++ code.
To save disk space on the user's device, Chromium stores the
feature's native .so libraries uncompressed and
page-aligned inside the split APK. When the module is triggered,
Chromium uses the Android system linker (dlopen) to map the
.so file directly from the APK zip archive into the
device's memory, completely bypassing the need to extract the file to
the device's storage.
Once the native library is mapped into memory, it resolves its
dependencies against the base module's core C++ library. Finally,
Chromium executes a dynamic JNI (Java Native Interface) registration
step, which binds the newly loaded Java methods in the isolated
ClassLoader to their corresponding C++ memory
addresses.
Merging UI Resources
Features frequently require their own UI layouts, localized strings, and graphics. During the Chromium build process, each feature module is assigned a unique resource package ID to prevent its resource identifiers from colliding with those in the base APK.
When a DFM is loaded at runtime, Chromium creates a new
Context for the feature, which automatically updates the
underlying AssetManager to include the file path to the
newly downloaded split APK. Once the AssetManager is
updated, the feature module can seamlessly inflate XML layouts and read
strings just as if they had been installed with the original browser
download.