Introduction: Bridging Android and systemd in Embedded Systems
While Android primarily utilizes its own init system for process and service management, many advanced embedded Linux systems and custom AOSP (Android Open Source Project) builds for IoT, automotive, or specialized industrial devices often integrate systemd. This powerful suite of system and service managers provides a robust, declarative way to define and manage system services, manage boot processes, and enforce complex dependencies. For Android developers working on such custom platforms, understanding systemd is crucial for building reliable, self-healing applications that correctly interact with underlying hardware and network infrastructure. This guide will walk you through crafting sophisticated systemd unit files to manage hardware and network dependencies, ensuring your Android-centric services launch only when all prerequisites are met.
systemd Fundamentals for Android Developers
At its core, systemd manages ‘units’ – configuration files describing system resources or services. Key unit types you’ll encounter include:
.service: Defines a system service (e.g., a background application, a custom daemon)..target: Groups other units and defines synchronization points during boot or runtime. Think of them as logical states (e.g.,multi-user.target,graphical.target)..device: Represents a kernel device exposed throughsysfs. Automatically generated bysystemd-udevd..mount: Defines a filesystem mount point.
Dependencies are managed using directives within the [Unit] section of a unit file:
Wants=: A weak dependency. If the wanted unit fails to start, this unit will still attempt to start.Requires=: A strong dependency. If the required unit fails to start, this unit will not start.After=: Defines a strict ordering. This unit will start after the listed units.Before=: Defines a strict ordering. This unit will start before the listed units.BindsTo=: Creates a strong dependency that causes this unit to stop if the bound unit stops. Often used with mount units.PartOf=: Indicates that this unit is part of another unit (usually a target). Stopping or restarting the parent unit will also affect this unit.
Basic Unit File Structure
A typical .service unit file is divided into sections:
[Unit]Description=My Custom Android Background ServiceAfter=network-online.target[Service]ExecStart=/usr/local/bin/my-android-serviceType=simpleRestart=on-failureUser=android-userGroup=android-groupWorkingDirectory=/data/local/tmp[Install]WantedBy=multi-user.target
Handling Hardware Dependencies
For custom Android devices, services often rely on specialized hardware like custom sensors, input devices, or peripherals. Ensuring these are initialized and available before your service starts is critical.
Identifying Hardware with udev
udev is the Linux device manager that dynamically handles device events. When a device is plugged in or detected during boot, udev rules can be triggered. You can use tools like lsusb, lspci, or inspect /sys filesystem entries to identify unique hardware attributes (Vendor ID, Product ID, Serial Number, etc.).
For example, let’s say you have a custom USB device with Vendor ID 1234 and Product ID 5678. You can create a udev rule to tag it:
# /etc/udev/rules.d/99-mydevice.rulesSUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", SYMLINK+="my_custom_device", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="my-usb-device.device"
After reloading udev rules (sudo udevadm control --reload-rules && sudo udevadm trigger), systemd will create a .device unit for it, named after the device node or alias (e.g., sys-devices-platform-...-usb-1234:5678.device or my-usb-device.device if SYSTEMD_ALIAS is used). You can then use this in your service unit.
Crafting a Service for Hardware Readiness
Let’s create a service that waits for our custom USB device:
# /etc/systemd/system/my-hardware-app.service[Unit]Description=Android App Service requiring Custom USB DeviceAfter=systemd-udev-settle.serviceRequires=my-usb-device.device# Or if using the full sysfs path:Requires=sys-devices-platform-<bus>-<port>...-usb-1234:5678.device[Service]ExecStart=/usr/local/bin/start-my-android-app-with-usbType=simpleRestart=on-failureUser=android-app-user[Install]WantedBy=multi-user.target
systemd-udev-settle.service is important as it waits for all udev events to be processed, ensuring device nodes are stable.
Advanced Hardware Checks with Condition Directives
systemd provides powerful Condition directives for more granular control:
ConditionPathExists=/dev/my_custom_device: Checks if a specific device node exists.ConditionDeviceIsBound=/sys/bus/usb/devices/1-1: Checks if a device at a specific sysfs path is bound to a driver.
Example using ConditionPathExists:
[Unit]Description=Android Sensor ServiceConditionPathExists=/dev/i2c-4# ... other dependencies
Managing Network Dependencies
Many Android services require active network connectivity for data synchronization, API calls, or remote management. systemd offers a standardized way to manage this.
The network-online.target
The simplest and most common way to wait for network connectivity is to use network-online.target. This target is considered active when a network interface (typically Ethernet or Wi-Fi) has obtained an IP address and is generally considered functional.
# /etc/systemd/system/android-sync-service.service[Unit]Description=Android Data Synchronization ServiceAfter=network-online.target[Service]ExecStart=/usr/local/bin/android-data-syncType=forkingUser=android-sync-user[Install]WantedBy=multi-user.target
Note: network-online.target typically relies on network management services like systemd-networkd, NetworkManager, or custom scripts to signal its readiness. Ensure your network configuration properly integrates with these.
Waiting for Specific Network Interfaces
If your service requires a *specific* interface (e.g., an Ethernet connection, not Wi-Fi), you might need a more tailored approach. You can create a custom unit or use a Condition directive.
For example, to wait for an Ethernet interface named eth0:
[Unit]Description=Android VPN ClientAfter=network-online.targetConditionPathExists=/sys/class/net/eth0/operstateConditionFileIsExecutable=/usr/sbin/openvpn# ExecStartPre can also be used for more complex checksExecStartPre=/bin/sh -c 'while ! ip link show eth0 up; do sleep 1; done'[Service]ExecStart=/usr/sbin/openvpn --config /etc/openvpn/client.confType=forkingUser=vpn-user[Install]WantedBy=multi-user.target
Crafting Robust Unit Files: Advanced Techniques
Beyond basic dependencies, systemd offers features for resilience and control.
Service Types
Type=simple: The default. Process specified byExecStartis the main process.Type=forking: The process specified inExecStartwill fork into a child process and the parent will exit.systemdwaits for the parent to exit before considering the service started. Useful for traditional daemons.Type=oneshot: A short-lived command that exits immediately.systemdwaits for the command to finish before proceeding. Useful for initialization tasks.
Restart Policies
The Restart= directive in the [Service] section defines when the service should be restarted:
no: Never restart.on-failure: Restart if exit code is non-zero, or if it terminates on a signal (except clean exits).always: Always restart, regardless of exit code or signal.on-abnormal,on-success, etc., offer more nuanced control.
[Service]ExecStart=/opt/android-kiosk/kiosk-app.shRestart=on-failureRestartSec=5 # Wait 5 seconds before restarting
Practical Example: A Custom Android Kiosk Service
Imagine an Android-based kiosk device. Your custom service, kiosk-display.service, needs a specific external USB display (identified by my-usb-display.device from udev rules) to be ready, and it also requires network connectivity to download content.
Step 1: Define udev Rule for the USB Display
Create /etc/udev/rules.d/90-kiosk-display.rules:
SUBSYSTEM=="usb", ATTR{idVendor}=="04D8", ATTR{idProduct}=="F003", SYMLINK+="kiosk_display", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="kiosk-usb-display.device"
Reload udev rules: sudo udevadm control --reload-rules && sudo udevadm trigger
Step 2: Create the Kiosk Service Unit File
Create /etc/systemd/system/kiosk-display.service:
[Unit]Description=Android Kiosk Display ServiceDocumentation=https://example.com/kiosk-guide.htmlAfter=network-online.target systemd-udev-settle.service# Requires both network AND the specific USB displayRequires=network-online.target kiosk-usb-display.device[Service]Type=simple# User and Group under which the Android app will runUser=kiosk-userGroup=kiosk-group# Environment variables for the Android appEnvironment="DISPLAY_MODE=external" "KIOSK_ID=ABC123"# Command to start your custom Android application or related serviceExecStart=/usr/local/bin/start-kiosk-app.sh# Ensure the service restarts if it crashesRestart=on-failureRestartSec=10# Give it some time to start upTimeoutStartSec=60s[Install]# This service should be active when the system is in multi-user modeWantedBy=multi-user.target
Step 3: Enable and Start the Service
sudo systemctl daemon-reloadsudo systemctl enable kiosk-display.servicesudo systemctl start kiosk-display.service
You can monitor its status with sudo systemctl status kiosk-display.service and view logs with journalctl -u kiosk-display.service. If either the network or the USB display is not available, systemd will hold off starting the kiosk service, preventing premature launches and potential errors.
Conclusion
For Android developers engaged in custom embedded Linux systems or specialized AOSP deployments, mastering systemd unit files is an invaluable skill. By precisely defining hardware and network dependencies, you can create more resilient, self-managing, and robust applications. Leveraging directives like Requires=, After=, network-online.target, and integrating with udev events allows you to orchestrate complex boot and runtime sequences, ensuring your Android-based services operate flawlessly in diverse and demanding environments.
Android Mobile Specs & Compare Directory
Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!
Compare Devices Specs →