Audio

Mixer configuration
This provides a brief overview of how Android audio HALs configure the ALSA mixer.

Android devices can have an assortment mixer configurations such as headphones, speakers, or microphones. For a particular device the audio route configurations are defined in. For an example see the mixer path XML for Nexus 5 (hammerhead).

Android audio HALs make use of tinyalsa and audio_route. Tinyalsa is a small standalone library to interface with ALSA in the Linux kernel. Audio HALs call the  library which loads audio routes from an XML and controls the mixer through.

Format of mixer_paths.xml

 * ALSA controls are defined by  elements.
 * Audio routes are defined by  elements. A   element contains a collection of   elements as well as other   elements.
 * The path  attribute is used to select an audio route.

During initialisation, all the mixer controls specified at the top of the file will be applied. To apply a particular path (e.g. "speaker") the controls in that path will be applied, switching to say, "headphones", involved resetting the controls back to their values before the speaker path was applied, in reverse order, and then applying the new path.

Headphone jack
Android kernels use  kernel driver to notify the Android frameworks of headphone jack events. The driver source code can be located at: or . Note that the switch class driver is an Android specific driver. It has not been upstreamed to the mainline kernel.

In userspace the WiredAccessoryManager monitors the  for uevents when the headphone is (un)plugged.

Udev rules can be used to detect if headphones are plugged in, example for this is from xiaomi-santoni

Bring up Android DSP subsystem
ADSP needs to be powered on before audio could work on downstream kernels. To do that, you'll have to supply firmware files that is available on your internal MMC.

On a shell prompt inside postmarketOS, type  (replace mmcblk0 with the correct device name for internal MMC). If that doesn't display the partition labels, you can also try  or. At this point you should get a familiar partition layout of a Android device.

Now, the only thing that is important is the partition with  label on it, which on my device it's mmcblk0p1. Mount the partition as read-only to /mnt using:


 * 1) mount -o ro /dev/mmcblk0p1 /mnt

Inside /mnt, there is a folder named  which has a bunch of firmware files for different parts of the device, like wcnss (for wlan), DRM contents and so on, the only thing that needs to be extracted is all the files that named  :

// Create /lib/firmware/postmarketos if it doesn't exist
 * 1) mkdir -p /lib/firmware/postmarketos

// Copy all adsp.* to the postmarketOS firmware directory
 * 1) cp -v /mnt/image/adsp.* /lib/firmware/postmarketos

After that, you should be able to bring up the ADSP subsystem by running:
 * 1) echo 1 > /dev/subsys_adsp

You should check dmesg and /var/log/firmwareload.log to make sure there aren't firmwares failing to load.

If it goes fine, you should see a bunch of playback devices by typing

You also want to install  from pmOS repo to load the subsystem on automatically on bootup.

Convert XML audio to UCM
The audio routes in Linux userspace can be defined in ALSA UCM configuration files. There is a tool called xml2ucm which will convert the Android  and a device config XML to UCM files. The  tool introduces the device config XML which provides necessary routing information that was hardcoded in the audio HAL on Android.

The  is commonly found in the Android device repository. (e.g. ). You must write the device config XML for your device.

Format of device config XML
A device config XML describes a sound card with use cases and sets of audio routes. In the examples available at the moment there is only one use case named HiFi. Under each  there are multiple   elements. In this context a  means audio route(s) which comprise a logical audio device (e.g. Headphone, Headset, Speaker).

Android audio HALs can and do select multiple audio routes at once. For example a headset can have a headphone output route and a microphone input route. To handle this a  element (the headset) can contain multiple   elements (audio routes). Example device config XML files are provided in the  repository.

The  must be the name of the sound card which can be obtained using. In the following example from the Samsung p4wifi the  is the sound card named.

Once the  and device config XML are converted to UCM format then an audio route can be set by using. Example:

libhybris
In general in Hybris environment just install pulseaudio-modules-droid package and sound will work.

