Enable recording and playing on Android 4.4
Background since the beginning of ICS, the audio system has undergone great changes. First, alsalib has been abandoned, and then AIO has been adopted. All levels of frameworks have their own characteristics, it is a step away from the Linux Audio Application, forming its own unique audio management and audio configuration functions. In general, the improvement is still very large, at least in terms of user experience has greatly surpassed the previous version. We will analyze some of the changes and implementation mechanisms in the audio Implementation of 4.4.
Requirements
First, the hardware function is normal. This is not a table. Linux supports the alsa driver to generate the alsa subsystem. It is best to test the playing and recording of audio on other file systems such as buildroot in advance.
HAL is a simple implementation of HAL. For more information, see device/asus/grouper/audio. If there is no complicated audio configuration, you can modify it based on the code, it mainly involves some playback and recording parameters. This HAL has implemented common interfaces and called standard tinyalsa interfaces, which are highly portable. Here we use wm8904, which has few functions. You can use it directly.
Android Configuration
It mainly contains four files, audio_policy.conf media_profiles.xml media_codecs.xml mixer_paths.xml, which can be directly used without major changes.
In this case, the system should not use the default stub audio HAL, but the added audio HAL. However, most of them are not supported.
Debugging
The audio system calls several underlying libraries of libtinyalsa libaudioutils libaudioroute. Some general alsa devices have been transplanted to enable the configuration function, but the specific platform may not be able to run normally. The main reason is that these libraries are easy to implement and are not fully considered, their hardware details may be ignored by them. Similarly, we do not support time stamp for our wm8904, but tinyalsa must be turned off by default.
disable tstamp for wm8904. Change-Id: Ia22aa6ed39ede6214657487344d0488be93e5544diff --git a/pcm.c b/pcm.cindex 4501777..94cf6ee 100644--- a/pcm.c+++ b/pcm.c@@ -691,7 +691,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, memset(&sparams, 0, sizeof(sparams));- sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE; sparams.period_step = 1; if (!config->start_threshold) {
If the specific parameters are incorrect or inappropriate, the Android driver engineer needs to check the hardware design and chip manual one by one to configure the optimal working state of an audio system. So that the user experience can be the best.
Android audio system analysis is based on 4.4.2
Audio HAL
Tinyalsa and audiorouteAndroid audio systems are Linux-based ALSA drivers. tinyalsa encapsulates audio interfaces based on the alsa drivers and provides them to audio HAL and audio HAL to Android audioflinger and other frameworks. HAL needs to enable and disable the audio hardware (which android considers as hardware ).
static inline int audio_hw_device_open(const struct hw_module_t* module, struct audio_hw_device** device){ return module->methods->open(module, AUDIO_HARDWARE_INTERFACE, (struct hw_device_t**)device);}static inline int audio_hw_device_close(struct audio_hw_device* device){ return device->common.close(&device->common);}
Data Stream struct audio_stream_out struct audio_stream_in that needs to be implemented in and out
The in mainly includes the read method for reading audio data, and the out mainly includes the write method, which writes data to the device for recording and playing respectively. For details, see hardware/libhardware/include/hardware/audio. h.
The method is the called tinyalsa interface. The pcm operation is as follows:
/* Open and close a stream */struct pcm *pcm_open(unsigned int card, unsigned int device, unsigned int flags, struct pcm_config *config);int pcm_close(struct pcm *pcm);int pcm_is_ready(struct pcm *pcm);/* Obtain the parameters for a PCM */struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, unsigned int flags);void pcm_params_free(struct pcm_params *pcm_params);unsigned int pcm_params_get_min(struct pcm_params *pcm_params, enum pcm_param param);unsigned int pcm_params_get_max(struct pcm_params *pcm_params, enum pcm_param param);/* Set and get config */int pcm_get_config(struct pcm *pcm, struct pcm_config *config);int pcm_set_config(struct pcm *pcm, struct pcm_config *config);/* Returns a human readable reason for the last error */const char *pcm_get_error(struct pcm *pcm);/* Returns the sample size in bits for a PCM format. * As with ALSA formats, this is the storage size for the format, whereas the * format represents the number of significant bits. For example, * PCM_FORMAT_S24_LE uses 32 bits of storage. */unsigned int pcm_format_to_bits(enum pcm_format format);/* Returns the buffer size (int frames) that should be used for pcm_write. */unsigned int pcm_get_buffer_size(struct pcm *pcm);unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes);/* Returns the pcm latency in ms */unsigned int pcm_get_latency(struct pcm *pcm);/* Returns available frames in pcm buffer and corresponding time stamp. * The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open, * otherwise the clock is CLOCK_REALTIME. * For an input stream, frames available are frames ready for the * application to read. * For an output stream, frames available are the number of empty frames available * for the application to write. */int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, struct timespec *tstamp);/* Write data to the fifo. * Will start playback on the first write or on a write that * occurs after a fifo underrun. */int pcm_write(struct pcm *pcm, const void *data, unsigned int count);int pcm_read(struct pcm *pcm, void *data, unsigned int count);/* * mmap() support. */int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count);int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned int *frames);int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);/* Start and stop a PCM channel that doesn't transfer data */int pcm_start(struct pcm *pcm);int pcm_stop(struct pcm *pcm);/* Interrupt driven API */int pcm_wait(struct pcm *pcm, int timeout);/* Change avail_min after the stream has been opened with no need to stop the stream. * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags */int pcm_set_avail_min(struct pcm *pcm, int avail_min);
It is worth mentioning that HAL does not include the route operation, and audio route is handed over to libaudioroute. so, it also calls the tinyalsa interface and contains an xml parser to parse the route configuration data in mixer_paths.xml. In this way, the system can operate the pcm and mixer of alsa. In theory, the system should be able to play the audio. The tool provided by tinyalsa can be used for testing. Of course, the HAL interface cannot be tested. Tinycap tinymix tinypcminfo tinyplay
Tinyplay can play pure audio data in wav format. Tinymix allows you to view and configure the audio path:
root@sama5d3:/ # tinymix Mixer name: 'wm8904 @ SAMA5D3EK'Number of controls: 41ctl type num name value0 INT 1 EQ1 Volume 121 INT 1 EQ2 Volume 122 INT 1 EQ3 Volume 123 INT 1 EQ4 Volume 124 INT 1 EQ5 Volume 125 INT 2 Digital Capture Volume 96 966 ENUM 1 Left Caputure Mode Single-Ended7 ENUM 1 Right Capture Mode Single-Ended8 INT 2 Capture Volume 5 59 BOOL 2 Capture Switch Off Off10 BOOL 1 High Pass Filter Switch On11 ENUM 1 High Pass Filter Mode Hi-fi12 BOOL 1 ADC 128x OSR Switch On13 INT 1 Digital Playback Boost Volume 014 INT 2 Digital Playback Volume 96 9615 INT 2 Headphone Volume 45 4516 BOOL 2 Headphone Switch On On17 BOOL 2 Headphone ZC Switch On On18 INT 2 Line Output Volume 57 5719 BOOL 2 Line Output Switch On On20 BOOL 2 Line Output ZC Switch On On21 BOOL 1 EQ Switch Off22 BOOL 1 DRC Switch Off23 ENUM 1 DRC Path ADC24 BOOL 1 DAC OSRx2 Switch Off25 BOOL 1 DAC Deemphasis Switch Off26 INT 2 Digital Sidetone Volume 0 027 ENUM 1 LINER Mux DAC28 ENUM 1 LINEL Mux DAC29 ENUM 1 HPR Mux DAC30 ENUM 1 HPL Mux DAC31 ENUM 1 Right Sidetone None32 ENUM 1 Left Sidetone None33 ENUM 1 DACR Mux Right34 ENUM 1 DACL Mux Left35 ENUM 1 AIFOUTR Mux Right36 ENUM 1 AIFOUTL Mux Left37 ENUM 1 Right Capture Inverting Mux IN1R38 ENUM 1 Right Capture Mux IN2R39 ENUM 1 Left Capture Inverting Mux IN1L40 ENUM 1 Left Capture Mux IN2L
Audioflinger
Audioflinger is an audio server that loads audio hal and processes audio requests from the audio application. This analysis has a lot, refer to the following: http://blog.csdn.net/DroidPhone/article/details/5941344