AOSP Expert & Production Engineering
5 min read

Device Bring-Up Steps

Introduction to Device Bring-Up

Device bring-up is the process of getting the Android Open Source Project (AOSP) to boot and function on a new piece of hardware. It is often considered one of the most challenging and rewarding tasks in Android systems engineering. The bring-up phase requires a methodical approach, transitioning a device from a brick state to a fully functional smartphone or tablet.

During bring-up, you will encounter bootloops, kernel panics, and countless SELinux denials. Success requires an iterative approach: isolating subsystems, examining logs, and enabling features one by one.

Phase 1: Securing Display Output

The very first goal in any device bring-up is visual feedback. Until the display works, debugging relies entirely on serial console output (UART) or rudimentary USB debugging.

Bootloader and Splash Screen

The bootloader initializes the display controller. If the bootloader cannot bring up the display, the kernel will not be able to either. Ensure the bootloader correctly configures the MIPI DSI (Mobile Industry Processor Interface Display Serial Interface) or eDP (Embedded DisplayPort) interface.

Kernel Display Subsystem (DRM/KMS)

Android relies on the Direct Rendering Manager (DRM) and Kernel Mode Setting (KMS) subsystems. You need to ensure the correct panel driver is compiled and loaded.

// Example: Panel driver probe function in kernel
static int my_panel_probe(struct mipi_dsi_device *dsi)
{
    struct my_panel *panel;
    int err;

    panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
    if (!panel)
        return -ENOMEM;

    mipi_dsi_set_drvdata(dsi, panel);
    panel->dsi = dsi;

    // Initialize display panel sequence
    err = mipi_dsi_attach(dsi);
    if (err)
        return err;

    return 0;
}

If the display remains black, verify the backlight driver. You can often test the backlight directly via sysfs:

# Enable backlight manually via shell
echo 255 > /sys/class/leds/lcd-backlight/brightness

Phase 2: Establishing ADB Connectivity

Once the kernel boots, securing an Android Debug Bridge (ADB) connection is critical. ADB provides a shell, logcat access, and file transfer capabilities.

USB Gadget Configuration

Android uses the USB gadget framework (ConfigFS) to configure USB endpoints. During early bring-up, you must ensure the init.rc scripts correctly initialize the USB controller.

Check your device-specific init.${ro.hardware}.rc or init.${ro.hardware}.usb.rc:

on boot
    mount configfs none /config
    mkdir /config/usb_gadget/g1 0770 shell shell
    mkdir /config/usb_gadget/g1/strings/0x409 0770 shell shell
    write /config/usb_gadget/g1/idVendor 0x18D1
    write /config/usb_gadget/g1/idProduct 0x4EE7
    write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}
    write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}
    write /config/usb_gadget/g1/strings/0x409/product ${ro.product.model}

If ADB is failing, verify the adbd service is running using the serial console:

# Check if adbd is running
ps -A | grep adbd

Ensure the USB composition includes ffs (FunctionFS) which adbd relies upon.

Phase 3: Fixing SELinux Denials Iteratively

AOSP enforces SELinux strictly. During bring-up, you will inevitably face permission denials that block critical services from starting.

Understanding dmesg Denials

When a service fails, check the kernel log for avc: denied messages.

# Extract SELinux denials from dmesg
dmesg | grep 'avc: denied'

Example output: type=1400 audit(1620000000.000:12): avc: denied { read } for pid=345 comm="surfaceflinger" name="hwc" dev="tmpfs" ino=1234 scontext=u:r:surfaceflinger:s0 tcontext=u:object_r:hwc_prop:s0 tclass=file permissive=0

Resolving the Denial

To fix the above denial, you must add the appropriate rule to your device's sepolicy files (e.g., device/manufacturer/codename/sepolicy/vendor/surfaceflinger.te).

# Allow surfaceflinger to read hwc_prop
get_prop(surfaceflinger, hwc_prop)

Iterate through denials systematically. Tools like audit2allow can automate rule generation, but always review the generated rules to ensure you are not compromising system security.

# Generate SELinux rules from dmesg
adb shell dmesg | audit2allow -p out/target/product/codename/root/sepolicy

Phase 4: Bringing up WiFi and Bluetooth

Connectivity relies heavily on vendor specific blobs (proprietary firmware and HALs).

WiFi Bring-Up

WiFi bring-up requires the kernel driver (e.g., wlan.ko), firmware blobs in /vendor/firmware, and the WPA Supplicant configuration.

Ensure the wpa_supplicant service is correctly defined in your init.rc:

service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
    -O/data/vendor/wifi/wpa/sockets -puse_p2p_group_interface=1 \
    -g@android:wpa_wlan0
    interface android.hardware.wifi.supplicant@1.0::ISupplicant default
    interface android.hardware.wifi.supplicant@1.1::ISupplicant default
    class main
    socket wpa_wlan0 dgram 660 wifi wifi
    disabled
    oneshot

Bluetooth Bring-Up

Bluetooth typically uses a UART interface or shared SDIO bus. Ensure the bt_vendor.conf is correctly configured and the android.hardware.bluetooth@1.x-service is running.

Check the logcat for HCI (Host Controller Interface) timeout errors, which usually indicate incorrect UART configuration or missing firmware.

Phase 5: Camera and Audio Bring-Up

Multimedia subsystems are often the most complex due to tight integration between kernel drivers, hardware abstraction layers (HALs), and framework services.

Audio Routing and HAL

Audio requires ALSA (Advanced Linux Sound Architecture) kernel drivers. The Audio HAL reads configuration from audio_policy_configuration.xml and mixer_paths.xml.

If audio fails, use tinyplay to bypass the Android framework and test the kernel ALSA driver directly:

# Test audio playback directly via ALSA
tinyplay /sdcard/test.wav -D 0 -d 0

If tinyplay works but Android audio fails, the issue lies in the Audio HAL or mixer_paths.xml configuration.

Camera Pipeline

The Camera subsystem requires the V4L2 (Video for Linux 2) kernel framework and a vendor specific Camera HAL. Ensure the sensor drivers are loaded and probing correctly in dmesg.

# Verify camera sensor detection in kernel
dmesg | grep "camera"

The dumpsys media.camera command is invaluable for checking the state of the camera service and identifying whether the HAL is properly registered.

# Check camera service state
dumpsys media.camera

By methodical isolation and log analysis, you can successfully navigate the bring-up process, transforming a board into a fully integrated Android device.