Android External Storage Support: Volume Daemon (vold) Architecture
Introduction.
When
we insert an sdcard/usb drive in an Android device, The system automatically mounts them for use. The vold [short for Volume Daemon] is the service responsible for
detecting and mounting/unmounting of all the external or extended storage media
in Android like usb, sdcard, cdrom.
Its
main function involves in helping Android support hot pluggable storage devices.
In
this tutorial we will understand vold and associated components along with their code walkthrough.
The
vold process receives external storage device connection or disconnection messages
from the kernel to manage and control the external storage devices on the
Android platform.
They
include sdcard plugging, mounting, uninstalling, and formatting.
When
the external device changes, the kernel sends messages in uEvent format through
Netlink.
For
user space programs, Netlink
is a special socket based communication mechanism which is asynchronous and used for
bidirectional data transfer between the kernel and the user application.
The
user socket application can use the standard socket API to use the powerful
functions provided by Netlink(Please visit the wiki page for more details).
What
we see above from the diagram is a basic workflow model of how vold works and
some of the components involved.
vold is a native program for managing and controlling the control center of the
external storage device on the Android platform. It is a background running
process. It interacts with the Java layer MountService. vold receives uevent
messages from the kernel and forwards them to the upper layer.
The
MountService receives messages from vold and can also send control commands to
vold. vold has broadly three modules, NetlinkManager, VolumeManager, and CommandListener.
The
NetlinkManager module specifically receives the uevent message from the Linux
kernel and forwards the message to the VolumeManager.
The
VolumeManager module then sends the related information to the MountService
through the CommandListener.
The
MountService sends the corresponding processing command to the VolumeManager
according to the received message, and the VolumeManager receives the command.
Then directly operate the external storage device.
The
CommandListener module internally encapsulates a Socket for cross-process
communication. The client-side MountService of the Java layer communicates with
the server-side vold via the Socket.
The
required device information is exported by the sysfs file system. For every
device the kernel has detected and initialized, a directory with the device
name is created. It contains attribute files with device-specific properties.
Every time a device is added or removed, the kernel sends a uevent to notify
udev of the change.
The
udev daemon reads and parses all provided rules from the
/etc/udev/rules.d/*.rules files once at start-up and keeps them in memory. If
rules files are changed, added, or removed, the daemon receives an event and
updates the in-memory representation of the rules.
Every
received event is matched against the set of provides rules. The rules can add
or change event environment keys, request a specific name for the device node
to create, add symlinks pointing to the node, or add programs to run after the
device node is created. The driver core uevents are received from a kernel
netlink socket.
Source
Code Analysis.
Vold
startup.
During
boot the init.rc starts vold process, Let us see how.
The
vold executable is in /system/bin.
Let
us see some of the important steps as part of the vold startup.
1. Check
and initialize the selinux file context handle.
2. Create
the vold device folder.
3. Initialize
and start the related classes of VolumeManager, NetlinkManager, CommandListener and CryptCommandListener.
4. Start
the VolumeManager and NetlinkManager.
5. Start
the CommandListener and eventually become the monitoring thread.
Remember
that VolumeManager and NetlinkManager are singletons.
The
process_config function reads the fstab file and initialize the disksources as
seen above.
Vold
component relationship.
We
already understood that vold typically consists of 3 components, NetlinkManager,
VolumeManager, and CommandListener.
We
shall visit these components in order to understand more on them.
The
NetlinkManager receives the uevent messages from the Kernel, resolves it into a
NetlinkEvent object, and passes this NetlinkEvent object to the VolumeManager
for processing.
We
can see from above that the NetlinkManager on starting creates a socket and binds
to it and starts the NetlinkHandler associated with the socket.
The
job of NetlinkHandler is to check check if the events received from the uevent
are for block devices and asj the VolumeManager to handle them.
Let
us also quickly have a small glance at the SocketListener::startListener code
which is self explanatory.
The
SocketListener::threadStart starts the Listener above which keeps waiting for
an uevent message.
The
most important part of SocketListener::runListener() is listening on socketlist
and as soon as it gets a message call the onDataAvailable().
We
can see how onEvent(evt); gets called by the NetlinkListener::onDataAvailable
and implemented by NetlinkHandler::onEvent() as shown above which checks if the
message belongs to subsys calls VolumeManager to handle this message and we
also complete our loop.
VolumeManager.
The
VolumeManager module sends the related information obtained above to the
MountService through the CommandListener.
Major
steps which involve in the working of VolumeManager are.
1) Constructing VolumeManager object instance
2) Setting up event broadcast monitoring
3) Starting VolumeManager
4) Configuring VolumeManager
Let
us get into a code walkthrough and we will understand things more.
We
already know that VolumeManager is a singleton. Let us move forward.
ueevent
processing.
The
NetlinkManager module introduced above has an onEvent function which gets the
NetlinkEvents and passes on to the VolumeManager for further processing.
Let
us see how that works.
Before
we move and see the handling of these NetLinkEvents, Let us try and understand
what are these events.
The
names of these Events are self-explanatory. Let us continue.
Let us also look at some of the paths and device numbers which are used to add / remove these volumes.
We
start by extracting the DEVPATH and DEVTYPE from the event message. Only
process the message if the DEVTYPE is “disk”.
Find the MAJOR & MINOR numbers for the device driver and create it.
NetlinkEvent::Action::kAdd
NetlinkEvent::Action::kChange
NetlinkEvent::Action::kRemove
Look at the Disk class other functions in detail if you want to learn actually how devices are maintained.
Depending
on the type of events we add or remove these disks. Let us also see the Disk class which is actually responsible for creating and managing Disk connections in Disk.cpp above.
Once the Disk add/removes/modifies these volume entries, It Broadcasts this to the MountService using the CommandListener which is inherited from FrameworkListener which is again inherited from SocketListener.
CommandListener.
Let us see some more details on CommandListener.
Message
processing.
When
receiving a message sent by the MountService, FrameworkListener::onDataAvailable
is called to handle the command.
The
CommandListener parent FrameworkListener overrides the message handling
onDataAvailable function.
FrameworkListener::dispatchCommand
later after doing all checks and balances calls runCommand function to handle
various commands sent by the MountService.
We
already saw how FrameworkCommand gets registered along with their handler
functions above.
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd());
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
registerCmd(new StorageCmd());
registerCmd(new FstrimCmd()); as shown below.
Please check the CommandListener for more details. Logically every command registers a runCommand function which is responsible for the corresponding command implementation example.
Let us see another runCommand dunction for the volume command.
We can get into the details of this function however it is really simple to understand.
Typically most of the functionality is implemented by VolumeBase class we can see some of them below.
We will try and understand more on the details of MountService in the coming tutorials to see how it is created and different scenarios in which it works.
Very nice article,thank you...
ReplyDeleteandroid app development course
Now, I understand how SD card is detected.
ReplyDeleteThis is exactly what I'm looking for and I Google anything. I have no idea how to make my Google bring up more answers like yours but I wish it was as easy as Googling it. LOL thank you so much.
ReplyDeleteDAEMON Tools Pro 8.3.0.0767 Crack
ReplyDeleteI am very impressed with your post because this post is very beneficial for me and provide a new knowledge to me
Discover top-quality spy gadgets online in Delhi at Spy World. Stay ahead with our cutting-edge surveillance technology and enhance your security today!
ReplyDelete