audio: Avoid possible crashes [1/3]
PD#OTT-70004
Problem:
When the sound card is busy, a crash will occur
when it is used again.
Solution:
Perform the checking and print the necessary log
Verify:
zapper
Change-Id: I07f617464cb7f7b6a249bd36b18a1fbc9c3032d4
Signed-off-by: haiyang.ren <haiyang.ren@amlogic.com>
diff --git a/audio_hal/audio_hw.c b/audio_hal/audio_hw.c
index 6117b46..1ea81be 100644
--- a/audio_hal/audio_hw.c
+++ b/audio_hal/audio_hw.c
@@ -6320,7 +6320,7 @@
closed anymore, because its ref is bigger than 0.
Now we add this patch to make sure the alsa will be closed.
*/
- if ((!adev->useSubMix && (!ms12->dolby_ms12_enable && (eDolbyMS12Lib == adev->dolby_lib_type)))) {
+ if ((!adev->useSubMix || (!ms12->dolby_ms12_enable && (eDolbyMS12Lib == adev->dolby_lib_type)))) {
ALOGI("%s aml_out(%p)standby close", __func__, aml_out);
aml_audio_pcm_out_close(adev);
}
diff --git a/utils/tinyalsa/pcm.c b/utils/tinyalsa/pcm.c
index ae87aa2..a3b5724 100644
--- a/utils/tinyalsa/pcm.c
+++ b/utils/tinyalsa/pcm.c
@@ -127,11 +127,54 @@
#endif
};
+#define PCM_ERROR_MAX 128
+
+struct pcm {
+ int fd;
+ unsigned int flags;
+ int running:1;
+ int prepared:1;
+ int underruns;
+ unsigned int buffer_size;
+ unsigned int boundary;
+ char error[PCM_ERROR_MAX];
+ struct pcm_config config;
+ struct snd_pcm_mmap_status *mmap_status;
+ struct snd_pcm_mmap_control *mmap_control;
+ struct snd_pcm_sync_ptr *sync_ptr;
+ void *mmap_buffer;
+ unsigned int noirq_frames_per_msec;
+ int wait_for_avail_min;
+ unsigned int subdevice;
+};
+
/* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */
static const char * const subformat_lookup[] = {
"STD",
};
+static int oops(struct pcm *pcm, int e, const char *fmt, ...)
+{
+ va_list ap;
+ int sz;
+
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
+ va_end(ap);
+ sz = strlen(pcm->error);
+
+ if (e)
+ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
+ ": %s", strerror(e));
+ return -1;
+}
+
+
static inline int param_is_mask(int p)
{
return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
@@ -242,66 +285,44 @@
p->info = ~0U;
}
-#define PCM_ERROR_MAX 128
-
-struct pcm {
- int fd;
- unsigned int flags;
- int running:1;
- int prepared:1;
- int underruns;
- unsigned int buffer_size;
- unsigned int boundary;
- char error[PCM_ERROR_MAX];
- struct pcm_config config;
- struct snd_pcm_mmap_status *mmap_status;
- struct snd_pcm_mmap_control *mmap_control;
- struct snd_pcm_sync_ptr *sync_ptr;
- void *mmap_buffer;
- unsigned int noirq_frames_per_msec;
- int wait_for_avail_min;
- unsigned int subdevice;
-};
-
unsigned int pcm_get_buffer_size(struct pcm *pcm)
{
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return 0;
+ }
+
return pcm->buffer_size;
}
int pcm_get_config(struct pcm *pcm, struct pcm_config *config) {
- if (pcm == NULL) {
- return -1;
- }
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
*config = pcm->config;
return 0;
}
const char* pcm_get_error(struct pcm *pcm)
{
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return NULL;
+ }
+
return pcm->error;
}
unsigned int pcm_get_subdevice(struct pcm *pcm)
{
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return 0;
+ }
+
return pcm->subdevice;
}
-static int oops(struct pcm *pcm, int e, const char *fmt, ...)
-{
- va_list ap;
- int sz;
-
- va_start(ap, fmt);
- vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
- va_end(ap);
- sz = strlen(pcm->error);
-
- if (e)
- snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
- ": %s", strerror(e));
- return -1;
-}
-
static unsigned int pcm_format_to_alsa(enum pcm_format format)
{
switch (format) {
@@ -335,12 +356,22 @@
unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes)
{
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return 0;
+ }
+
return bytes / (pcm->config.channels *
(pcm_format_to_bits(pcm->config.format) >> 3));
}
unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames)
{
+ if (NULL == pcm) {
+ ALOGE("pcm was null pinter!");
+ return 0;
+ }
+
return frames * pcm->config.channels *
(pcm_format_to_bits(pcm->config.format) >> 3);
}
@@ -539,6 +570,10 @@
int frames;
int rc;
+ if (NULL == pcm) {
+ return oops(pcm, 0, "");
+ }
+
if (pcm == NULL || hw_ptr == NULL || tstamp == NULL)
return oops(pcm, EINVAL, "pcm %p, hw_ptr %p, tstamp %p", pcm, hw_ptr, tstamp);
@@ -569,6 +604,9 @@
{
struct snd_xferi x;
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if (pcm->flags & PCM_IN)
return -EINVAL;
@@ -608,6 +646,9 @@
{
struct snd_xferi x;
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if (!(pcm->flags & PCM_IN))
return -EINVAL;
@@ -915,7 +956,7 @@
int pcm_close(struct pcm *pcm)
{
- if (pcm == &bad_pcm)
+ if (NULL == pcm || pcm == &bad_pcm)
return 0;
pcm_hw_munmap_status(pcm);
@@ -1123,11 +1164,19 @@
int pcm_is_ready(struct pcm *pcm)
{
- return pcm->fd >= 0;
+ if (pcm) {
+ return pcm->fd >= 0;
+ } else {
+ ALOGE("pcm is not ready now!");
+ return 0;
+ }
}
int pcm_prepare(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if (pcm->prepared)
return 0;
@@ -1156,6 +1205,9 @@
int pcm_stop(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0)
return oops(pcm, errno, "cannot stop channel");
ALOGI("pcm_stop handle(%p)", pcm);
@@ -1188,6 +1240,9 @@
int pcm_mmap_avail(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
if (pcm->flags & PCM_IN)
return pcm_mmap_capture_avail(pcm);
@@ -1211,6 +1266,9 @@
{
unsigned int continuous, copy_frames, avail;
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
/* return the mmap buffer */
*areas = pcm->mmap_buffer;
@@ -1235,6 +1293,9 @@
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset __attribute__((unused)), unsigned int frames)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
/* update the application pointer in userspace and kernel */
pcm_mmap_appl_forward(pcm, frames);
pcm_sync_ptr(pcm, 0);
@@ -1244,12 +1305,18 @@
int pcm_avail_update(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
pcm_sync_ptr(pcm, 0);
return pcm_mmap_avail(pcm);
}
int pcm_state(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
int err = pcm_sync_ptr(pcm, 0);
if (err < 0)
return err;
@@ -1259,6 +1326,9 @@
int pcm_set_avail_min(struct pcm *pcm, int avail_min)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ))
return -ENOSYS;
@@ -1271,6 +1341,9 @@
struct pollfd pfd;
int err;
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
pfd.fd = pcm->fd;
pfd.events = POLLOUT | POLLERR | POLLNVAL;
@@ -1309,6 +1382,9 @@
int pcm_get_poll_fd(struct pcm *pcm)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
return pcm->fd;
}
@@ -1317,6 +1393,9 @@
int err = 0, frames, avail;
unsigned int offset = 0, count;
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if (bytes == 0)
return 0;
@@ -1402,6 +1481,9 @@
int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if ((~pcm->flags) & (PCM_OUT | PCM_MMAP))
return -ENOSYS;
@@ -1410,6 +1492,9 @@
int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count)
{
+ if (NULL == pcm)
+ return oops(pcm, 0, "");
+
if ((~pcm->flags) & (PCM_IN | PCM_MMAP))
return -ENOSYS;