154362a6e2208117b98db169af9e03c082175af38Heidi Millerpage.title=TV Audio
254362a6e2208117b98db169af9e03c082175af38Heidi Miller@jd:body
354362a6e2208117b98db169af9e03c082175af38Heidi Miller
454362a6e2208117b98db169af9e03c082175af38Heidi Miller<!--
554362a6e2208117b98db169af9e03c082175af38Heidi Miller    Copyright 2014 The Android Open Source Project
654362a6e2208117b98db169af9e03c082175af38Heidi Miller
754362a6e2208117b98db169af9e03c082175af38Heidi Miller    Licensed under the Apache License, Version 2.0 (the "License");
854362a6e2208117b98db169af9e03c082175af38Heidi Miller    you may not use this file except in compliance with the License.
954362a6e2208117b98db169af9e03c082175af38Heidi Miller    You may obtain a copy of the License at
1054362a6e2208117b98db169af9e03c082175af38Heidi Miller
1154362a6e2208117b98db169af9e03c082175af38Heidi Miller        http://www.apache.org/licenses/LICENSE-2.0
1254362a6e2208117b98db169af9e03c082175af38Heidi Miller
1354362a6e2208117b98db169af9e03c082175af38Heidi Miller    Unless required by applicable law or agreed to in writing, software
1454362a6e2208117b98db169af9e03c082175af38Heidi Miller    distributed under the License is distributed on an "AS IS" BASIS,
1554362a6e2208117b98db169af9e03c082175af38Heidi Miller    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1654362a6e2208117b98db169af9e03c082175af38Heidi Miller    See the License for the specific language governing permissions and
1754362a6e2208117b98db169af9e03c082175af38Heidi Miller    limitations under the License.
1854362a6e2208117b98db169af9e03c082175af38Heidi Miller-->
1954362a6e2208117b98db169af9e03c082175af38Heidi Miller<div id="qv-wrapper">
2054362a6e2208117b98db169af9e03c082175af38Heidi Miller  <div id="qv">
2154362a6e2208117b98db169af9e03c082175af38Heidi Miller    <h2>In this document</h2>
2254362a6e2208117b98db169af9e03c082175af38Heidi Miller    <ol id="auto-toc">
2354362a6e2208117b98db169af9e03c082175af38Heidi Miller    </ol>
2454362a6e2208117b98db169af9e03c082175af38Heidi Miller  </div>
2554362a6e2208117b98db169af9e03c082175af38Heidi Miller</div>
2654362a6e2208117b98db169af9e03c082175af38Heidi Miller
2754362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>The TV Input Framework (TIF) manager works with the audio routing API to support flexible audio
2854362a6e2208117b98db169af9e03c082175af38Heidi Millerpath changes. When a System on Chip (SoC) implements the TV hardware abstraction layer (HAL), each
2954362a6e2208117b98db169af9e03c082175af38Heidi MillerTV input (HDMI IN, Tuner, etc.) provides <code>TvInputHardwareInfo</code> that specifies AudioPort information for audio type and address.</p>
3054362a6e2208117b98db169af9e03c082175af38Heidi Miller
3154362a6e2208117b98db169af9e03c082175af38Heidi Miller<ul>
3254362a6e2208117b98db169af9e03c082175af38Heidi Miller<li><b>Physical</b> audio input/output devices have a corresponding AudioPort.</li>
3354362a6e2208117b98db169af9e03c082175af38Heidi Miller<li><b>Software</b> audio output/input streams are represented as AudioMixPort (child class of
3454362a6e2208117b98db169af9e03c082175af38Heidi MillerAudioPort).</li>
3554362a6e2208117b98db169af9e03c082175af38Heidi Miller</ul>
3654362a6e2208117b98db169af9e03c082175af38Heidi Miller
3754362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>The TIF then uses AudioPort information for the audio routing API.</p>
3854362a6e2208117b98db169af9e03c082175af38Heidi Miller
3954362a6e2208117b98db169af9e03c082175af38Heidi Miller<p><img src="audio/images/ape_audio_tv_tif.png" alt="Android TV Input Framework (TIF)" />
4054362a6e2208117b98db169af9e03c082175af38Heidi Miller<p class="img-caption"><strong>Figure 1.</strong> TV Input Framework (TIF)</p>
4154362a6e2208117b98db169af9e03c082175af38Heidi Miller
4254362a6e2208117b98db169af9e03c082175af38Heidi Miller<h2 id="Requirements">Requirements</h2>
4354362a6e2208117b98db169af9e03c082175af38Heidi Miller
4454362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>A SoC must implement the audio HAL with the following audio routing API support:</p>
4554362a6e2208117b98db169af9e03c082175af38Heidi Miller
4654362a6e2208117b98db169af9e03c082175af38Heidi Miller<table>
4754362a6e2208117b98db169af9e03c082175af38Heidi Miller<tbody>
4854362a6e2208117b98db169af9e03c082175af38Heidi Miller<tr>
4954362a6e2208117b98db169af9e03c082175af38Heidi Miller<th>Audio Ports</th>
5054362a6e2208117b98db169af9e03c082175af38Heidi Miller<td>
5154362a6e2208117b98db169af9e03c082175af38Heidi Miller<ul>
5254362a6e2208117b98db169af9e03c082175af38Heidi Miller<li>TV Audio Input has a corresponding audio source port implementation.</li>
5354362a6e2208117b98db169af9e03c082175af38Heidi Miller<li>TV Audio Output has a corresponding audio sink port implementation.</li>
5454362a6e2208117b98db169af9e03c082175af38Heidi Miller<li>Can create audio patch between any TV input audio port and any TV output audio port.</li>
5554362a6e2208117b98db169af9e03c082175af38Heidi Miller</ul>
5654362a6e2208117b98db169af9e03c082175af38Heidi Miller</td>
5754362a6e2208117b98db169af9e03c082175af38Heidi Miller</tr>
5854362a6e2208117b98db169af9e03c082175af38Heidi Miller<tr>
5954362a6e2208117b98db169af9e03c082175af38Heidi Miller<th>Default Input</th>
6054362a6e2208117b98db169af9e03c082175af38Heidi Miller<td>AudioRecord (created with DEFAULT input source) must seize <i>virtual null input source</i> for
6154362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_DEFAULT acquisition on Android TV.</td>
6254362a6e2208117b98db169af9e03c082175af38Heidi Miller</tr>
6354362a6e2208117b98db169af9e03c082175af38Heidi Miller<tr>
6454362a6e2208117b98db169af9e03c082175af38Heidi Miller<th>Device Loopback</th>
6554362a6e2208117b98db169af9e03c082175af38Heidi Miller<td>Requires supporting an AUDIO_DEVICE_IN_LOOPBACK input that is a complete mix of all audio output
6654362a6e2208117b98db169af9e03c082175af38Heidi Millerof all the TV output (11Khz, 16bit mono or 48Khz, 16bit mono). Used only for audio capture.
6754362a6e2208117b98db169af9e03c082175af38Heidi Miller</td>
6854362a6e2208117b98db169af9e03c082175af38Heidi Miller</tr>
6954362a6e2208117b98db169af9e03c082175af38Heidi Miller</tbody>
7054362a6e2208117b98db169af9e03c082175af38Heidi Miller</table>
7154362a6e2208117b98db169af9e03c082175af38Heidi Miller
7254362a6e2208117b98db169af9e03c082175af38Heidi Miller
7354362a6e2208117b98db169af9e03c082175af38Heidi Miller<h2 id="Audio Devices">TV audio devices</h2>
7454362a6e2208117b98db169af9e03c082175af38Heidi Miller
7554362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>Android supports the following audio devices for TV audio input/output.</p>
7654362a6e2208117b98db169af9e03c082175af38Heidi Miller
7754362a6e2208117b98db169af9e03c082175af38Heidi Miller<h4>system/core/include/system/audio.h</h4>
7854362a6e2208117b98db169af9e03c082175af38Heidi Miller
7954362a6e2208117b98db169af9e03c082175af38Heidi Miller<pre>
8054362a6e2208117b98db169af9e03c082175af38Heidi Miller/* output devices */
8154362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_OUT_AUX_DIGITAL  = 0x400,
8254362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_OUT_HDMI   = AUDIO_DEVICE_OUT_AUX_DIGITAL,
8354362a6e2208117b98db169af9e03c082175af38Heidi Miller/* HDMI Audio Return Channel */
8454362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_OUT_HDMI_ARC   = 0x40000,
8554362a6e2208117b98db169af9e03c082175af38Heidi Miller/* S/PDIF out */
8654362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_OUT_SPDIF    = 0x80000,
8754362a6e2208117b98db169af9e03c082175af38Heidi Miller/* input devices */
8854362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_AUX_DIGITAL   = AUDIO_DEVICE_BIT_IN | 0x20,
8954362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_HDMI      = AUDIO_DEVICE_IN_AUX_DIGITAL,
9054362a6e2208117b98db169af9e03c082175af38Heidi Miller/* TV tuner input */
9154362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_TV_TUNER    = AUDIO_DEVICE_BIT_IN | 0x4000,
9254362a6e2208117b98db169af9e03c082175af38Heidi Miller/* S/PDIF in */
9354362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_SPDIF   = AUDIO_DEVICE_BIT_IN | 0x10000,
9454362a6e2208117b98db169af9e03c082175af38Heidi MillerAUDIO_DEVICE_IN_LOOPBACK    = AUDIO_DEVICE_BIT_IN | 0x40000,
9554362a6e2208117b98db169af9e03c082175af38Heidi Miller</pre>
9654362a6e2208117b98db169af9e03c082175af38Heidi Miller
9754362a6e2208117b98db169af9e03c082175af38Heidi Miller
9854362a6e2208117b98db169af9e03c082175af38Heidi Miller<h2 id="HAL extension">Audio HAL extension</h2>
9954362a6e2208117b98db169af9e03c082175af38Heidi Miller
10054362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>The Audio HAL extension for the audio routing API is defined by following:</p>
10154362a6e2208117b98db169af9e03c082175af38Heidi Miller
10254362a6e2208117b98db169af9e03c082175af38Heidi Miller<h4>system/core/include/system/audio.h</h4>
10354362a6e2208117b98db169af9e03c082175af38Heidi Miller
10454362a6e2208117b98db169af9e03c082175af38Heidi Miller<pre>
10554362a6e2208117b98db169af9e03c082175af38Heidi Miller/* audio port configuration structure used to specify a particular configuration of an audio port */
10654362a6e2208117b98db169af9e03c082175af38Heidi Millerstruct audio_port_config {
10754362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_handle_t      id;           /* port unique ID */
10854362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_role_t        role;         /* sink or source */
10954362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_type_t        type;         /* device, mix ... */
11054362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             config_mask;  /* e.g AUDIO_PORT_CONFIG_ALL */
11154362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             sample_rate;  /* sampling rate in Hz */
11254362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_channel_mask_t     channel_mask; /* channel mask if applicable */
11354362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_format_t           format;       /* format if applicable */
11454362a6e2208117b98db169af9e03c082175af38Heidi Miller    struct audio_gain_config gain;         /* gain to apply if applicable */
11554362a6e2208117b98db169af9e03c082175af38Heidi Miller    union {
11654362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_config_device_ext  device;  /* device specific info */
11754362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_config_mix_ext     mix;     /* mix specific info */
11854362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_config_session_ext session; /* session specific info */
11954362a6e2208117b98db169af9e03c082175af38Heidi Miller    } ext;
12054362a6e2208117b98db169af9e03c082175af38Heidi Miller};
12154362a6e2208117b98db169af9e03c082175af38Heidi Millerstruct audio_port {
12254362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_handle_t      id;                /* port unique ID */
12354362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_role_t        role;              /* sink or source */
12454362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_port_type_t        type;              /* device, mix ... */
12554362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             num_sample_rates;  /* number of sampling rates in following array */
12654362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
12754362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             num_channel_masks; /* number of channel masks in following array */
12854362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_channel_mask_t     channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS];
12954362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             num_formats;       /* number of formats in following array */
13054362a6e2208117b98db169af9e03c082175af38Heidi Miller    audio_format_t           formats[AUDIO_PORT_MAX_FORMATS];
13154362a6e2208117b98db169af9e03c082175af38Heidi Miller    unsigned int             num_gains;         /* number of gains in following array */
13254362a6e2208117b98db169af9e03c082175af38Heidi Miller    struct audio_gain        gains[AUDIO_PORT_MAX_GAINS];
13354362a6e2208117b98db169af9e03c082175af38Heidi Miller    struct audio_port_config active_config;     /* current audio port configuration */
13454362a6e2208117b98db169af9e03c082175af38Heidi Miller    union {
13554362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_device_ext  device;
13654362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_mix_ext     mix;
13754362a6e2208117b98db169af9e03c082175af38Heidi Miller        struct audio_port_session_ext session;
13854362a6e2208117b98db169af9e03c082175af38Heidi Miller    } ext;
13954362a6e2208117b98db169af9e03c082175af38Heidi Miller};
14054362a6e2208117b98db169af9e03c082175af38Heidi Miller</pre>
14154362a6e2208117b98db169af9e03c082175af38Heidi Miller
14254362a6e2208117b98db169af9e03c082175af38Heidi Miller<h4>hardware/libhardware/include/hardware/audio.h</h4>
14354362a6e2208117b98db169af9e03c082175af38Heidi Miller
14454362a6e2208117b98db169af9e03c082175af38Heidi Miller<pre>
14554362a6e2208117b98db169af9e03c082175af38Heidi Millerstruct audio_hw_device {
14654362a6e2208117b98db169af9e03c082175af38Heidi Miller  :
14754362a6e2208117b98db169af9e03c082175af38Heidi Miller    /**
14854362a6e2208117b98db169af9e03c082175af38Heidi Miller     * Routing control
14954362a6e2208117b98db169af9e03c082175af38Heidi Miller     */
15054362a6e2208117b98db169af9e03c082175af38Heidi Miller
15154362a6e2208117b98db169af9e03c082175af38Heidi Miller    /* Creates an audio patch between several source and sink ports.
15254362a6e2208117b98db169af9e03c082175af38Heidi Miller     * The handle is allocated by the HAL and should be unique for this
15354362a6e2208117b98db169af9e03c082175af38Heidi Miller     * audio HAL module. */
15454362a6e2208117b98db169af9e03c082175af38Heidi Miller    int (*create_audio_patch)(struct audio_hw_device *dev,
15554362a6e2208117b98db169af9e03c082175af38Heidi Miller                               unsigned int num_sources,
15654362a6e2208117b98db169af9e03c082175af38Heidi Miller                               const struct audio_port_config *sources,
15754362a6e2208117b98db169af9e03c082175af38Heidi Miller                               unsigned int num_sinks,
15854362a6e2208117b98db169af9e03c082175af38Heidi Miller                               const struct audio_port_config *sinks,
15954362a6e2208117b98db169af9e03c082175af38Heidi Miller                               audio_patch_handle_t *handle);
16054362a6e2208117b98db169af9e03c082175af38Heidi Miller
16154362a6e2208117b98db169af9e03c082175af38Heidi Miller    /* Release an audio patch */
16254362a6e2208117b98db169af9e03c082175af38Heidi Miller    int (*release_audio_patch)(struct audio_hw_device *dev,
16354362a6e2208117b98db169af9e03c082175af38Heidi Miller                               audio_patch_handle_t handle);
16454362a6e2208117b98db169af9e03c082175af38Heidi Miller
16554362a6e2208117b98db169af9e03c082175af38Heidi Miller    /* Fills the list of supported attributes for a given audio port.
16654362a6e2208117b98db169af9e03c082175af38Heidi Miller     * As input, "port" contains the information (type, role, address etc...)
16754362a6e2208117b98db169af9e03c082175af38Heidi Miller     * needed by the HAL to identify the port.
16854362a6e2208117b98db169af9e03c082175af38Heidi Miller     * As output, "port" contains possible attributes (sampling rates, formats,
16954362a6e2208117b98db169af9e03c082175af38Heidi Miller     * channel masks, gain controllers...) for this port.
17054362a6e2208117b98db169af9e03c082175af38Heidi Miller     */
17154362a6e2208117b98db169af9e03c082175af38Heidi Miller    int (*get_audio_port)(struct audio_hw_device *dev,
17254362a6e2208117b98db169af9e03c082175af38Heidi Miller                          struct audio_port *port);
17354362a6e2208117b98db169af9e03c082175af38Heidi Miller
17454362a6e2208117b98db169af9e03c082175af38Heidi Miller    /* Set audio port configuration */
17554362a6e2208117b98db169af9e03c082175af38Heidi Miller    int (*set_audio_port_config)(struct audio_hw_device *dev,
17654362a6e2208117b98db169af9e03c082175af38Heidi Miller                         const struct audio_port_config *config);
17754362a6e2208117b98db169af9e03c082175af38Heidi Miller</pre>
17854362a6e2208117b98db169af9e03c082175af38Heidi Miller
17954362a6e2208117b98db169af9e03c082175af38Heidi Miller<h2 id="Testing">Testing DEVICE_IN_LOOPBACK</h2>
18054362a6e2208117b98db169af9e03c082175af38Heidi Miller
18154362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>To test DEVICE_IN_LOOPBACK for TV monitoring, use the following testing code. After running the
18254362a6e2208117b98db169af9e03c082175af38Heidi Millertest, the captured audio saves to <code>/sdcard/record_loopback.raw</code>, where you can listen to
18354362a6e2208117b98db169af9e03c082175af38Heidi Millerit using <code>ffmeg</code>.</p>
18454362a6e2208117b98db169af9e03c082175af38Heidi Miller
18554362a6e2208117b98db169af9e03c082175af38Heidi Miller<pre>
18654362a6e2208117b98db169af9e03c082175af38Heidi Miller&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" /&gt;
18754362a6e2208117b98db169af9e03c082175af38Heidi Miller&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
18854362a6e2208117b98db169af9e03c082175af38Heidi Miller
18954362a6e2208117b98db169af9e03c082175af38Heidi Miller   AudioRecord mRecorder;
19054362a6e2208117b98db169af9e03c082175af38Heidi Miller   Handler mHandler = new Handler();
19154362a6e2208117b98db169af9e03c082175af38Heidi Miller   int mMinBufferSize = AudioRecord.getMinBufferSize(RECORD_SAMPLING_RATE,
19254362a6e2208117b98db169af9e03c082175af38Heidi Miller           AudioFormat.CHANNEL_IN_MONO,
19354362a6e2208117b98db169af9e03c082175af38Heidi Miller           AudioFormat.ENCODING_PCM_16BIT);;
19454362a6e2208117b98db169af9e03c082175af38Heidi Miller   static final int RECORD_SAMPLING_RATE = 48000;
19554362a6e2208117b98db169af9e03c082175af38Heidi Miller   public void doCapture() {
19654362a6e2208117b98db169af9e03c082175af38Heidi Miller       mRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, RECORD_SAMPLING_RATE,
19754362a6e2208117b98db169af9e03c082175af38Heidi Miller               AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mMinBufferSize * 10);
19854362a6e2208117b98db169af9e03c082175af38Heidi Miller       AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
19954362a6e2208117b98db169af9e03c082175af38Heidi Miller       ArrayList&lt;AudioPort&gt; audioPorts = new ArrayList&lt;AudioPort&gt;();
20054362a6e2208117b98db169af9e03c082175af38Heidi Miller       am.listAudioPorts(audioPorts);
20154362a6e2208117b98db169af9e03c082175af38Heidi Miller       AudioPortConfig srcPortConfig = null;
20254362a6e2208117b98db169af9e03c082175af38Heidi Miller       AudioPortConfig sinkPortConfig = null;
20354362a6e2208117b98db169af9e03c082175af38Heidi Miller       for (AudioPort audioPort : audioPorts) {
20454362a6e2208117b98db169af9e03c082175af38Heidi Miller           if (srcPortConfig == null
20554362a6e2208117b98db169af9e03c082175af38Heidi Miller                   && audioPort.role() == AudioPort.ROLE_SOURCE
20654362a6e2208117b98db169af9e03c082175af38Heidi Miller                   && audioPort instanceof AudioDevicePort) {
20754362a6e2208117b98db169af9e03c082175af38Heidi Miller               AudioDevicePort audioDevicePort = (AudioDevicePort) audioPort;
20854362a6e2208117b98db169af9e03c082175af38Heidi Miller               if (audioDevicePort.type() == AudioManager.DEVICE_IN_LOOPBACK) {
20954362a6e2208117b98db169af9e03c082175af38Heidi Miller                   srcPortConfig = audioPort.buildConfig(48000, AudioFormat.CHANNEL_IN_DEFAULT,
21054362a6e2208117b98db169af9e03c082175af38Heidi Miller                           AudioFormat.ENCODING_DEFAULT, null);
21154362a6e2208117b98db169af9e03c082175af38Heidi Miller                   Log.d(LOG_TAG, "Found loopback audio source port : " + audioPort);
21254362a6e2208117b98db169af9e03c082175af38Heidi Miller               }
21354362a6e2208117b98db169af9e03c082175af38Heidi Miller           }
21454362a6e2208117b98db169af9e03c082175af38Heidi Miller           else if (sinkPortConfig == null
21554362a6e2208117b98db169af9e03c082175af38Heidi Miller                   && audioPort.role() == AudioPort.ROLE_SINK
21654362a6e2208117b98db169af9e03c082175af38Heidi Miller                   && audioPort instanceof AudioMixPort) {
21754362a6e2208117b98db169af9e03c082175af38Heidi Miller               sinkPortConfig = audioPort.buildConfig(48000, AudioFormat.CHANNEL_OUT_DEFAULT,
21854362a6e2208117b98db169af9e03c082175af38Heidi Miller                       AudioFormat.ENCODING_DEFAULT, null);
21954362a6e2208117b98db169af9e03c082175af38Heidi Miller               Log.d(LOG_TAG, "Found recorder audio mix port : " + audioPort);
22054362a6e2208117b98db169af9e03c082175af38Heidi Miller           }
22154362a6e2208117b98db169af9e03c082175af38Heidi Miller       }
22254362a6e2208117b98db169af9e03c082175af38Heidi Miller       if (srcPortConfig != null && sinkPortConfig != null) {
22354362a6e2208117b98db169af9e03c082175af38Heidi Miller           AudioPatch[] patches = new AudioPatch[] { null };
22454362a6e2208117b98db169af9e03c082175af38Heidi Miller           int status = am.createAudioPatch(
22554362a6e2208117b98db169af9e03c082175af38Heidi Miller                   patches,
22654362a6e2208117b98db169af9e03c082175af38Heidi Miller                   new AudioPortConfig[] { srcPortConfig },
22754362a6e2208117b98db169af9e03c082175af38Heidi Miller                   new AudioPortConfig[] { sinkPortConfig });
22854362a6e2208117b98db169af9e03c082175af38Heidi Miller           Log.d(LOG_TAG, "Result of createAudioPatch(): " + status);
22954362a6e2208117b98db169af9e03c082175af38Heidi Miller       }
23054362a6e2208117b98db169af9e03c082175af38Heidi Miller       mRecorder.startRecording();
23154362a6e2208117b98db169af9e03c082175af38Heidi Miller       processAudioData();
23254362a6e2208117b98db169af9e03c082175af38Heidi Miller       mRecorder.stop();
23354362a6e2208117b98db169af9e03c082175af38Heidi Miller       mRecorder.release();
23454362a6e2208117b98db169af9e03c082175af38Heidi Miller   }
23554362a6e2208117b98db169af9e03c082175af38Heidi Miller   private void processAudioData() {
23654362a6e2208117b98db169af9e03c082175af38Heidi Miller       OutputStream rawFileStream = null;
23754362a6e2208117b98db169af9e03c082175af38Heidi Miller       byte data[] = new byte[mMinBufferSize];
23854362a6e2208117b98db169af9e03c082175af38Heidi Miller       try {
23954362a6e2208117b98db169af9e03c082175af38Heidi Miller           rawFileStream = new BufferedOutputStream(
24054362a6e2208117b98db169af9e03c082175af38Heidi Miller                   new FileOutputStream(new File("/sdcard/record_loopback.raw")));
24154362a6e2208117b98db169af9e03c082175af38Heidi Miller       } catch (FileNotFoundException e) {
24254362a6e2208117b98db169af9e03c082175af38Heidi Miller           Log.d(LOG_TAG, "Can't open file.", e);
24354362a6e2208117b98db169af9e03c082175af38Heidi Miller       }
24454362a6e2208117b98db169af9e03c082175af38Heidi Miller       long startTimeMs = System.currentTimeMillis();
24554362a6e2208117b98db169af9e03c082175af38Heidi Miller       while (System.currentTimeMillis() - startTimeMs &lt; 5000) {
24654362a6e2208117b98db169af9e03c082175af38Heidi Miller           int nbytes = mRecorder.read(data, 0, mMinBufferSize);
24754362a6e2208117b98db169af9e03c082175af38Heidi Miller           if (nbytes &lt;= 0) {
24854362a6e2208117b98db169af9e03c082175af38Heidi Miller               continue;
24954362a6e2208117b98db169af9e03c082175af38Heidi Miller           }
25054362a6e2208117b98db169af9e03c082175af38Heidi Miller           try {
25154362a6e2208117b98db169af9e03c082175af38Heidi Miller               rawFileStream.write(data);
25254362a6e2208117b98db169af9e03c082175af38Heidi Miller           } catch (IOException e) {
25354362a6e2208117b98db169af9e03c082175af38Heidi Miller               Log.e(LOG_TAG, "Error on writing raw file.", e);
25454362a6e2208117b98db169af9e03c082175af38Heidi Miller           }
25554362a6e2208117b98db169af9e03c082175af38Heidi Miller       }
25654362a6e2208117b98db169af9e03c082175af38Heidi Miller       try {
25754362a6e2208117b98db169af9e03c082175af38Heidi Miller           rawFileStream.close();
25854362a6e2208117b98db169af9e03c082175af38Heidi Miller       } catch (IOException e) {
25954362a6e2208117b98db169af9e03c082175af38Heidi Miller       }
26054362a6e2208117b98db169af9e03c082175af38Heidi Miller       Log.d(LOG_TAG, "Exit audio recording.");
26154362a6e2208117b98db169af9e03c082175af38Heidi Miller   }
26254362a6e2208117b98db169af9e03c082175af38Heidi Miller</pre>
26354362a6e2208117b98db169af9e03c082175af38Heidi Miller
26454362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>Locate the captured audio file in <code>/sdcard/record_loopback.raw</code> and listen to it using
26554362a6e2208117b98db169af9e03c082175af38Heidi Miller<code>ffmeg</code>:</p>
26654362a6e2208117b98db169af9e03c082175af38Heidi Miller
26754362a6e2208117b98db169af9e03c082175af38Heidi Miller<pre>
26854362a6e2208117b98db169af9e03c082175af38Heidi Milleradb pull /sdcard/record_loopback.raw
26954362a6e2208117b98db169af9e03c082175af38Heidi Millerffmpeg -f s16le -ar 48k -ac 1 -i record_loopback.raw record_loopback.wav
27054362a6e2208117b98db169af9e03c082175af38Heidi Millerffplay record_loopback.wav
27154362a6e2208117b98db169af9e03c082175af38Heidi Miller</pre>
27254362a6e2208117b98db169af9e03c082175af38Heidi Miller
27354362a6e2208117b98db169af9e03c082175af38Heidi Miller<h2 id="Use cases">Use cases</h2>
27454362a6e2208117b98db169af9e03c082175af38Heidi Miller
27554362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>This section includes common use cases for TV audio.</p>
27654362a6e2208117b98db169af9e03c082175af38Heidi Miller
27754362a6e2208117b98db169af9e03c082175af38Heidi Miller<h3>TV tuner with speaker output</h3>
27854362a6e2208117b98db169af9e03c082175af38Heidi Miller
27954362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>When a TV tuner becomes active, the audio routing API creates an audio patch between the tuner
28054362a6e2208117b98db169af9e03c082175af38Heidi Millerand the default output (e.g. the speaker). The tuner output does not require decoding, but final
28154362a6e2208117b98db169af9e03c082175af38Heidi Milleraudio output is mixed with software output_stream.</p>
28254362a6e2208117b98db169af9e03c082175af38Heidi Miller
28354362a6e2208117b98db169af9e03c082175af38Heidi Miller<p><img src="audio/images/ape_audio_tv_tuner.png" alt="Android TV Tuner Audio Patch" />
28454362a6e2208117b98db169af9e03c082175af38Heidi Miller<p class="img-caption">
28554362a6e2208117b98db169af9e03c082175af38Heidi Miller<strong>Figure 2.</strong> Audio Patch for TV tuner with speaker output.</p>
28654362a6e2208117b98db169af9e03c082175af38Heidi Miller
28754362a6e2208117b98db169af9e03c082175af38Heidi Miller
28854362a6e2208117b98db169af9e03c082175af38Heidi Miller<h3>HDMI OUT during live TV</h3>
28954362a6e2208117b98db169af9e03c082175af38Heidi Miller
29054362a6e2208117b98db169af9e03c082175af38Heidi Miller<p>A user is watching live TV then switches to the HDMI audio output (Intent.ACTION_HDMI_AUDIO_PLUG)
29154362a6e2208117b98db169af9e03c082175af38Heidi Miller. The output device of all output_streams changes to the HDMI_OUT port, and the TIF manager changes
29254362a6e2208117b98db169af9e03c082175af38Heidi Millerthe sink port of the existing tuner audio patch to the HDMI_OUT port.</p>
29354362a6e2208117b98db169af9e03c082175af38Heidi Miller
29454362a6e2208117b98db169af9e03c082175af38Heidi Miller<p><p><img src="audio/images/ape_audio_tv_hdmi_tuner.png" alt="Android TV HDMI-OUT Audio Patch" />
29554362a6e2208117b98db169af9e03c082175af38Heidi Miller<p class="img-caption">
29654362a6e2208117b98db169af9e03c082175af38Heidi Miller<strong>Figure 3.</strong> Audio Patch for HDMI OUT from live TV.</p>