Loading hal/audio_extn/a2dp.c +113 −116 Original line number Original line Diff line number Diff line Loading @@ -255,7 +255,7 @@ typedef enum { // --- external function dependency --- // --- external function dependency --- fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_check_a2dp_restore_t fp_check_a2dp_restore; fp_check_a2dp_restore_t fp_check_a2dp_restore_l; /* PCM config for ABR Feedback hostless front end */ /* PCM config for ABR Feedback hostless front end */ static struct pcm_config pcm_config_abr = { static struct pcm_config pcm_config_abr = { Loading Loading @@ -2872,7 +2872,9 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) #endif #endif ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value)); ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value)); if (ret >= 0) { if (ret >= 0) { if (a2dp.bt_lib_source_handle) { if (a2dp.bt_lib_source_handle == NULL) goto param_handled; if ((!strncmp(value, "true", sizeof(value)))) { if ((!strncmp(value, "true", sizeof(value)))) { if (a2dp.a2dp_source_suspended) { if (a2dp.a2dp_source_suspended) { ALOGD("%s: A2DP is already suspended", __func__); ALOGD("%s: A2DP is already suspended", __func__); Loading @@ -2888,9 +2890,7 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP || (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)) { uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)) { pthread_mutex_unlock(&a2dp.adev->lock); fp_check_a2dp_restore_l(a2dp.adev, uc_info->stream.out, false); fp_check_a2dp_restore(a2dp.adev, uc_info->stream.out, false); pthread_mutex_lock(&a2dp.adev->lock); } } } } if (!a2dp.swb_configured) if (!a2dp.swb_configured) Loading Loading @@ -2929,10 +2929,7 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) uc_info = node_to_item(node, struct audio_usecase, list); uc_info = node_to_item(node, struct audio_usecase, list); if (uc_info->stream.out && uc_info->type == PCM_PLAYBACK && if (uc_info->stream.out && uc_info->type == PCM_PLAYBACK && is_a2dp_out_device_type(&uc_info->stream.out->device_list)) { is_a2dp_out_device_type(&uc_info->stream.out->device_list)) { pthread_mutex_unlock(&a2dp.adev->lock); fp_check_a2dp_restore_l(a2dp.adev, uc_info->stream.out, true); fp_check_a2dp_restore(a2dp.adev, uc_info->stream.out, true); pthread_mutex_lock(&a2dp.adev->lock); } } } } } } } Loading Loading @@ -3022,7 +3019,7 @@ void a2dp_init(void *adev, // init function pointers // init function pointers fp_platform_get_pcm_device_id = fp_platform_get_pcm_device_id = init_config.fp_platform_get_pcm_device_id; init_config.fp_platform_get_pcm_device_id; fp_check_a2dp_restore = init_config.fp_check_a2dp_restore; fp_check_a2dp_restore_l = init_config.fp_check_a2dp_restore_l; reset_a2dp_enc_config_params(); reset_a2dp_enc_config_params(); reset_a2dp_source_dec_config_params(); reset_a2dp_source_dec_config_params(); Loading hal/audio_extn/audio_extn.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4750,7 +4750,7 @@ void audio_extn_a2dp_init(void *adev) if (a2dp_init) { if (a2dp_init) { a2dp_offload_init_config_t a2dp_init_config; a2dp_offload_init_config_t a2dp_init_config; a2dp_init_config.fp_platform_get_pcm_device_id = platform_get_pcm_device_id; a2dp_init_config.fp_platform_get_pcm_device_id = platform_get_pcm_device_id; a2dp_init_config.fp_check_a2dp_restore = check_a2dp_restore; a2dp_init_config.fp_check_a2dp_restore_l = check_a2dp_restore_l; a2dp_init(adev, a2dp_init_config); a2dp_init(adev, a2dp_init_config); } } Loading hal/audio_extn/audio_extn.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -337,7 +337,7 @@ typedef int (*fp_check_a2dp_restore_t)(struct audio_device *, struct stream_out *, bool); struct stream_out *, bool); struct a2dp_offload_init_config { struct a2dp_offload_init_config { fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_check_a2dp_restore_t fp_check_a2dp_restore; fp_check_a2dp_restore_t fp_check_a2dp_restore_l; }; }; typedef struct a2dp_offload_init_config a2dp_offload_init_config_t; typedef struct a2dp_offload_init_config a2dp_offload_init_config_t; // END: A2DP_OFFLOAD FEATURE ==================================================== // END: A2DP_OFFLOAD FEATURE ==================================================== Loading hal/audio_hw.c +79 −56 Original line number Original line Diff line number Diff line Loading @@ -516,7 +516,6 @@ static unsigned int audio_device_ref_count; //cache last MBDRC cal step level //cache last MBDRC cal step level static int last_known_cal_step = -1 ; static int last_known_cal_step = -1 ; static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore); static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right); static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right); static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right); static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right); static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right); static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right); Loading Loading @@ -3383,7 +3382,7 @@ static int send_offload_cmd_l(struct stream_out* out, int command) return 0; return 0; } } /* must be called iwth out->lock locked */ /* must be called with out->lock and latch lock */ static void stop_compressed_output_l(struct stream_out *out) static void stop_compressed_output_l(struct stream_out *out) { { out->offload_state = OFFLOAD_STATE_IDLE; out->offload_state = OFFLOAD_STATE_IDLE; Loading Loading @@ -3644,9 +3643,11 @@ static int create_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) { { lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); pthread_join(out->offload_thread, (void **) NULL); pthread_join(out->offload_thread, (void **) NULL); pthread_cond_destroy(&out->offload_cond); pthread_cond_destroy(&out->offload_cond); Loading Loading @@ -3721,6 +3722,9 @@ static int stop_output_stream(struct stream_out *out) list_remove(&uc_info->list); list_remove(&uc_info->list); out->started = 0; out->started = 0; pthread_mutex_lock(&out->latch_lock); out->muted = false; pthread_mutex_unlock(&out->latch_lock); if (is_offload_usecase(out->usecase) && if (is_offload_usecase(out->usecase) && (audio_extn_passthru_is_passthrough_stream(out))) { (audio_extn_passthru_is_passthrough_stream(out))) { ALOGV("Disable passthrough , reset mixer to pcm"); ALOGV("Disable passthrough , reset mixer to pcm"); Loading Loading @@ -4541,8 +4545,11 @@ static int out_standby(struct audio_stream *stream) if (adev->adm_deregister_stream) if (adev->adm_deregister_stream) adev->adm_deregister_stream(adev->adm_data, out->handle); adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); out->standby = true; out->standby = true; Loading Loading @@ -4616,7 +4623,9 @@ static int out_on_error(struct audio_stream *stream) // is needed e.g. when SSR happens within compress_open // is needed e.g. when SSR happens within compress_open // since the stream is active, offload_callback_thread is also active. // since the stream is active, offload_callback_thread is also active. if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } } pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); Loading Loading @@ -4654,8 +4663,11 @@ int out_standby_l(struct audio_stream *stream) if (adev->adm_deregister_stream) if (adev->adm_deregister_stream) adev->adm_deregister_stream(adev->adm_data, out->handle); adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } out->standby = true; out->standby = true; if (out->usecase == USECASE_COMPRESS_VOIP_CALL) { if (out->usecase == USECASE_COMPRESS_VOIP_CALL) { Loading Loading @@ -5002,12 +5014,13 @@ int route_output_stream(struct stream_out *out, audio_extn_perf_lock_release(&adev->perf_lock_handle); audio_extn_perf_lock_release(&adev->perf_lock_handle); } } if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && out->a2dp_compress_mute && (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) { (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) { pthread_mutex_lock(&out->compr_mute_lock); pthread_mutex_lock(&out->latch_lock); if (out->a2dp_compress_mute) { out->a2dp_compress_mute = false; out->a2dp_compress_mute = false; out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); pthread_mutex_unlock(&out->compr_mute_lock); } pthread_mutex_unlock(&out->latch_lock); } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); } } Loading Loading @@ -5562,7 +5575,9 @@ static int out_set_volume(struct audio_stream_out *stream, float left, ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right); ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right); if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) { if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) { /* only take left channel into account: the API is for stereo anyway */ /* only take left channel into account: the API is for stereo anyway */ pthread_mutex_lock(&out->latch_lock); out->muted = (left == 0.0f); out->muted = (left == 0.0f); pthread_mutex_unlock(&out->latch_lock); return 0; return 0; } else if (is_offload_usecase(out->usecase)) { } else if (is_offload_usecase(out->usecase)) { if (audio_extn_passthru_is_passthrough_stream(out)) { if (audio_extn_passthru_is_passthrough_stream(out)) { Loading Loading @@ -5599,18 +5614,20 @@ static int out_set_volume(struct audio_stream_out *stream, float left, out->volume_r = out_ctxt->output->volume_r; out->volume_r = out_ctxt->output->volume_r; } } } } pthread_mutex_lock(&out->latch_lock); if (!out->a2dp_compress_mute) { if (!out->a2dp_compress_mute) { ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); } } pthread_mutex_unlock(&out->latch_lock); return ret; return ret; } else { } else { pthread_mutex_lock(&out->compr_mute_lock); pthread_mutex_lock(&out->latch_lock); ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute); ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute); if (!out->a2dp_compress_mute) if (!out->a2dp_compress_mute) ret = out_set_compr_volume(stream, left, right); ret = out_set_compr_volume(stream, left, right); out->volume_l = left; out->volume_l = left; out->volume_r = right; out->volume_r = right; pthread_mutex_unlock(&out->compr_mute_lock); pthread_mutex_unlock(&out->latch_lock); return ret; return ret; } } } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { Loading Loading @@ -6021,7 +6038,9 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } } audio_extn_dts_eagle_fade(adev, true, out); audio_extn_dts_eagle_fade(adev, true, out); out->playback_started = 1; out->playback_started = 1; pthread_mutex_lock(&out->latch_lock); out->offload_state = OFFLOAD_STATE_PLAYING; out->offload_state = OFFLOAD_STATE_PLAYING; pthread_mutex_unlock(&out->latch_lock); audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, popcount(out->channel_mask), popcount(out->channel_mask), Loading @@ -6033,8 +6052,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } else { } else { if (out->pcm) { if (out->pcm) { size_t bytes_to_write = bytes; size_t bytes_to_write = bytes; pthread_mutex_lock(&out->latch_lock); if (out->muted) if (out->muted) memset((void *)buffer, 0, bytes); memset((void *)buffer, 0, bytes); pthread_mutex_unlock(&out->latch_lock); ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu", ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu", __func__, frames, frame_size, bytes_to_write); __func__, frames, frame_size, bytes_to_write); Loading Loading @@ -6408,6 +6429,7 @@ static int out_pause(struct audio_stream_out* stream) ALOGD("copl(%p):pause compress driver", out); ALOGD("copl(%p):pause compress driver", out); status = -ENODATA; status = -ENODATA; lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { if (out->card_status != CARD_STATUS_OFFLINE) if (out->card_status != CARD_STATUS_OFFLINE) status = compress_pause(out->compr); status = compress_pause(out->compr); Loading @@ -6424,6 +6446,7 @@ static int out_pause(struct audio_stream_out* stream) out->sample_rate, popcount(out->channel_mask), out->sample_rate, popcount(out->channel_mask), 0); 0); } } pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); } } return status; return status; Loading @@ -6438,6 +6461,7 @@ static int out_resume(struct audio_stream_out* stream) ALOGD("copl(%p):resume compress driver", out); ALOGD("copl(%p):resume compress driver", out); status = -ENODATA; status = -ENODATA; lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->card_status != CARD_STATUS_OFFLINE) { if (out->card_status != CARD_STATUS_OFFLINE) { status = compress_resume(out->compr); status = compress_resume(out->compr); Loading @@ -6449,6 +6473,7 @@ static int out_resume(struct audio_stream_out* stream) audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, popcount(out->channel_mask), 1); popcount(out->channel_mask), 1); } } pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); } } return status; return status; Loading Loading @@ -6477,12 +6502,14 @@ static int out_flush(struct audio_stream_out* stream) if (is_offload_usecase(out->usecase)) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%p):calling compress flush", out); ALOGD("copl(%p):calling compress flush", out); lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->offload_state == OFFLOAD_STATE_PAUSED) { stop_compressed_output_l(out); stop_compressed_output_l(out); } else { } else { ALOGW("%s called in invalid state %d", __func__, out->offload_state); ALOGW("%s called in invalid state %d", __func__, out->offload_state); } } out->written = 0; out->written = 0; pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); ALOGD("copl(%p):out of compress flush", out); ALOGD("copl(%p):out of compress flush", out); return 0; return 0; Loading Loading @@ -7757,7 +7784,7 @@ int adev_open_output_stream(struct audio_hw_device *dev, pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL); pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL); pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL); Loading Loading @@ -8672,6 +8699,9 @@ void adev_close_output_stream(struct audio_hw_device *dev __unused, pthread_cond_destroy(&out->cond); pthread_cond_destroy(&out->cond); pthread_mutex_destroy(&out->lock); pthread_mutex_destroy(&out->lock); pthread_mutex_destroy(&out->pre_lock); pthread_mutex_destroy(&out->latch_lock); pthread_mutex_destroy(&out->position_query_lock); pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle); streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle); Loading Loading @@ -8895,31 +8925,31 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) if (is_a2dp_out_device_type(&usecase->device_list)) { if (is_a2dp_out_device_type(&usecase->device_list)) { ALOGD("reconfigure a2dp... forcing device switch"); ALOGD("reconfigure a2dp... forcing device switch"); pthread_mutex_unlock(&adev->lock); lock_output_stream(usecase->stream.out); pthread_mutex_lock(&adev->lock); audio_extn_a2dp_set_handoff_mode(true); audio_extn_a2dp_set_handoff_mode(true); ALOGD("Switching to speaker and muting the stream before select_devices"); ALOGD("Switching to speaker and muting the stream before select_devices"); check_a2dp_restore_l(adev, usecase->stream.out, false); check_a2dp_restore_l(adev, usecase->stream.out, false); //force device switch to re configure encoder //force device switch to re configure encoder select_devices(adev, usecase->id); select_devices(adev, usecase->id); ALOGD("Unmuting the stream after select_devices"); ALOGD("Unmuting the stream after select_devices"); pthread_mutex_lock(&usecase->stream.out->latch_lock); usecase->stream.out->a2dp_compress_mute = false; usecase->stream.out->a2dp_compress_mute = false; out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r); out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r); pthread_mutex_unlock(&usecase->stream.out->latch_lock); audio_extn_a2dp_set_handoff_mode(false); audio_extn_a2dp_set_handoff_mode(false); pthread_mutex_unlock(&usecase->stream.out->lock); break; break; } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { usecase->stream.out->a2dp_compress_mute) { pthread_mutex_lock(&usecase->stream.out->latch_lock); pthread_mutex_unlock(&adev->lock); if (usecase->stream.out->a2dp_compress_mute) { lock_output_stream(usecase->stream.out); pthread_mutex_unlock(&usecase->stream.out->latch_lock); pthread_mutex_lock(&adev->lock); reassign_device_list(&usecase->stream.out->device_list, reassign_device_list(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, ""); AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, ""); check_a2dp_restore_l(adev, usecase->stream.out, true); check_a2dp_restore_l(adev, usecase->stream.out, true); pthread_mutex_unlock(&usecase->stream.out->lock); break; break; } } pthread_mutex_unlock(&usecase->stream.out->latch_lock); } } } } } Loading Loading @@ -9745,6 +9775,9 @@ static void adev_close_input_stream(struct audio_hw_device *dev, } else } else in_standby(&stream->common); in_standby(&stream->common); pthread_mutex_destroy(&in->lock); pthread_mutex_destroy(&in->pre_lock); pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); if (in->usecase == USECASE_AUDIO_RECORD) { if (in->usecase == USECASE_AUDIO_RECORD) { adev->pcm_record_uc_state = 0; adev->pcm_record_uc_state = 0; Loading Loading @@ -10349,8 +10382,8 @@ static void adev_snd_mon_cb(void *cookie, struct str_parms *parms) return; return; } } /* out and adev lock held */ /* adev lock held */ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore) int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore) { { struct audio_usecase *uc_info; struct audio_usecase *uc_info; float left_p; float left_p; Loading @@ -10369,23 +10402,26 @@ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *ou out->usecase, use_case_table[out->usecase]); out->usecase, use_case_table[out->usecase]); if (restore) { if (restore) { pthread_mutex_lock(&out->latch_lock); // restore A2DP device for active usecases and unmute if required // restore A2DP device for active usecases and unmute if required if (is_a2dp_out_device_type(&out->device_list)) { if (is_a2dp_out_device_type(&out->device_list)) { ALOGD("%s: restoring A2dp and unmuting stream", __func__); ALOGD("%s: restoring A2dp and unmuting stream", __func__); if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP) if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP) select_devices(adev, uc_info->id); select_devices(adev, uc_info->id); pthread_mutex_lock(&out->compr_mute_lock); if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) { (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) { if (out->a2dp_compress_mute) { out->a2dp_compress_mute = false; out->a2dp_compress_mute = false; out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); } } pthread_mutex_unlock(&out->compr_mute_lock); } } } out->muted = false; pthread_mutex_unlock(&out->latch_lock); } else { } else { pthread_mutex_lock(&out->latch_lock); if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { // mute compress stream if suspended // mute compress stream if suspended pthread_mutex_lock(&out->compr_mute_lock); if (!out->a2dp_compress_mute && !out->standby) { if (!out->a2dp_compress_mute && !out->standby) { ALOGD("%s: selecting speaker and muting stream", __func__); ALOGD("%s: selecting speaker and muting stream", __func__); assign_devices(&devices, &out->device_list); assign_devices(&devices, &out->device_list); Loading @@ -10403,31 +10439,18 @@ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *ou out->volume_l = left_p; out->volume_l = left_p; out->volume_r = right_p; out->volume_r = right_p; } } pthread_mutex_unlock(&out->compr_mute_lock); } else { } else { // tear down a2dp path for non offloaded streams // mute for non offloaded streams if (audio_extn_a2dp_source_is_suspended()) if (audio_extn_a2dp_source_is_suspended()) { out_standby_l(&out->stream.common); out->muted = true; } } } pthread_mutex_unlock(&out->latch_lock); } } ALOGV("%s: exit", __func__); ALOGV("%s: exit", __func__); return 0; return 0; } } int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore) { int ret = 0; lock_output_stream(out); pthread_mutex_lock(&adev->lock); ret = check_a2dp_restore_l(adev, out, restore); pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); return ret; } void adev_on_battery_status_changed(bool charging) void adev_on_battery_status_changed(bool charging) { { pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); Loading hal/audio_hw.h +8 −3 Original line number Original line Diff line number Diff line Loading @@ -364,13 +364,18 @@ struct stream_inout { stream_callback_t client_callback; stream_callback_t client_callback; void *client_cookie; void *client_cookie; }; }; struct stream_out { struct stream_out { struct audio_stream_out stream; struct audio_stream_out stream; pthread_mutex_t lock; /* see note below on mutex acquisition order */ pthread_mutex_t lock; /* see note below on mutex acquisition order */ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ pthread_mutex_t compr_mute_lock; /* acquire before setting compress volume */ pthread_mutex_t position_query_lock; /* acquire before updating/getting position of track offload*/ pthread_cond_t cond; pthread_cond_t cond; /* stream_out->lock is of large granularity, and can only be held before device lock * latch is a supplemetary lock to protect certain fields of out stream and * it can be held after device lock */ pthread_mutex_t latch_lock; pthread_mutex_t position_query_lock; /* sychronize frame written */ struct pcm_config config; struct pcm_config config; struct compr_config compr_config; struct compr_config compr_config; struct pcm *pcm; struct pcm *pcm; Loading Loading @@ -780,7 +785,7 @@ int pcm_ioctl(struct pcm *pcm, int request, ...); audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev, audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev, usecase_type_t type); usecase_type_t type); int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore); int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore); int adev_open_output_stream(struct audio_hw_device *dev, int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_io_handle_t handle, Loading Loading
hal/audio_extn/a2dp.c +113 −116 Original line number Original line Diff line number Diff line Loading @@ -255,7 +255,7 @@ typedef enum { // --- external function dependency --- // --- external function dependency --- fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_check_a2dp_restore_t fp_check_a2dp_restore; fp_check_a2dp_restore_t fp_check_a2dp_restore_l; /* PCM config for ABR Feedback hostless front end */ /* PCM config for ABR Feedback hostless front end */ static struct pcm_config pcm_config_abr = { static struct pcm_config pcm_config_abr = { Loading Loading @@ -2872,7 +2872,9 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) #endif #endif ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value)); ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value)); if (ret >= 0) { if (ret >= 0) { if (a2dp.bt_lib_source_handle) { if (a2dp.bt_lib_source_handle == NULL) goto param_handled; if ((!strncmp(value, "true", sizeof(value)))) { if ((!strncmp(value, "true", sizeof(value)))) { if (a2dp.a2dp_source_suspended) { if (a2dp.a2dp_source_suspended) { ALOGD("%s: A2DP is already suspended", __func__); ALOGD("%s: A2DP is already suspended", __func__); Loading @@ -2888,9 +2890,7 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP || (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP || uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)) { uc_info->out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)) { pthread_mutex_unlock(&a2dp.adev->lock); fp_check_a2dp_restore_l(a2dp.adev, uc_info->stream.out, false); fp_check_a2dp_restore(a2dp.adev, uc_info->stream.out, false); pthread_mutex_lock(&a2dp.adev->lock); } } } } if (!a2dp.swb_configured) if (!a2dp.swb_configured) Loading Loading @@ -2929,10 +2929,7 @@ int a2dp_set_parameters(struct str_parms *parms, bool *reconfig) uc_info = node_to_item(node, struct audio_usecase, list); uc_info = node_to_item(node, struct audio_usecase, list); if (uc_info->stream.out && uc_info->type == PCM_PLAYBACK && if (uc_info->stream.out && uc_info->type == PCM_PLAYBACK && is_a2dp_out_device_type(&uc_info->stream.out->device_list)) { is_a2dp_out_device_type(&uc_info->stream.out->device_list)) { pthread_mutex_unlock(&a2dp.adev->lock); fp_check_a2dp_restore_l(a2dp.adev, uc_info->stream.out, true); fp_check_a2dp_restore(a2dp.adev, uc_info->stream.out, true); pthread_mutex_lock(&a2dp.adev->lock); } } } } } } } Loading Loading @@ -3022,7 +3019,7 @@ void a2dp_init(void *adev, // init function pointers // init function pointers fp_platform_get_pcm_device_id = fp_platform_get_pcm_device_id = init_config.fp_platform_get_pcm_device_id; init_config.fp_platform_get_pcm_device_id; fp_check_a2dp_restore = init_config.fp_check_a2dp_restore; fp_check_a2dp_restore_l = init_config.fp_check_a2dp_restore_l; reset_a2dp_enc_config_params(); reset_a2dp_enc_config_params(); reset_a2dp_source_dec_config_params(); reset_a2dp_source_dec_config_params(); Loading
hal/audio_extn/audio_extn.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4750,7 +4750,7 @@ void audio_extn_a2dp_init(void *adev) if (a2dp_init) { if (a2dp_init) { a2dp_offload_init_config_t a2dp_init_config; a2dp_offload_init_config_t a2dp_init_config; a2dp_init_config.fp_platform_get_pcm_device_id = platform_get_pcm_device_id; a2dp_init_config.fp_platform_get_pcm_device_id = platform_get_pcm_device_id; a2dp_init_config.fp_check_a2dp_restore = check_a2dp_restore; a2dp_init_config.fp_check_a2dp_restore_l = check_a2dp_restore_l; a2dp_init(adev, a2dp_init_config); a2dp_init(adev, a2dp_init_config); } } Loading
hal/audio_extn/audio_extn.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -337,7 +337,7 @@ typedef int (*fp_check_a2dp_restore_t)(struct audio_device *, struct stream_out *, bool); struct stream_out *, bool); struct a2dp_offload_init_config { struct a2dp_offload_init_config { fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id; fp_check_a2dp_restore_t fp_check_a2dp_restore; fp_check_a2dp_restore_t fp_check_a2dp_restore_l; }; }; typedef struct a2dp_offload_init_config a2dp_offload_init_config_t; typedef struct a2dp_offload_init_config a2dp_offload_init_config_t; // END: A2DP_OFFLOAD FEATURE ==================================================== // END: A2DP_OFFLOAD FEATURE ==================================================== Loading
hal/audio_hw.c +79 −56 Original line number Original line Diff line number Diff line Loading @@ -516,7 +516,6 @@ static unsigned int audio_device_ref_count; //cache last MBDRC cal step level //cache last MBDRC cal step level static int last_known_cal_step = -1 ; static int last_known_cal_step = -1 ; static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore); static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right); static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right); static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right); static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right); static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right); static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right); Loading Loading @@ -3383,7 +3382,7 @@ static int send_offload_cmd_l(struct stream_out* out, int command) return 0; return 0; } } /* must be called iwth out->lock locked */ /* must be called with out->lock and latch lock */ static void stop_compressed_output_l(struct stream_out *out) static void stop_compressed_output_l(struct stream_out *out) { { out->offload_state = OFFLOAD_STATE_IDLE; out->offload_state = OFFLOAD_STATE_IDLE; Loading Loading @@ -3644,9 +3643,11 @@ static int create_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) { { lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); pthread_join(out->offload_thread, (void **) NULL); pthread_join(out->offload_thread, (void **) NULL); pthread_cond_destroy(&out->offload_cond); pthread_cond_destroy(&out->offload_cond); Loading Loading @@ -3721,6 +3722,9 @@ static int stop_output_stream(struct stream_out *out) list_remove(&uc_info->list); list_remove(&uc_info->list); out->started = 0; out->started = 0; pthread_mutex_lock(&out->latch_lock); out->muted = false; pthread_mutex_unlock(&out->latch_lock); if (is_offload_usecase(out->usecase) && if (is_offload_usecase(out->usecase) && (audio_extn_passthru_is_passthrough_stream(out))) { (audio_extn_passthru_is_passthrough_stream(out))) { ALOGV("Disable passthrough , reset mixer to pcm"); ALOGV("Disable passthrough , reset mixer to pcm"); Loading Loading @@ -4541,8 +4545,11 @@ static int out_standby(struct audio_stream *stream) if (adev->adm_deregister_stream) if (adev->adm_deregister_stream) adev->adm_deregister_stream(adev->adm_data, out->handle); adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); out->standby = true; out->standby = true; Loading Loading @@ -4616,7 +4623,9 @@ static int out_on_error(struct audio_stream *stream) // is needed e.g. when SSR happens within compress_open // is needed e.g. when SSR happens within compress_open // since the stream is active, offload_callback_thread is also active. // since the stream is active, offload_callback_thread is also active. if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } } pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); Loading Loading @@ -4654,8 +4663,11 @@ int out_standby_l(struct audio_stream *stream) if (adev->adm_deregister_stream) if (adev->adm_deregister_stream) adev->adm_deregister_stream(adev->adm_data, out->handle); adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } out->standby = true; out->standby = true; if (out->usecase == USECASE_COMPRESS_VOIP_CALL) { if (out->usecase == USECASE_COMPRESS_VOIP_CALL) { Loading Loading @@ -5002,12 +5014,13 @@ int route_output_stream(struct stream_out *out, audio_extn_perf_lock_release(&adev->perf_lock_handle); audio_extn_perf_lock_release(&adev->perf_lock_handle); } } if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && out->a2dp_compress_mute && (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) { (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) { pthread_mutex_lock(&out->compr_mute_lock); pthread_mutex_lock(&out->latch_lock); if (out->a2dp_compress_mute) { out->a2dp_compress_mute = false; out->a2dp_compress_mute = false; out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); pthread_mutex_unlock(&out->compr_mute_lock); } pthread_mutex_unlock(&out->latch_lock); } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); } } Loading Loading @@ -5562,7 +5575,9 @@ static int out_set_volume(struct audio_stream_out *stream, float left, ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right); ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right); if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) { if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) { /* only take left channel into account: the API is for stereo anyway */ /* only take left channel into account: the API is for stereo anyway */ pthread_mutex_lock(&out->latch_lock); out->muted = (left == 0.0f); out->muted = (left == 0.0f); pthread_mutex_unlock(&out->latch_lock); return 0; return 0; } else if (is_offload_usecase(out->usecase)) { } else if (is_offload_usecase(out->usecase)) { if (audio_extn_passthru_is_passthrough_stream(out)) { if (audio_extn_passthru_is_passthrough_stream(out)) { Loading Loading @@ -5599,18 +5614,20 @@ static int out_set_volume(struct audio_stream_out *stream, float left, out->volume_r = out_ctxt->output->volume_r; out->volume_r = out_ctxt->output->volume_r; } } } } pthread_mutex_lock(&out->latch_lock); if (!out->a2dp_compress_mute) { if (!out->a2dp_compress_mute) { ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); } } pthread_mutex_unlock(&out->latch_lock); return ret; return ret; } else { } else { pthread_mutex_lock(&out->compr_mute_lock); pthread_mutex_lock(&out->latch_lock); ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute); ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute); if (!out->a2dp_compress_mute) if (!out->a2dp_compress_mute) ret = out_set_compr_volume(stream, left, right); ret = out_set_compr_volume(stream, left, right); out->volume_l = left; out->volume_l = left; out->volume_r = right; out->volume_r = right; pthread_mutex_unlock(&out->compr_mute_lock); pthread_mutex_unlock(&out->latch_lock); return ret; return ret; } } } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { Loading Loading @@ -6021,7 +6038,9 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } } audio_extn_dts_eagle_fade(adev, true, out); audio_extn_dts_eagle_fade(adev, true, out); out->playback_started = 1; out->playback_started = 1; pthread_mutex_lock(&out->latch_lock); out->offload_state = OFFLOAD_STATE_PLAYING; out->offload_state = OFFLOAD_STATE_PLAYING; pthread_mutex_unlock(&out->latch_lock); audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, popcount(out->channel_mask), popcount(out->channel_mask), Loading @@ -6033,8 +6052,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } else { } else { if (out->pcm) { if (out->pcm) { size_t bytes_to_write = bytes; size_t bytes_to_write = bytes; pthread_mutex_lock(&out->latch_lock); if (out->muted) if (out->muted) memset((void *)buffer, 0, bytes); memset((void *)buffer, 0, bytes); pthread_mutex_unlock(&out->latch_lock); ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu", ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu", __func__, frames, frame_size, bytes_to_write); __func__, frames, frame_size, bytes_to_write); Loading Loading @@ -6408,6 +6429,7 @@ static int out_pause(struct audio_stream_out* stream) ALOGD("copl(%p):pause compress driver", out); ALOGD("copl(%p):pause compress driver", out); status = -ENODATA; status = -ENODATA; lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { if (out->card_status != CARD_STATUS_OFFLINE) if (out->card_status != CARD_STATUS_OFFLINE) status = compress_pause(out->compr); status = compress_pause(out->compr); Loading @@ -6424,6 +6446,7 @@ static int out_pause(struct audio_stream_out* stream) out->sample_rate, popcount(out->channel_mask), out->sample_rate, popcount(out->channel_mask), 0); 0); } } pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); } } return status; return status; Loading @@ -6438,6 +6461,7 @@ static int out_resume(struct audio_stream_out* stream) ALOGD("copl(%p):resume compress driver", out); ALOGD("copl(%p):resume compress driver", out); status = -ENODATA; status = -ENODATA; lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->card_status != CARD_STATUS_OFFLINE) { if (out->card_status != CARD_STATUS_OFFLINE) { status = compress_resume(out->compr); status = compress_resume(out->compr); Loading @@ -6449,6 +6473,7 @@ static int out_resume(struct audio_stream_out* stream) audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate, popcount(out->channel_mask), 1); popcount(out->channel_mask), 1); } } pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); } } return status; return status; Loading Loading @@ -6477,12 +6502,14 @@ static int out_flush(struct audio_stream_out* stream) if (is_offload_usecase(out->usecase)) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%p):calling compress flush", out); ALOGD("copl(%p):calling compress flush", out); lock_output_stream(out); lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->offload_state == OFFLOAD_STATE_PAUSED) { if (out->offload_state == OFFLOAD_STATE_PAUSED) { stop_compressed_output_l(out); stop_compressed_output_l(out); } else { } else { ALOGW("%s called in invalid state %d", __func__, out->offload_state); ALOGW("%s called in invalid state %d", __func__, out->offload_state); } } out->written = 0; out->written = 0; pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->lock); ALOGD("copl(%p):out of compress flush", out); ALOGD("copl(%p):out of compress flush", out); return 0; return 0; Loading Loading @@ -7757,7 +7784,7 @@ int adev_open_output_stream(struct audio_hw_device *dev, pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL); pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL); pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL); pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL); Loading Loading @@ -8672,6 +8699,9 @@ void adev_close_output_stream(struct audio_hw_device *dev __unused, pthread_cond_destroy(&out->cond); pthread_cond_destroy(&out->cond); pthread_mutex_destroy(&out->lock); pthread_mutex_destroy(&out->lock); pthread_mutex_destroy(&out->pre_lock); pthread_mutex_destroy(&out->latch_lock); pthread_mutex_destroy(&out->position_query_lock); pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle); streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle); Loading Loading @@ -8895,31 +8925,31 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) if (is_a2dp_out_device_type(&usecase->device_list)) { if (is_a2dp_out_device_type(&usecase->device_list)) { ALOGD("reconfigure a2dp... forcing device switch"); ALOGD("reconfigure a2dp... forcing device switch"); pthread_mutex_unlock(&adev->lock); lock_output_stream(usecase->stream.out); pthread_mutex_lock(&adev->lock); audio_extn_a2dp_set_handoff_mode(true); audio_extn_a2dp_set_handoff_mode(true); ALOGD("Switching to speaker and muting the stream before select_devices"); ALOGD("Switching to speaker and muting the stream before select_devices"); check_a2dp_restore_l(adev, usecase->stream.out, false); check_a2dp_restore_l(adev, usecase->stream.out, false); //force device switch to re configure encoder //force device switch to re configure encoder select_devices(adev, usecase->id); select_devices(adev, usecase->id); ALOGD("Unmuting the stream after select_devices"); ALOGD("Unmuting the stream after select_devices"); pthread_mutex_lock(&usecase->stream.out->latch_lock); usecase->stream.out->a2dp_compress_mute = false; usecase->stream.out->a2dp_compress_mute = false; out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r); out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r); pthread_mutex_unlock(&usecase->stream.out->latch_lock); audio_extn_a2dp_set_handoff_mode(false); audio_extn_a2dp_set_handoff_mode(false); pthread_mutex_unlock(&usecase->stream.out->lock); break; break; } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { usecase->stream.out->a2dp_compress_mute) { pthread_mutex_lock(&usecase->stream.out->latch_lock); pthread_mutex_unlock(&adev->lock); if (usecase->stream.out->a2dp_compress_mute) { lock_output_stream(usecase->stream.out); pthread_mutex_unlock(&usecase->stream.out->latch_lock); pthread_mutex_lock(&adev->lock); reassign_device_list(&usecase->stream.out->device_list, reassign_device_list(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, ""); AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, ""); check_a2dp_restore_l(adev, usecase->stream.out, true); check_a2dp_restore_l(adev, usecase->stream.out, true); pthread_mutex_unlock(&usecase->stream.out->lock); break; break; } } pthread_mutex_unlock(&usecase->stream.out->latch_lock); } } } } } Loading Loading @@ -9745,6 +9775,9 @@ static void adev_close_input_stream(struct audio_hw_device *dev, } else } else in_standby(&stream->common); in_standby(&stream->common); pthread_mutex_destroy(&in->lock); pthread_mutex_destroy(&in->pre_lock); pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); if (in->usecase == USECASE_AUDIO_RECORD) { if (in->usecase == USECASE_AUDIO_RECORD) { adev->pcm_record_uc_state = 0; adev->pcm_record_uc_state = 0; Loading Loading @@ -10349,8 +10382,8 @@ static void adev_snd_mon_cb(void *cookie, struct str_parms *parms) return; return; } } /* out and adev lock held */ /* adev lock held */ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore) int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore) { { struct audio_usecase *uc_info; struct audio_usecase *uc_info; float left_p; float left_p; Loading @@ -10369,23 +10402,26 @@ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *ou out->usecase, use_case_table[out->usecase]); out->usecase, use_case_table[out->usecase]); if (restore) { if (restore) { pthread_mutex_lock(&out->latch_lock); // restore A2DP device for active usecases and unmute if required // restore A2DP device for active usecases and unmute if required if (is_a2dp_out_device_type(&out->device_list)) { if (is_a2dp_out_device_type(&out->device_list)) { ALOGD("%s: restoring A2dp and unmuting stream", __func__); ALOGD("%s: restoring A2dp and unmuting stream", __func__); if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP) if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP) select_devices(adev, uc_info->id); select_devices(adev, uc_info->id); pthread_mutex_lock(&out->compr_mute_lock); if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) { (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) { if (out->a2dp_compress_mute) { out->a2dp_compress_mute = false; out->a2dp_compress_mute = false; out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); } } pthread_mutex_unlock(&out->compr_mute_lock); } } } out->muted = false; pthread_mutex_unlock(&out->latch_lock); } else { } else { pthread_mutex_lock(&out->latch_lock); if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { // mute compress stream if suspended // mute compress stream if suspended pthread_mutex_lock(&out->compr_mute_lock); if (!out->a2dp_compress_mute && !out->standby) { if (!out->a2dp_compress_mute && !out->standby) { ALOGD("%s: selecting speaker and muting stream", __func__); ALOGD("%s: selecting speaker and muting stream", __func__); assign_devices(&devices, &out->device_list); assign_devices(&devices, &out->device_list); Loading @@ -10403,31 +10439,18 @@ static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *ou out->volume_l = left_p; out->volume_l = left_p; out->volume_r = right_p; out->volume_r = right_p; } } pthread_mutex_unlock(&out->compr_mute_lock); } else { } else { // tear down a2dp path for non offloaded streams // mute for non offloaded streams if (audio_extn_a2dp_source_is_suspended()) if (audio_extn_a2dp_source_is_suspended()) { out_standby_l(&out->stream.common); out->muted = true; } } } pthread_mutex_unlock(&out->latch_lock); } } ALOGV("%s: exit", __func__); ALOGV("%s: exit", __func__); return 0; return 0; } } int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore) { int ret = 0; lock_output_stream(out); pthread_mutex_lock(&adev->lock); ret = check_a2dp_restore_l(adev, out, restore); pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); return ret; } void adev_on_battery_status_changed(bool charging) void adev_on_battery_status_changed(bool charging) { { pthread_mutex_lock(&adev->lock); pthread_mutex_lock(&adev->lock); Loading
hal/audio_hw.h +8 −3 Original line number Original line Diff line number Diff line Loading @@ -364,13 +364,18 @@ struct stream_inout { stream_callback_t client_callback; stream_callback_t client_callback; void *client_cookie; void *client_cookie; }; }; struct stream_out { struct stream_out { struct audio_stream_out stream; struct audio_stream_out stream; pthread_mutex_t lock; /* see note below on mutex acquisition order */ pthread_mutex_t lock; /* see note below on mutex acquisition order */ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ pthread_mutex_t compr_mute_lock; /* acquire before setting compress volume */ pthread_mutex_t position_query_lock; /* acquire before updating/getting position of track offload*/ pthread_cond_t cond; pthread_cond_t cond; /* stream_out->lock is of large granularity, and can only be held before device lock * latch is a supplemetary lock to protect certain fields of out stream and * it can be held after device lock */ pthread_mutex_t latch_lock; pthread_mutex_t position_query_lock; /* sychronize frame written */ struct pcm_config config; struct pcm_config config; struct compr_config compr_config; struct compr_config compr_config; struct pcm *pcm; struct pcm *pcm; Loading Loading @@ -780,7 +785,7 @@ int pcm_ioctl(struct pcm *pcm, int request, ...); audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev, audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev, usecase_type_t type); usecase_type_t type); int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore); int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore); int adev_open_output_stream(struct audio_hw_device *dev, int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_io_handle_t handle, Loading