Fundamentals 14 min read

Analyzing Android 6.0 Storage Architecture and Communication Design

This article examines Android 6.0’s storage architecture, detailing the roles and interactions of MountService, Vold, and the kernel, illustrating module and process structures, communication flows via sockets, and highlighting performance considerations such as thread blocking and ANR issues.

IT Architects Alliance
IT Architects Alliance
IT Architects Alliance
Analyzing Android 6.0 Storage Architecture and Communication Design

Introduction: The author encountered storage‑related bugs causing ANR on Android devices, traced to the main thread being blocked in the vold process. To understand and fix the issue, the article dives into the design of Android’s storage system based on Android 6.0 source code.

Overview : The storage system centers on two core modules, MountService (a Binder service running in system_server ) and Vold (the Volume Daemon, a native process). The article focuses on these modules and their interaction, showing only essential code snippets.

Module Architecture : The communication chain is Linux Kernel → uevent → NetlinkManager → VolumeManager → CommandListener → MountService. Each step forwards events or commands to the next component.

Process Architecture :

Java layer: 1 main thread ( system_server ) plus three MountService‑related threads (VoldConnector, MountService, CryptdConnector).

Native layer: 1 main thread ( /system/bin/vold ), three child threads (named vold ), and one child process ( /system/bin/sdcard ).

The article also notes two additional system threads used by handlers: android.fg and android.io .

Communication Architecture :

MountService communicates with Vold via a socket rather than the usual Android Binder IPC. The instantiation of MountService creates several threads and handlers:

Create ICallbacks on the android.fg thread.

Start a handler thread named "MountService".

Create OBB handler on the android.io thread.

Instantiate NativeDaemonConnector .

Start threads "VoldConnector" and "CryptdConnector".

Register broadcast listeners for user add/remove events.

Thus three dedicated threads (MountService, VoldConnector, CryptdConnector) plus the two system threads are used for storage operations.

MountService Sending Messages :

When a mount request is issued, MountService calls:

public void mount(String volId) {
    // ...
    mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
}

The execute call eventually reaches NDC.execute , which increments a sequence number, writes the command (e.g., 3 volume reset ) to the socket, and blocks waiting for a response with a poll loop. It exits the loop either after a timeout (1 minute) or when a response code outside the [100,200) range is received. Commands taking longer than 500 ms generate a log prefixed with "NDC Command" for performance analysis.

Vold’s native side creates a listener thread via pthread_create . When data arrives on the socket, FL.onDataAvailable is invoked, which forwards the command to FL.dispatchCommand . The dispatcher maps the command to a handler class; unknown commands or overly long arguments result in a 500‑code error response.

For a volume mount command, CommandListener.VolumeCmd.runCommand processes the mount branch.

MountService Receiving Messages :

After Vold processes a command, it sends a response via sendGenericOkFail . Response codes are categorized as follows:

Code Range

Event Category

Method

[100,200)

Partial response, more events follow

isClassContinue

[200,300)

Success

isClassOk

[400,500)

Remote server error

isClassServerError

[500,600)

Local client error

isClassClientError

[600,700)

Unsolicited event from Vold

isClassUnsolicited

If the response code is not in [600,700) , the event is added to mResponseQueue , unblocking the original NDC.execute call. Unsolicited events are dispatched to the android.fg handler, which invokes NativeDaemonConnector.handleMessage .

Summary :

The article provides a module‑level and process‑level view of Android’s storage system, explains the socket‑based communication between MountService and Vold, and points out that heavy I/O operations (e.g., fsck, fstrim) can block the main thread, leading to ANR. Future work will cover Vold‑kernel communication.

androidsystem designstorage architectureVoldMountServiceprocess communication
IT Architects Alliance
Written by

IT Architects Alliance

Discussion and exchange on system, internet, large‑scale distributed, high‑availability, and high‑performance architectures, as well as big data, machine learning, AI, and architecture adjustments with internet technologies. Includes real‑world large‑scale architecture case studies. Open to architects who have ideas and enjoy sharing.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.