Merge "camera3: fix some spec issue related with input/bidrectional stream"
diff --git a/include/hardware/sound_trigger.h b/include/hardware/sound_trigger.h
index fc3ac47..2a8db87 100644
--- a/include/hardware/sound_trigger.h
+++ b/include/hardware/sound_trigger.h
@@ -98,12 +98,9 @@
*/
int (*start_recognition)(const struct sound_trigger_hw_device *dev,
sound_model_handle_t sound_model_handle,
- audio_io_handle_t capture_handle,
- audio_devices_t capture_device,
+ const struct sound_trigger_recognition_config *config,
recognition_callback_t callback,
- void *cookie,
- unsigned int data_size,
- char *data);
+ void *cookie);
/* Stop recognition on a given model.
* The implementation does not have to call the callback when stopped via this method.
diff --git a/modules/soundtrigger/sound_trigger_hw.c b/modules/soundtrigger/sound_trigger_hw.c
index 8347d02..b78a0d1 100644
--- a/modules/soundtrigger/sound_trigger_hw.c
+++ b/modules/soundtrigger/sound_trigger_hw.c
@@ -81,8 +81,9 @@
event->key_phrase_in_capture = false;
event->num_phrases = 1;
event->phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER;
- event->phrase_extras[0].num_users = 1;
- event->phrase_extras[0].confidence_levels[0] = 100;
+ event->phrase_extras[0].num_levels = 1;
+ event->phrase_extras[0].levels[0].level = 100;
+ event->phrase_extras[0].levels[0].user_id = 0;
event->common.data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
event->common.data_size = 1;
data[event->common.data_offset] = 8;
@@ -183,12 +184,9 @@
static int stdev_start_recognition(const struct sound_trigger_hw_device *dev,
sound_model_handle_t sound_model_handle,
- audio_io_handle_t capture_handle __unused,
- audio_devices_t capture_device __unused,
+ const struct sound_trigger_recognition_config *config,
recognition_callback_t callback,
- void *cookie,
- unsigned int data_size,
- char *data)
+ void *cookie)
{
struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
int status = 0;
@@ -202,13 +200,10 @@
status = -ENOSYS;
goto exit;
}
- if (data_size != 0 && data == NULL) {
- status = -EINVAL;
- goto exit;
- }
- if (data_size != 0) {
+ if (config->data_size != 0) {
+ char *data = (char *)config + config->data_offset;
ALOGI("%s data size %d data %d - %d", __func__,
- data_size, data[0], data[data_size - 1]);
+ config->data_size, data[0], data[config->data_size - 1]);
}
stdev->recognition_callback = callback;
diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c
index 4b5c257..2085268 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hw.c
@@ -102,8 +102,7 @@
/*
* Output Configuration Cache
- * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure
- * but that will involve changes in The Framework.
+ * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure.
*/
static struct pcm_config cached_output_hardware_config;
static bool output_hardware_config_is_cached = false;
@@ -119,6 +118,11 @@
struct audio_config hal_pcm_config;
+ /* this is the format the framework thinks it's using. We may need to convert from the actual
+ * (24-bit, 32-bit?) format to this theoretical (framework, probably 16-bit)
+ * format in in_read() */
+ enum pcm_format input_framework_format;
+
// struct resampler_itfe *resampler;
// struct resampler_buffer_provider buf_provider;
@@ -155,7 +159,6 @@
* We are doing this since we *always* present to The Framework as A PCM16LE device, but need to
* support PCM24_3LE (24-bit, packed).
* NOTE:
- * We're just filling the low-order byte of the PCM24LE samples with 0.
* This conversion is safe to do in-place (in_buff == out_buff).
* TODO Move this to a utilities module.
*/
@@ -181,6 +184,37 @@
}
/*
+ * Convert a buffer of packed (3-byte) PCM32 samples to PCM16LE samples.
+ * in_buff points to the buffer of PCM32 samples
+ * num_in_samples size of input buffer in SAMPLES
+ * out_buff points to the buffer to receive converted PCM16LE LE samples.
+ * returns
+ * the number of BYTES of output data.
+ * We are doing this since we *always* present to The Framework as A PCM16LE device, but need to
+ * support PCM_FORMAT_S32_LE (32-bit).
+ * NOTE:
+ * This conversion is safe to do in-place (in_buff == out_buff).
+ * TODO Move this to a utilities module.
+ */
+static size_t convert_32_to_16(const int32_t * in_buff, size_t num_in_samples, short * out_buff)
+{
+ /*
+ * Move from front to back so that the conversion can be done in-place
+ * i.e. in_buff == out_buff
+ */
+
+ short * dst_ptr = out_buff;
+ const int32_t* src_ptr = in_buff;
+ size_t src_smpl_index;
+ for (src_smpl_index = 0; src_smpl_index < num_in_samples; src_smpl_index++) {
+ *dst_ptr++ = *src_ptr++ >> 16;
+ }
+
+ /* return number of *bytes* generated: */
+ return num_in_samples * 2;
+}
+
+/*
* Convert a buffer of N-channel, interleaved PCM16 samples to M-channel PCM16 channels
* (where N < M).
* in_buff points to the buffer of PCM16 samples
@@ -373,14 +407,14 @@
/*
* Maps from bit position in pcm_mask to AUDIO_ format constants.
*/
-static int const format_value_map[] = {
+static audio_format_t const format_value_map[] = {
AUDIO_FORMAT_PCM_8_BIT, /* 00 - SNDRV_PCM_FORMAT_S8 */
AUDIO_FORMAT_PCM_8_BIT, /* 01 - SNDRV_PCM_FORMAT_U8 */
AUDIO_FORMAT_PCM_16_BIT, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
AUDIO_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
AUDIO_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
AUDIO_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
- AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
+ AUDIO_FORMAT_INVALID, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
AUDIO_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
AUDIO_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
AUDIO_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
@@ -406,7 +440,7 @@
AUDIO_FORMAT_INVALID,
AUDIO_FORMAT_INVALID,
AUDIO_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
- AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
+ AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
AUDIO_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
AUDIO_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
AUDIO_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
@@ -426,6 +460,13 @@
AUDIO_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
};
+/*
+ * Returns true if mask indicates support for PCM_16.
+ */
+static bool mask_has_pcm_16(struct pcm_mask* mask) {
+ return (mask->bits[0] & 0x0004) != 0;
+}
+
static int get_format_for_mask(struct pcm_mask* mask)
{
int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
@@ -1124,7 +1165,12 @@
static audio_format_t in_get_format(const struct audio_stream *stream)
{
- return audio_format_from_pcm_format(cached_input_hardware_config.format);
+ const struct stream_in * in_stream = (const struct stream_in *)stream;
+
+ ALOGV("in_get_format() = %d -> %d", in_stream->input_framework_format,
+ audio_format_from_pcm_format(in_stream->input_framework_format));
+ /* return audio_format_from_pcm_format(cached_input_hardware_config.format); */
+ return audio_format_from_pcm_format(in_stream->input_framework_format);
}
static int in_set_format(struct audio_stream *stream, audio_format_t format)
@@ -1253,15 +1299,17 @@
// supported sample formats
if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
- /*TODO This is wrong. It needs to return AUDIO_ format constants (as strings)
- as in audio_policy.conf */
- min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS);
- max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS);
- num_written = snprintf(buffer, buffer_size, "%u", min);
- if (min != max) {
- snprintf(buffer + num_written, buffer_size - num_written, "|%u", max);
+ struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
+ char * format_params = get_format_str_for_mask(format_mask);
+ if (!mask_has_pcm_16(format_mask)) {
+ /* For now, always support PCM_16 and convert locally if necessary */
+ char buff[256];
+ snprintf(buff, sizeof(buff), "AUDIO_FORMAT_PCM_16_BIT|%s", format_params);
+ free(format_params);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, buff);
+ } else {
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
}
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, buffer);
} // AUDIO_PARAMETER_STREAM_SUP_FORMATS
result_str = str_parms_to_str(result);
@@ -1270,6 +1318,8 @@
str_parms_destroy(query);
str_parms_destroy(result);
+ ALOGV("usb:audio_hw::in in_get_parameters() = %s", result_str);
+
return result_str;
}
@@ -1340,8 +1390,13 @@
num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
}
+ /* Assume (for now) that in->input_framework_format == PCM_FORMAT_S16_LE */
if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
+ /* 24-bit USB device */
num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
+ } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
+ /* 32-bit USB device */
+ num_read_buff_bytes = num_read_buff_bytes * 2;
}
// Setup/Realloc the conversion buffer (if necessary).
@@ -1360,14 +1415,22 @@
* Do any conversions necessary to send the data in the format specified to/by the HAL
* (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
*/
- if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
+ if (cached_input_hardware_config.format != PCM_FORMAT_S16_LE) {
+ // we need to convert
if (num_device_channels != num_req_channels) {
out_buff = read_buff;
}
- /* Bit Format Conversion */
- num_read_buff_bytes =
- convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
+ if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
+ num_read_buff_bytes =
+ convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
+ } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
+ num_read_buff_bytes =
+ convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
+ }
+ else {
+ goto err;
+ }
}
if (num_device_channels != num_req_channels) {
@@ -1432,36 +1495,50 @@
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
+ in->input_framework_format = PCM_FORMAT_S16_LE;
+
in->dev = (struct audio_device *)dev;
- if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO)
- ret = -EINVAL;
-
- if (input_hardware_config_is_cached) {
- config->sample_rate = cached_input_hardware_config.rate;
-
- config->format = audio_format_from_pcm_format(cached_input_hardware_config.format);
- if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
- // Always report PCM16 for now. AudioPolicyManagerBase/AudioFlinger dont' understand
- // formats with more other format, so we won't get chosen (say with a 24bit DAC).
- /* TODO Remove this when the above restriction is removed. */
- config->format = AUDIO_FORMAT_PCM_16_BIT;
- }
-
- config->channel_mask = audio_channel_in_mask_from_count(
- cached_input_hardware_config.channels);
- if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
- // Always report STEREO for now. AudioPolicyManagerBase/AudioFlinger dont' understand
- // formats with more channels, so we won't get chosen (say with a 4-channel DAC).
- /* TODO Remove this when the above restriction is removed. */
- config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
- }
- } else {
+ if (!input_hardware_config_is_cached) {
+ // just return defaults until we can actually query the device.
cached_input_hardware_config = default_alsa_in_config;
+ }
- config->format = in_get_format(&in->stream.common);
- config->channel_mask = in_get_channels(&in->stream.common);
- config->sample_rate = in_get_sample_rate(&in->stream.common);
+ /* Rate */
+ /* TODO Check that the requested rate is valid for the connected device */
+ if (config->sample_rate == 0) {
+ config->sample_rate = cached_input_hardware_config.rate;
+ } else {
+ cached_input_hardware_config.rate = config->sample_rate;
+ }
+
+ /* Format */
+ /* until the framework supports format conversion, just take what it asks for
+ * i.e. AUDIO_FORMAT_PCM_16_BIT */
+ /* config->format = audio_format_from_pcm_format(cached_input_hardware_config.format); */
+ if (config->format == AUDIO_FORMAT_DEFAULT) {
+ /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+ * formats */
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
+ /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+ * formats */
+ } else {
+ /* When the framework support other formats, validate here */
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ ret = -EINVAL;
+ }
+
+ /* don't change the cached_input_hardware_config, we will open it as what it is and
+ * convert as necessary */
+ if (config->channel_mask == AUDIO_CHANNEL_NONE) {
+ /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
+ * formats */
+ config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
+ /* allow only stereo capture for now */
+ config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ ret = -EINVAL;
}
in->standby = true;