summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul McLean <pmclean@google.com>2014-07-15 23:07:19 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-07-15 20:39:52 +0000
commitf899cc1c93c25a7f974deda8d73d81b03243c25f (patch)
tree4d83b80fe747f6c2c9453f0d01dd8f492877b77f
parent2cd18a8715589fbabd23b7e976f6f94e65e54f30 (diff)
parent497abe3d9983bd0d1122b99a29a4c290c48245e6 (diff)
downloadhardware_libhardware-f899cc1c93c25a7f974deda8d73d81b03243c25f.zip
hardware_libhardware-f899cc1c93c25a7f974deda8d73d81b03243c25f.tar.gz
hardware_libhardware-f899cc1c93c25a7f974deda8d73d81b03243c25f.tar.bz2
Merge "Added enumeration of legitimate sample rates for input and output." into lmp-dev
-rw-r--r--include/hardware/hwcomposer.h65
-rw-r--r--modules/usbaudio/audio_hw.c284
-rw-r--r--tests/hardware/struct-offset.cpp4
3 files changed, 207 insertions, 146 deletions
diff --git a/include/hardware/hwcomposer.h b/include/hardware/hwcomposer.h
index f647ab3..882bade 100644
--- a/include/hardware/hwcomposer.h
+++ b/include/hardware/hwcomposer.h
@@ -678,16 +678,24 @@ typedef struct hwc_composer_device_1 {
* total number of configurations available for the display is returned in
* *numConfigs. If *numConfigs is zero on entry, then configs may be NULL.
*
- * HWC_DEVICE_API_VERSION_1_1 does not provide a way to choose a config.
- * For displays that support multiple configurations, the h/w composer
- * implementation should choose one and report it as the first config in
- * the list. Reporting the not-chosen configs is not required.
- *
- * Returns 0 on success or -errno on error. If disp is a hotpluggable
- * display type and no display is connected, an error should be returned.
+ * Hardware composers implementing HWC_DEVICE_API_VERSION_1_3 or prior
+ * shall choose one configuration to activate and report it as the first
+ * entry in the returned list. Reporting the inactive configurations is not
+ * required.
+ *
+ * HWC_DEVICE_API_VERSION_1_4 and later provide configuration management
+ * through SurfaceFlinger, and hardware composers implementing these APIs
+ * must also provide getActiveConfig and setActiveConfig. Hardware composers
+ * implementing these API versions may choose not to activate any
+ * configuration, leaving configuration selection to higher levels of the
+ * framework.
+ *
+ * Returns 0 on success or a negative error code on error. If disp is a
+ * hotpluggable display type and no display is connected, an error shall be
+ * returned.
*
* This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later.
- * It should be NULL for previous versions.
+ * It shall be NULL for previous versions.
*/
int (*getDisplayConfigs)(struct hwc_composer_device_1* dev, int disp,
uint32_t* configs, size_t* numConfigs);
@@ -704,19 +712,54 @@ typedef struct hwc_composer_device_1 {
* array will have one less value than the attributes array.
*
* This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later.
- * It should be NULL for previous versions.
+ * It shall be NULL for previous versions.
*
* If disp is a hotpluggable display type and no display is connected,
* or if config is not a valid configuration for the display, a negative
- * value should be returned.
+ * error code shall be returned.
*/
int (*getDisplayAttributes)(struct hwc_composer_device_1* dev, int disp,
uint32_t config, const uint32_t* attributes, int32_t* values);
/*
+ * (*getActiveConfig)() returns the index of the configuration that is
+ * currently active on the connected display. The index is relative to
+ * the list of configuration handles returned by getDisplayConfigs. If there
+ * is no active configuration, -1 shall be returned.
+ *
+ * Returns the configuration index on success or -1 on error.
+ *
+ * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_4 and later.
+ * It shall be NULL for previous versions.
+ */
+ int (*getActiveConfig)(struct hwc_composer_device_1* dev, int disp);
+
+ /*
+ * (*setActiveConfig)() instructs the hardware composer to switch to the
+ * display configuration at the given index in the list of configuration
+ * handles returned by getDisplayConfigs.
+ *
+ * If this function returns without error, any subsequent calls to
+ * getActiveConfig shall return the index set by this function until one
+ * of the following occurs:
+ * 1) Another successful call of this function
+ * 2) The display is disconnected
+ *
+ * Returns 0 on success or a negative error code on error. If disp is a
+ * hotpluggable display type and no display is connected, or if index is
+ * outside of the range of hardware configurations returned by
+ * getDisplayConfigs, an error shall be returned.
+ *
+ * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_4 and later.
+ * It shall be NULL for previous versions.
+ */
+ int (*setActiveConfig)(struct hwc_composer_device_1* dev, int disp,
+ int index);
+
+ /*
* Reserved for future use. Must be NULL.
*/
- void* reserved_proc[4];
+ void* reserved_proc[2];
} hwc_composer_device_1_t;
diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c
index 3ab7454..8945791 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hw.c
@@ -16,6 +16,7 @@
#define LOG_TAG "usb_audio_hw"
/*#define LOG_NDEBUG 0*/
+/*#define LOG_PCM_PARAMS 0*/
#include <errno.h>
#include <inttypes.h>
@@ -36,6 +37,8 @@
#include <tinyalsa/asoundlib.h>
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
/* This is the default configuration to hand to The Framework on the initial
* adev_open_output_stream(). Actual device attributes will be used on the subsequent
* adev_open_output_stream() after the card and device number have been set in out_set_parameters()
@@ -69,18 +72,22 @@ struct pcm_config default_alsa_in_config = {
.stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT),
};
+struct audio_device_profile {
+ int card;
+ int device;
+ int direction; /* PCM_OUT or PCM_IN */
+};
+
struct audio_device {
struct audio_hw_device hw_device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
/* output */
- int out_card;
- int out_device;
+ struct audio_device_profile out_profile;
/* input */
- int in_card;
- int in_device;
+ struct audio_device_profile in_profile;
bool standby;
};
@@ -93,6 +100,7 @@ struct stream_out {
bool standby;
struct audio_device *dev; /* hardware information */
+ struct audio_device_profile * profile;
void * conversion_buffer; /* any conversions are put into here
* they could come from here too if
@@ -116,6 +124,8 @@ struct stream_in {
struct audio_device *dev;
+ struct audio_device_profile * profile;
+
struct audio_config hal_pcm_config;
/* this is the format the framework thinks it's using. We may need to convert from the actual
@@ -746,6 +756,54 @@ static int get_pcm_format_for_mask(struct pcm_mask* mask) {
return -1; /* error */
}
+static bool test_out_sample_rate(struct audio_device_profile* dev_profile, unsigned rate) {
+ struct pcm_config local_config = cached_output_hardware_config;
+ local_config.rate = rate;
+
+ bool works = false; /* let's be pessimistic */
+ struct pcm * pcm =
+ pcm_open(dev_profile->card, dev_profile->device, dev_profile->direction, &local_config);
+
+ if (pcm != NULL) {
+ works = pcm_is_ready(pcm);
+ pcm_close(pcm);
+ }
+
+ return works;
+}
+
+/* sort these highest -> lowest */
+static const unsigned std_sample_rates[] =
+ {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
+
+static char* enum_std_sample_rates(struct audio_device_profile* dev_profile,
+ unsigned min, unsigned max)
+{
+ char buffer[128];
+ buffer[0] = '\0';
+ int buffSize = ARRAY_SIZE(buffer);
+
+ char numBuffer[32];
+
+ int numEntries = 0;
+ unsigned index;
+ for(index = 0; index < ARRAY_SIZE(std_sample_rates); index++) {
+ if (std_sample_rates[index] >= min && std_sample_rates[index] <= max &&
+ test_out_sample_rate(dev_profile, std_sample_rates[index])) {
+ if (numEntries++ != 0) {
+ strncat(buffer, "|", buffSize);
+ }
+ snprintf(numBuffer, sizeof(numBuffer), "%u", std_sample_rates[index]);
+ strncat(buffer, numBuffer, buffSize);
+ }
+ }
+
+ return strdup(buffer);
+}
+
+/*
+ * Logging
+ */
static void log_pcm_mask(const char* mask_name, struct pcm_mask* mask) {
char buff[512];
char bit_buff[32];
@@ -835,15 +893,18 @@ static unsigned int calc_min_period_size(unsigned int sample_rate) {
/*
* Reads and decodes configuration info from the specified ALSA card/device
*/
-static int read_alsa_device_config(int card, int device, int io_type, struct pcm_config * config)
+static int read_alsa_device_config(struct audio_device_profile * dev_profile,
+ struct pcm_config * config)
{
- ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",card, device, io_type);
+ ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
+ dev_profile->card, dev_profile->device, dev_profile->direction);
- if (card < 0 || device < 0) {
+ if (dev_profile->card < 0 || dev_profile->device < 0) {
return -EINVAL;
}
- struct pcm_params * alsa_hw_params = pcm_params_get(card, device, io_type);
+ struct pcm_params * alsa_hw_params =
+ pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
if (alsa_hw_params == NULL) {
return -EINVAL;
}
@@ -853,7 +914,9 @@ static int read_alsa_device_config(int card, int device, int io_type, struct pcm
/*
* This Logging will be useful when testing new USB devices.
*/
- /* log_pcm_params(alsa_hw_params); */
+#ifdef LOG_PCM_PARAMS
+ log_pcm_params(alsa_hw_params);
+#endif
config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
@@ -951,7 +1014,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
ALOGV("usb:audio_hw::out out_set_parameters() keys:%s", kvpairs);
struct stream_out *out = (struct stream_out *)stream;
- struct audio_device *adev = out->dev;
struct str_parms *parms;
char value[32];
int param_val;
@@ -959,45 +1021,41 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
int ret_value = 0;
parms = str_parms_create_str(kvpairs);
- pthread_mutex_lock(&adev->lock);
+ pthread_mutex_lock(&out->dev->lock);
+ pthread_mutex_lock(&out->lock);
bool recache_device_params = false;
param_val = str_parms_get_str(parms, "card", value, sizeof(value));
if (param_val >= 0) {
- adev->out_card = atoi(value);
+ out->profile->card = atoi(value);
recache_device_params = true;
}
param_val = str_parms_get_str(parms, "device", value, sizeof(value));
if (param_val >= 0) {
- adev->out_device = atoi(value);
+ out->profile->device = atoi(value);
recache_device_params = true;
}
- if (recache_device_params && adev->out_card >= 0 && adev->out_device >= 0) {
- ret_value = read_alsa_device_config(adev->out_card, adev->out_device, PCM_OUT,
- &cached_output_hardware_config);
+ if (recache_device_params && out->profile->card >= 0 && out->profile->device >= 0) {
+ ret_value = read_alsa_device_config(out->profile, &cached_output_hardware_config);
output_hardware_config_is_cached = (ret_value == 0);
}
- pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&out->lock);
+ pthread_mutex_unlock(&out->dev->lock);
str_parms_destroy(parms);
return ret_value;
}
-/*TODO it seems like both out_get_parameters() and in_get_parameters()
- could be written in terms of a get_device_parameters(io_type) */
-
-static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
+static char * device_get_parameters(struct audio_device_profile * dev_profile, const char *keys)
{
- ALOGV("usb:audio_hw::out out_get_parameters() keys:%s", keys);
+ ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
- struct stream_out *out = (struct stream_out *) stream;
- struct audio_device *adev = out->dev;
-
- if (adev->out_card < 0 || adev->out_device < 0)
+ if (dev_profile->card < 0 || dev_profile->device < 0) {
return strdup("");
+ }
unsigned min, max;
@@ -1009,58 +1067,74 @@ static char * out_get_parameters(const struct audio_stream *stream, const char *
int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
char* result_str = NULL;
- struct pcm_params * alsa_hw_params = pcm_params_get(adev->out_card, adev->out_device, PCM_OUT);
+ struct pcm_params * alsa_hw_params =
+ pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
// These keys are from hardware/libhardware/include/audio.h
// supported sample rates
if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
- // pcm_hw_params doesn't have a list of supported samples rates, just a min and a max, so
- // if they are different, return a list containing those two values, otherwise just the one.
min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE);
- num_written = snprintf(buffer, buffer_size, "%u", min);
- if (min != max) {
- snprintf(buffer + num_written, buffer_size - num_written, "|%u", max);
- }
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
- buffer);
+
+ char* rates_list = enum_std_sample_rates(dev_profile, min, max);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, rates_list);
+ free(rates_list);
} // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES
// supported channel counts
if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
- // Similarly for output channels count
- /* TODO - This is wrong, we need format strings, not numbers (another CL) */
- min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
- max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
- num_written = snprintf(buffer, buffer_size, "%u", min);
- if (min != max) {
- snprintf(buffer + num_written, buffer_size - num_written, "|%u", max);
- }
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, buffer);
+ // TODO remove this hack when it is superceeded by proper multi-channel support
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
+ dev_profile->direction == PCM_OUT
+ ? "AUDIO_CHANNEL_OUT_STEREO"
+ : "AUDIO_CHANNEL_IN_STEREO");
} // AUDIO_PARAMETER_STREAM_SUP_CHANNELS
// supported sample formats
if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
- char * format_params =
- get_format_str_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
- free(format_params);
+ // TODO remove this hack when we have support for input in non PCM16 formats
+ if (dev_profile->direction == PCM_IN) {
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, "AUDIO_FORMAT_PCM_16_BIT");
+ } else {
+ 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);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
+ free(format_params);
+ }
} // AUDIO_PARAMETER_STREAM_SUP_FORMATS
+ pcm_params_free(alsa_hw_params);
+
result_str = str_parms_to_str(result);
// done with these...
str_parms_destroy(query);
str_parms_destroy(result);
- ALOGV("usb:audio_hw::out out_get_parameters() = %s", result_str);
+ ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
return result_str;
}
-static uint32_t out_get_latency(const struct audio_stream_out *stream)
+static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
{
+ ALOGV("usb:audio_hw::out out_get_parameters() keys:%s", keys);
+
struct stream_out *out = (struct stream_out *) stream;
+ pthread_mutex_lock(&out->dev->lock);
+ pthread_mutex_lock(&out->lock);
+
+ char * params_str = device_get_parameters(out->profile, keys);
+
+ pthread_mutex_unlock(&out->lock);
+ pthread_mutex_unlock(&out->dev->lock);
+
+ return params_str;
+}
+
+static uint32_t out_get_latency(const struct audio_stream_out *stream)
+{
+ // struct stream_out *out = (struct stream_out *) stream;
/*TODO Do we need a term here for the USB latency (as reported in the USB descriptors)? */
uint32_t latency = (cached_output_hardware_config.period_size
@@ -1077,13 +1151,13 @@ static int out_set_volume(struct audio_stream_out *stream, float left, float rig
/* must be called with hw device and output stream mutexes locked */
static int start_output_stream(struct stream_out *out)
{
- struct audio_device *adev = out->dev;
int return_val = 0;
ALOGV("usb:audio_hw::out start_output_stream(card:%d device:%d)",
- adev->out_card, adev->out_device);
+ out->profile->card, out->profile->device);
- out->pcm = pcm_open(adev->out_card, adev->out_device, PCM_OUT, &cached_output_hardware_config);
+ out->pcm = pcm_open(out->profile->card, out->profile->device, PCM_OUT,
+ &cached_output_hardware_config);
if (out->pcm == NULL) {
return -ENOMEM;
@@ -1222,6 +1296,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->dev = adev;
+ out->profile = &(adev->out_profile);
+ out->profile->direction = PCM_OUT;
+
if (output_hardware_config_is_cached) {
config->sample_rate = cached_output_hardware_config.rate;
@@ -1388,7 +1465,6 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
struct stream_in *in = (struct stream_in *)stream;
- struct audio_device *adev = in->dev;
struct str_parms *parms;
char value[32];
int param_val;
@@ -1396,112 +1472,49 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
int ret_value = 0;
parms = str_parms_create_str(kvpairs);
- pthread_mutex_lock(&adev->lock);
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
bool recache_device_params = false;
// Card/Device
param_val = str_parms_get_str(parms, "card", value, sizeof(value));
if (param_val >= 0) {
- adev->in_card = atoi(value);
+ in->profile->card = atoi(value);
recache_device_params = true;
}
param_val = str_parms_get_str(parms, "device", value, sizeof(value));
if (param_val >= 0) {
- adev->in_device = atoi(value);
+ in->profile->device = atoi(value);
recache_device_params = true;
}
- if (recache_device_params && adev->in_card >= 0 && adev->in_device >= 0) {
- ret_value = read_alsa_device_config(adev->in_card, adev->in_device,
- PCM_IN, &(cached_input_hardware_config));
+ if (recache_device_params && in->profile->card >= 0 && in->profile->device >= 0) {
+ ret_value = read_alsa_device_config(in->profile, &cached_input_hardware_config);
input_hardware_config_is_cached = (ret_value == 0);
}
- pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
str_parms_destroy(parms);
return ret_value;
}
-/*TODO it seems like both out_get_parameters() and in_get_parameters()
- could be written in terms of a get_device_parameters(io_type) */
-
static char * in_get_parameters(const struct audio_stream *stream, const char *keys) {
ALOGV("usb:audio_hw::in in_get_parameters() keys:%s", keys);
struct stream_in *in = (struct stream_in *)stream;
- struct audio_device *adev = in->dev;
-
- if (adev->in_card < 0 || adev->in_device < 0)
- return strdup("");
-
- struct pcm_params * alsa_hw_params = pcm_params_get(adev->in_card, adev->in_device, PCM_IN);
- if (alsa_hw_params == NULL)
- return strdup("");
-
- struct str_parms *query = str_parms_create_str(keys);
- struct str_parms *result = str_parms_create();
-
- int num_written = 0;
- char buffer[256];
- int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
- char* result_str = NULL;
-
- unsigned min, max;
-
- // These keys are from hardware/libhardware/include/audio.h
- // supported sample rates
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
- // pcm_hw_params doesn't have a list of supported samples rates, just a min and a max, so
- // if they are different, return a list containing those two values, otherwise just the one.
- min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
- max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE);
- num_written = snprintf(buffer, buffer_size, "%u", min);
- if (min != max) {
- snprintf(buffer + num_written, buffer_size - num_written, "|%u", max);
- }
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SAMPLING_RATE, buffer);
- } // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES
-
- // supported channel counts
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
- // Similarly for output channels count
- // TODO This is wrong, we need format strings, not numbers (another CL)
- min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
- max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
- num_written = snprintf(buffer, buffer_size, "%u", min);
- if (min != max) {
- snprintf(buffer + num_written, buffer_size - num_written, "|%u", max);
- }
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_CHANNELS, buffer);
- } // AUDIO_PARAMETER_STREAM_SUP_CHANNELS
-
- // supported sample formats
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
- 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);
- }
- } // AUDIO_PARAMETER_STREAM_SUP_FORMATS
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
- result_str = str_parms_to_str(result);
+ char * params_str = device_get_parameters(in->profile, keys);
- // done with these...
- str_parms_destroy(query);
- str_parms_destroy(result);
-
- ALOGV("usb:audio_hw::in in_get_parameters() = %s", result_str);
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
- return result_str;
+ return params_str;
}
static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
@@ -1521,13 +1534,13 @@ static int in_set_gain(struct audio_stream_in *stream, float gain)
/* must be called with hw device and output stream mutexes locked */
static int start_input_stream(struct stream_in *in) {
- struct audio_device *adev = in->dev;
int return_val = 0;
ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
- adev->in_card, adev->in_device);
+ in->profile->card, in->profile->device);
- in->pcm = pcm_open(adev->in_card, adev->in_device, PCM_IN, &cached_input_hardware_config);
+ in->pcm = pcm_open(in->profile->card, in->profile->device, PCM_IN,
+ &cached_input_hardware_config);
if (in->pcm == NULL) {
ALOGE("usb:audio_hw pcm_open() in->pcm == NULL");
return -ENOMEM;
@@ -1678,6 +1691,9 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
in->dev = (struct audio_device *)dev;
+ in->profile = &(in->dev->in_profile);
+ in->profile->direction = PCM_IN;
+
if (!input_hardware_config_is_cached) {
// just return defaults until we can actually query the device.
cached_input_hardware_config = default_alsa_in_config;
diff --git a/tests/hardware/struct-offset.cpp b/tests/hardware/struct-offset.cpp
index 8e5aa40..2354408 100644
--- a/tests/hardware/struct-offset.cpp
+++ b/tests/hardware/struct-offset.cpp
@@ -167,7 +167,9 @@ void CheckOffsets(void) {
CHECK_MEMBER_AT(hwc_composer_device_1_t, dump, 88, 168);
CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayConfigs, 92, 176);
CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayAttributes, 96, 184);
- CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 100, 192);
+ CHECK_MEMBER_AT(hwc_composer_device_1_t, getActiveConfig, 100, 192);
+ CHECK_MEMBER_AT(hwc_composer_device_1_t, setActiveConfig, 104, 200);
+ CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 108, 208);
//Types defined in gralloc.h
CHECK_MEMBER_AT(gralloc_module_t, common, 0, 0);