How to Inspect APEX Packages and Mainline System Modules on Android Using ADB

Beginning with Android 10 and expanded substantially through Project Mainline, Google transitioned core operating system components—such as the Android Runtime (ART), media codecs, DNS resolvers, Conscrypt cryptography, and permission controllers—away from monolithic OS builds into modular packages known as APEX (Android Pony EXpress). Unlike standard APK applications that execute purely in user space, APEX packages contain shared native libraries, system daemons, and low-level binaries that mount directly into the Android root filesystem during early boot. Inspecting installed APEX modules via the Android Debug Bridge (ADB) allows developers and system engineers to audit module versions, active loopback mount points, and staging rollback states.

Architecture of the APEX Packaging Format

An APEX file is an archive format designed for high-security system modularity. Inside each .apex container resides an ext4 or EROFS disk image containing compiled system binaries, an AndroidManifest.xml declaring metadata, and cryptographic payload signatures.

During the early boot phase, the native apexd daemon validates cryptographic signatures against pre-installed device keys. Once verified, apexd mounts the internal disk image as a read-only loopback device under /apex/<package-name>@<version> and binds a clean symbolic link into /apex/<package-name>. This design allows critical components to be updated via Google Play System Updates without requiring a full firmware flash from the device manufacturer.

Listing Installed APEX Modules Using Package Manager

To audit which APEX modules are installed and currently active on an Android device, connect via ADB and query the Android package manager with the --apex-only filter:

adb shell pm list packages --apex-only -f

The terminal outputs the file paths and package identifiers for all active modules:

package:/system/apex/com.android.runtime.apex=com.android.runtime
package:/system/apex/com.android.art.apex=com.android.art
package:/data/apex/active/[email protected]=com.android.conscrypt
package:/system/apex/com.android.media.apex=com.android.media
package:/system/apex/com.android.tethering.apex=com.android.tethering

Notice the distinction between source directories:

  • /system/apex/: Factory pre-installed base modules bundled into the read-only system image by the device manufacturer.
  • /data/apex/active/: Dynamically updated Mainline modules delivered via Google Play System Updates that supersede factory base modules.

Querying APEX Daemon Diagnostics via cmd apexservice

The apexd daemon exposes a command-line interface via cmd apexservice to inspect detailed module properties, activation states, and rollback sessions.

To dump all active APEX packages with version codes and active flags:

adb shell cmd apexservice getActivePackages

To inspect all packages present on the device—including inactive factory modules that have been superseded by newer updates:

adb shell cmd apexservice getAllPackages

Each returned package entry includes:

  • packageName: The unique reverse-DNS identifier (e.g., com.android.adservices).
  • packagePath: The exact container location on the internal storage filesystem.
  • versionCode: An integer representing the update build version.
  • isActive: true if the package is mounted into the active runtime namespace; false if it is dormant or superseded.
  • isFactory: Indicates whether the module originated from the factory ROM build.

Inspecting Mounted APEX Loopback Filesystems

Because each active APEX module runs as an isolated loopback mount, you can inspect their internal filesystem layouts directly from the Linux shell:

adb shell mount | grep /apex

The command lists the loopback bindings:

/dev/block/loop12 on /apex/com.android.art@341512000 type erofs (ro,nodev,noatime)
/dev/block/loop14 on /apex/com.android.conscrypt@341512000 type ext4 (ro,nodev,noatime)

To explore the files delivered by a specific module (for example, inspecting the binaries and shared libraries inside the Android Runtime module):

adb shell ls -la /apex/com.android.art/bin/
adb shell ls -la /apex/com.android.art/lib64/

You can inspect executable binaries like dalvikvm and core runtime libraries (such as libart.so), confirming the precise compilation dates and build properties loaded into memory.

Auditing Staged and Pending APEX Sessions

When a Google Play System Update downloads a new APEX module, it cannot apply changes to running system services immediately because active loopback filesystems cannot be hot-swapped while in use. Instead, the package is placed into a staged session that applies during the next device reboot.

To inspect pending and historical APEX update sessions:

adb shell cmd apexservice getSessions

The output reports the session ID, state (such as STAGED, ACTIVATED, or SUCCESS), and whether the session was marked for rollback due to boot validation failures. If a module update causes a boot loop, Android’s built-in rollback mechanism reverts the pending session to the factory APEX image automatically, preserving device stability.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.