The Inter-IC Sound (IIS or I2S) bus connects digital audio devices and transfers PCM audio data between them. It is commonly used to connect microphones and audio amplifiers to a host control system.
I2S is a synchronous serial interface, which means it relies on shared clock signals to synchronize data transfer between devices. An I2S master device drives communication and timing through the primary bit clock (BCLK) signal, similar to I2C or SPI. I2S also includes a separate left-right clock (LRCLK) signal, which the master uses to select the proper audio channel for data (left or right).

I2S devices contain at least one Serial Data (SD) signal. This is common with peripherals, which generally only produce or consume audio data. Master devices are more likely to have dedicated lines for receive (SDIN) and transmit (SDOUT) to support full-duplex communication. This allows you to connect to multiple peripherals to send and receive audio data simultaneously.
Managing the device connection
In order to open a connection to a particular I2S device, you need to
know the unique name of the bus. During the initial stages of development, or
when porting an app to new hardware, it's helpful to discover all the available
device names from PeripheralManagerService using getI2sDeviceList():
PeripheralManagerService manager = new PeripheralManagerService();
List<String> deviceList = manager.getI2sDeviceList();
if (deviceList.isEmpty()) {
Log.i(TAG, "No I2S bus available on this device.");
} else {
Log.i(TAG, "List of available devices: " + deviceList);
}
Once you know the target device name, use PeripheralManagerService to connect
to that device and supply the audio parameters of the PCM data. You can provide
these as discrete parameters, or as an
AudioFormat.
When you are done communicating with the peripheral device,
close the connection to free up resources. Additionally, you cannot open a new
connection to the device until the existing connection is closed. To close the
connection, use the device's close() method.
public class HomeActivity extends Activity {
// I2S Device Name
private static final String I2S_DEVICE_NAME = ...;
private static final AudioFormat AUDIO_FORMAT_STEREO =
new AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_IN_STEREO)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(44100)
.build();
private I2sDevice mDevice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Attempt to access the I2C device
try {
PeripheralManagerService manager = new PeripheralManagerService();
mDevice = manager.openI2sDevice(I2S_DEVICE_NAME, AUDIO_FORMAT_STEREO);
} catch (IOException e) {
Log.w(TAG, "Unable to access I2S device", e);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mDevice != null) {
try {
mDevice.close();
mDevice = null;
} catch (IOException e) {
Log.w(TAG, "Unable to close I2S device", e);
}
}
}
}
Choosing an audio format
When creating an I2S connection, the supplied audio parameters define the transfer characteristics of the bus, such as the clock frequency. Consider the following example format for 2-channel audio data, 16-bit samples, captured at 44.1kHz:
private static final AudioFormat AUDIO_FORMAT_STEREO =
new AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_IN_STEREO) // 2 channels
.setEncoding(AudioFormat.ENCODING_PCM_16BIT) // 16-bit samples
.setSampleRate(44100) // 44.1kHz
.build();
In addition to describing the expected audio data, this tells the I2S driver the required frequency of the BCLK signal. The frequency is derived from the following formula:
Frequency = SampleRate x Encoding x ChannelCount
Per the formula, the above example format requires an I2S bit clock frequency of 1.41MHz. Similar to the requirements on UART baud rate, the timing of this signal must be very accurate to avoid transmission errors caused by jitter. Ensure that your hardware platform can accurately generate the required bit clock frequency for your chosen format parameters.
To learn more about audio frames, encoding, and sampling, see the AudioFormat reference.
Transferring audio samples
The data transfer methods of I2sDevice mirror the format of the
AudioTrack and
AudioRecord APIs. This allows your
app to integrate with custom audio peripherals the same way it would with the
built-in microphone or speaker. Each method accepts data as a byte[], short[],
or ByteBuffer. Choose the version that matches the
encoding
used for your audio data.
The following example reads data from an I2S input device (such as a microphone) and echoes that data out through the default audio route:
public int echoAudio(String i2sName, AudioFormat format) throws IOException {
// Set up audio input source
PeripheralManagerService manager = new PeripheralManagerService();
I2sDevice source = manager.openI2sDevice(i2sName, format);
// Set up the audio playback sink
int bufferSize = AudioTrack.getMinBufferSize(
format.getSampleRate(),
format.getChannelMask(),
format.getEncoding());
AudioTrack sink = new AudioTrack.Builder()
.setAudioFormat(format)
.setTransferMode(AudioTrack.MODE_STATIC)
.setBufferSizeInBytes(bufferSize)
.build();
// Transfer data from input to output
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
int read = source.read(buffer, bufferSize);
sink.write(buffer, read);
return read;
}