audio: move gef device change notification to the tail
It's thread unsafe to unlatch the device lock in the middle, active
usecase list may be accessed from other threads and results into race
condition.
Caching the stream information and notify device change at the tail of
select_devices(). In the wrost case, stale info gets notified which won't
harm.
Change-Id: I14f2473a304761d1b2d822135db4c70862c84415
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index fa83205..ef74440 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2015,6 +2015,10 @@
struct stream_out stream_out;
audio_usecase_t hfp_ucid;
int status = 0;
+ audio_devices_t audio_device;
+ audio_channel_mask_t channel_mask;
+ int sample_rate;
+ int acdb_id;
ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
@@ -2255,14 +2259,11 @@
usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
}
- /* Notify device change info to effect clients registered */
- pthread_mutex_unlock(&adev->lock);
- audio_extn_gef_notify_device_config(
- usecase->stream.out->devices,
- usecase->stream.out->channel_mask,
- usecase->stream.out->app_type_cfg.sample_rate,
- platform_get_snd_device_acdb_id(usecase->out_snd_device));
- pthread_mutex_lock(&adev->lock);
+ /* Cache stream information to be notified to gef clients */
+ audio_device = usecase->stream.out->devices;
+ channel_mask = usecase->stream.out->channel_mask;
+ sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
+ acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
}
enable_audio_route(adev, usecase);
@@ -2319,6 +2320,16 @@
}
}
+ /* Notify device change info to effect clients registered
+ * NOTE: device lock has to be unlock temporarily here.
+ * To the worst case, we notify stale info to clients.
+ */
+ if (usecase->type == PCM_PLAYBACK) {
+ pthread_mutex_unlock(&adev->lock);
+ audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
+ pthread_mutex_lock(&adev->lock);
+ }
+
ALOGD("%s: done",__func__);
return status;