Advanced AOSP Subsystems
3 min read

AudioTrack

Overview

AudioTrack is the primary Java/C++ API in Android for playing streaming audio. Unlike MediaPlayer, which handles the entire decoding pipeline, AudioTrack operates purely on raw, uncompressed Pulse Code Modulation (PCM) data or compressed audio formats passed directly for hardware offloading. It sits at the top of the audio framework stack, interfacing directly with the AudioFlinger system service.

AudioTrack API: Creating and Writing PCM Data

To use AudioTrack, an application must specify the audio characteristics, allocate an internal buffer, and then push PCM data into that buffer.

Initialization

Initialization requires defining the stream type, sample rate, channel configuration, and audio format (typically 16-bit PCM or Float).

int sampleRate = 44100;
int channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);

AudioTrack audioTrack = new AudioTrack.Builder()
    .setAudioAttributes(new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build())
    .setAudioFormat(new AudioFormat.Builder()
            .setEncoding(audioFormat)
            .setSampleRate(sampleRate)
            .setChannelMask(channelConfig)
            .build())
    .setBufferSizeInBytes(minBufferSize * 2)
    .setTransferMode(AudioTrack.MODE_STREAM)
    .build();

audioTrack.play();

Writing Data

In MODE_STREAM, the application continuously writes to the track in a loop. This is ideal for streaming media or synthesized audio.

short[] audioData = getNextAudioFrame();
int bytesWritten = audioTrack.write(audioData, 0, audioData.length);

In MODE_STATIC, the entire audio buffer is written once before playback begins, which is useful for short sound effects with low latency requirements.

Audio Session and Attributes

Android manages audio routing and concurrency using AudioAttributes and Audio Sessions.

  • AudioAttributes: Replaced the legacy streamType (like STREAM_MUSIC). They describe the why (usage) and what (content type) of the audio. The AudioPolicyManager uses these attributes to determine routing (e.g., routing USAGE_ALARM to the device speaker even if headphones are plugged in).
  • Audio Session ID: A unique identifier grouping audio streams for applying effects. If you want to apply an Equalizer to a specific AudioTrack, you attach the effect to the track's Session ID.

Shared Memory Ring Buffer with AudioFlinger

The true power of AudioTrack lies in its IPC (Inter-Process Communication) mechanism. Writing audio data across process boundaries via standard Binder calls for every frame would introduce unacceptable latency and CPU overhead.

Instead, Android uses a lockless shared memory ring buffer (often referred to as cblk or control block).

  1. Allocation: When AudioTrack is created, AudioFlinger allocates a chunk of shared memory (ashmem).
  2. Mapping: Both the app process and the AudioFlinger process map this memory into their address spaces.
  3. Producer/Consumer:
    • The App (AudioTrack) is the Producer. It writes PCM data into the ring buffer and updates the write pointer in the control block.
    • AudioFlinger is the Consumer. Its mixing thread reads from the buffer, updates the read pointer, and mixes it with other active tracks.
  4. Synchronization: Futexes (fast userspace mutexes) are used to block the app if the buffer is full, or block AudioFlinger if the buffer is empty (an underrun).

AudioTrack State Machine

Internally, AudioTrack maintains a strict state machine to manage the native resources.

  • STATE_UNINITIALIZED: Creation failed or resources released.
  • STATE_INITIALIZED: Buffer allocated, ready for playback.
  • PLAYSTATE_PLAYING: AudioFlinger is actively consuming data.
  • PLAYSTATE_PAUSED: Consumption stopped, buffer contents preserved.
  • PLAYSTATE_STOPPED: Playback halted, buffer pointers reset.

To debug active AudioTrack instances across the system, you can dump the media.metrics or audioflinger services:

adb shell dumpsys media.audio_flinger

This command lists all active clients, their session IDs, formats, and buffer underrun statistics.