Make sure you have the following line in your : load-module module-droid-card Loading droid-card module is enough, other modules will be loaded automatically. Also it would not hurt to comment out,   lines to lower the amount of error messages in pulseauduio log (these modules don't work anyway), like that:
 * 1) Automatically load driver modules depending on the hardware available
 * 2) .ifexists module-udev-detect.so
 * 3) load-module module-udev-detect
 * 4) .else
 * 5) Use the static hardware detection module (for systems that lack udev support)
 * 6) load-module module-detect
 * 7) .endif

Start pulseaudio in verbose mode to make sure you can get to see if module-droid-card loads successfully. If it does then you should be able to play sound files using  from pulseaudio-utils package.

If you hear sounds coming from it, it works perfectly fine. If not, check dmesg, pulseaudio log and logcat.

You might also want to install  for ALSA backend on PulseAudio.

Audio cutting out when multiple streams start playing
See here

alsactl method
Cascardo reported having success with the following method on Debian, this should work for postmarketOS as well: I ran a debian chroot on a cyanogenmod, set the volume up, then ran alsactl save on the chroot. booted into debian, then after alsactl restore was run, I had audio working

so, in summary, it's hard to know which mixer settings will make it work, so my strategy was running some android stack that correctly set the mixer, then saving the state with a chroot or any other tool that would allow you to save, copy and restore that state later on a gnu stack

This method may work for non-Android devices as well, as long as you see an audio device in. Just boot the normal OS, save the volume settings somehow, then restore them.

amixer method
You can also skip the chroot step and run amixer on Android directly; then, you'll have to copy over the other settings manually. This is a bit more time-intensive, but should work well for most devices.


 * Root your device
 * Get a copy of amixer that runs under Android (I got mine by installing this Magisk module; sadly it installed without execute permissions, I had to move  to   (  wouldn't let me make it executable) and run it from there)
 * Get into a terminal and run
 * You will have do this twice - once with a headset plugged in, and once without; save them as separate files
 * Copy the files onto your computer
 * On your mainline device, run, then diff the output with the downstream output
 * You might want to get the diff using, then remove the "Capability" lines using   since it's fine if they're different
 * Open  on the Linux device and tweak the values until they match
 * Repeat diffing process as many times as necessary
 * Then save the output of  again, or run

strace method
It is possible to get audio working by stracing Android's audioserver and replicating the mixer configuration it performs. See here.

The positive side of such porting is that the amount of manual work is reduced to the minimum, another positive thing is that it may also work for non-Android proprietary userspace.

Spreadtrum
Audio support for Spreadtrum SoCs is provided in  and its subpackages. To get audio support for the device, add the package related to the audio device to dependencies of device package or install it manually, like apk add soc-sprd-audio-sc8830

WM1811
This audio chip is present in several Samsung devices that are based on the Exynos 4412 platform. There is a configuration for the Samsung Galaxy Note 10.1 available at the opensgn project. Have a look at the files in. In  there are the commands to use the configuration:

/usr/sbin/alsactl restore -f /usr/share/alsa/ucm/Midas_WM1811/init.state
 * 1) restore alsa sinitial tate

/usr/bin/alsaucm -c Midas_WM1811 set _verb HiFi set _enadev Speaker /usr/bin/alsaucm -c Midas_WM1811 set _verb HiFi set _enadev Mic
 * 1) enable speaker for output and builtin mic for input

For other devices the configuration might need to be adapted. On the Samsung Galaxy Note 8.0 for example, the audio device is named "Kona_WM1811". Replacing all occurrences in file names and file contents of  by   worked.

In case the existing UCM configs don't work, it's possible to get the ALSA mixer settings by running amixer on Android. This also works with the mainline kernel, as the settings there are nearly identical.

In mainline
The WM1811 is supported in mainline, as part of the Galaxy S3 (midas) support. Portions of the midas code can be reused between other Exynos devices using the same SoC and sound chip.

Troubleshooting audio input
A nice way to troubleshoot audio input is to run arecord in a terminal to get realtime audio levels of the default alsa input: