hal: SSR support for pcm playback,pcm record usecases

- Added SSR event handling support in HAL

- Added support to drop incoming pcm data for pcm playback
  usecase during SSR

- Added support to send dummy input(mute/zero buffer) for
  record usecase during SSR

Change-Id: I158b62fa443bb523091128fe1308c9a9b1415502
This commit is contained in:
Naresh Tanniru 2014-05-12 01:05:52 +05:30
parent e1be46f950
commit 4c63039cfa
2 changed files with 120 additions and 4 deletions

View File

@ -790,6 +790,15 @@ int start_input_stream(struct stream_in *in)
ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
__func__, &in->stream, in->usecase, use_case_table[in->usecase]);
pthread_mutex_lock(&adev->snd_card_status.lock);
if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state) {
ALOGE("%s: sound card is not active/SSR returning error", __func__);
ret = -ENETRESET;
pthread_mutex_unlock(&adev->snd_card_status.lock);
goto error_config;
}
pthread_mutex_unlock(&adev->snd_card_status.lock);
/* Check if source matches incall recording usecase criteria */
ret = voice_check_and_set_incall_rec_usecase(adev, in);
if (ret)
@ -827,8 +836,11 @@ int start_input_stream(struct stream_in *in)
pcm_close(in->pcm);
in->pcm = NULL;
ret = -EIO;
in->pcm_error_type = PCM_ERROR_EIO;
goto error_open;
}
in->pcm_error_type = PCM_ERROR_NONE;
ALOGV("%s: exit", __func__);
return ret;
@ -1169,6 +1181,16 @@ int start_output_stream(struct stream_out *out)
ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
__func__, &out->stream, out->usecase, use_case_table[out->usecase],
out->devices);
pthread_mutex_lock(&adev->snd_card_status.lock);
if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state) {
ALOGE("%s: sound card is not active/SSR returning error", __func__);
ret = -ENETRESET;
pthread_mutex_unlock(&adev->snd_card_status.lock);
goto error_config;
}
pthread_mutex_unlock(&adev->snd_card_status.lock);
out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
if (out->pcm_device_id < 0) {
ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
@ -1215,8 +1237,10 @@ int start_output_stream(struct stream_out *out)
pcm_close(out->pcm);
out->pcm = NULL;
ret = -EIO;
out->pcm_error_type = PCM_ERROR_EIO;
goto error_open;
}
out->pcm_error_type = PCM_ERROR_NONE;
} else {
out->pcm = NULL;
out->compr = compress_open(adev->snd_card,
@ -1642,9 +1666,28 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
{
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = out->dev;
int scard_state = SND_CARD_STATE_ONLINE;
ssize_t ret = 0;
pthread_mutex_lock(&out->lock);
pthread_mutex_lock(&adev->snd_card_status.lock);
scard_state = adev->snd_card_status.state;
pthread_mutex_unlock(&adev->snd_card_status.lock);
if (out->pcm) {
if (SND_CARD_STATE_OFFLINE == scard_state) {
ALOGD(" %s: sound card is not active/SSR state", __func__);
ret= -ENETRESET;
goto exit;
} else if (PCM_ERROR_ENETRESET == out->pcm_error_type) {
ALOGD(" %s restarting pcm session on post SSR", __func__);
out->standby = false;
pthread_mutex_unlock(&out->lock);
out_standby(&out->stream.common);
pthread_mutex_lock(&out->lock);
}
}
if (out->standby) {
out->standby = false;
pthread_mutex_lock(&adev->lock);
@ -1693,6 +1736,15 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
}
exit:
if (-ENETRESET == ret) {
pthread_mutex_lock(&adev->snd_card_status.lock);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
out->pcm_error_type = PCM_ERROR_ENETRESET;
out->standby = true; /*standby will be called on post SSR */
pthread_mutex_unlock(&adev->snd_card_status.lock);
}
pthread_mutex_unlock(&out->lock);
if (ret != 0) {
@ -1700,7 +1752,8 @@ exit:
ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
out_standby(&out->stream.common);
usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
out_get_sample_rate(&out->stream.common));
out_get_sample_rate(&out->stream.common));
}
return bytes;
}
@ -2032,8 +2085,27 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
struct stream_in *in = (struct stream_in *)stream;
struct audio_device *adev = in->dev;
int i, ret = -1;
int scard_state = SND_CARD_STATE_ONLINE;
pthread_mutex_lock(&in->lock);
pthread_mutex_lock(&adev->snd_card_status.lock);
scard_state = adev->snd_card_status.state;
pthread_mutex_unlock(&adev->snd_card_status.lock);
if (in->pcm) {
if(SND_CARD_STATE_OFFLINE == scard_state) {
ALOGD(" %s: sound card is not active/SSR state", __func__);
ret= -ENETRESET;
goto exit;
} else if (PCM_ERROR_ENETRESET == in->pcm_error_type) {
ALOGD(" %s restarting pcm session on post SSR", __func__);
in->standby = false;
pthread_mutex_unlock(&in->lock);
in_standby(&in->stream.common);
pthread_mutex_lock(&in->lock);
}
}
if (in->standby) {
pthread_mutex_lock(&adev->lock);
if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
@ -2064,13 +2136,22 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
memset(buffer, 0, bytes);
exit:
if (-ENETRESET == ret) {
pthread_mutex_lock(&adev->snd_card_status.lock);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
in->pcm_error_type = PCM_ERROR_ENETRESET;
memset(buffer, 0, bytes);
in->standby = true; /*standby will be called on post SSR */
pthread_mutex_unlock(&adev->snd_card_status.lock);
}
pthread_mutex_unlock(&in->lock);
if (ret != 0) {
in_standby(&in->stream.common);
ALOGV("%s: read failed - sleeping for buffer duration", __func__);
usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
in_get_sample_rate(&in->stream.common));
in_get_sample_rate(&in->stream.common));
}
return bytes;
}
@ -2398,10 +2479,23 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
int ret = 0, err;
ALOGD("%s: enter: %s", __func__, kvpairs);
pthread_mutex_lock(&adev->lock);
parms = str_parms_create_str(kvpairs);
err = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
if (err >= 0) {
char *snd_card_status = value+2;
pthread_mutex_lock(&adev->snd_card_status.lock);
if (strstr(snd_card_status, "OFFLINE")) {
ALOGD("Received sound card OFFLINE status");
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
} else if (strstr(snd_card_status, "ONLINE")) {
ALOGD("Received sound card ONLINE status");
adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
}
pthread_mutex_unlock(&adev->snd_card_status.lock);
}
pthread_mutex_lock(&adev->lock);
ret = voice_set_parameters(adev, parms);
if (ret != 0)
goto done;
@ -2762,6 +2856,9 @@ static int adev_open(const hw_module_t *module, const char *name,
list_init(&adev->usecase_list);
adev->cur_wfd_channels = 2;
adev->offload_usecases_state = 0;
pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
/* Loads platform specific libraries dynamically */
adev->platform = platform_init(adev);
if (!adev->platform) {
@ -2773,6 +2870,8 @@ static int adev_open(const hw_module_t *module, const char *name,
return -EINVAL;
}
adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
if (adev->visualizer_lib == NULL) {

View File

@ -52,6 +52,8 @@
#define MAX_SUPPORTED_CHANNEL_MASKS 2
#define DEFAULT_HDMI_OUT_CHANNELS 2
#define SND_CARD_STATE_OFFLINE 0
#define SND_CARD_STATE_ONLINE 1
typedef int snd_device_t;
/* These are the supported use cases by the hardware.
@ -138,6 +140,12 @@ enum {
OFFLOAD_STATE_PAUSED,
};
enum {
PCM_ERROR_NONE,
PCM_ERROR_EIO,
PCM_ERROR_ENETRESET, /* For SSR */
};
struct offload_cmd {
struct listnode node;
int cmd;
@ -178,6 +186,7 @@ struct stream_out {
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
int pcm_error_type;
struct audio_device *dev;
};
@ -196,6 +205,7 @@ struct stream_in {
bool enable_aec;
bool enable_ns;
audio_format_t format;
int pcm_error_type;
struct audio_device *dev;
};
@ -223,6 +233,11 @@ struct audio_usecase {
union stream_ptr stream;
};
struct sound_card_status {
pthread_mutex_t lock;
int state;
};
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@ -251,6 +266,8 @@ struct audio_device {
void *offload_effects_lib;
int (*offload_effects_start_output)(audio_io_handle_t, int);
int (*offload_effects_stop_output)(audio_io_handle_t, int);
struct sound_card_status snd_card_status;
};
int select_devices(struct audio_device *adev,