summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/hardware/audio.h2
-rw-r--r--include/hardware/sensors.h8
-rw-r--r--modules/usbaudio/alsa_device_profile.c27
-rw-r--r--modules/usbaudio/alsa_device_profile.h2
-rw-r--r--modules/usbaudio/alsa_device_proxy.c23
-rw-r--r--modules/usbaudio/audio_hw.c49
6 files changed, 79 insertions, 32 deletions
diff --git a/include/hardware/audio.h b/include/hardware/audio.h
index 59fb9a3..763ca58 100644
--- a/include/hardware/audio.h
+++ b/include/hardware/audio.h
@@ -124,6 +124,8 @@ __BEGIN_DECLS
#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */
#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */
+#define AUDIO_PARAMETER_DEVICE_DISCONNECT "disconnect" /* audio_devices_t */
+
/* Query supported formats. The response is a '|' separated list of strings from
* audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */
#define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats"
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index 495828a..a44c155 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -495,9 +495,11 @@ enum {
*
* Because this sensor is on-change, events must be generated when and only
* when heart_rate.bpm or heart_rate.status have changed since the last
- * event. The event should be generated no faster than every period_ns passed
- * to setDelay() or to batch(). See the definition of the on-change reporting
- * mode for more information.
+ * event. In particular, upon the first activation, unless the device is known
+ * to not be on the body, the status field of the first event must be set to
+ * SENSOR_STATUS_UNRELIABLE. The event should be generated no faster than every
+ * period_ns passed to setDelay() or to batch().
+ * See the definition of the on-change reporting mode for more information.
*
* sensor_t.requiredPermission must be set to SENSOR_PERMISSION_BODY_SENSORS.
*
diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c
index f214eab..c7df00c 100644
--- a/modules/usbaudio/alsa_device_profile.c
+++ b/modules/usbaudio/alsa_device_profile.c
@@ -92,6 +92,14 @@ bool profile_is_valid(alsa_device_profile* profile) {
return profile->is_valid;
}
+bool profile_is_cached_for(alsa_device_profile* profile, int card, int device) {
+ return card == profile->card && device == profile->device;
+}
+
+void profile_decache(alsa_device_profile* profile) {
+ profile->card = profile->device = -1;
+}
+
/*
* Returns the supplied value rounded up to the next even multiple of 16
*/
@@ -267,19 +275,28 @@ static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct
static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min, unsigned max)
{
- static const unsigned std_channel_counts[] = {8, 4, 2, 1};
+ // TODO: Don't return MONO even if the device supports it. This causes problems
+ // in AudioPolicyManager. Revisit.
+ static const unsigned std_out_channel_counts[] = {8, 4, 2/*, 1*/};
+ static const unsigned std_in_channel_counts[] = {8, 4, 2, 1};
+
+ unsigned * channel_counts =
+ profile->direction == PCM_OUT ? std_out_channel_counts : std_in_channel_counts;
+ unsigned num_channel_counts =
+ profile->direction == PCM_OUT
+ ? ARRAY_SIZE(std_out_channel_counts) : ARRAY_SIZE(std_in_channel_counts);
unsigned num_counts = 0;
unsigned index;
/* TODO write a profile_test_channel_count() */
/* Ensure there is at least one invalid channel count to terminate the channel counts array */
- for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
+ for (index = 0; index < num_channel_counts &&
num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
index++) {
/* TODO Do we want a channel counts test? */
- if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
- profile_test_channel_count(profile, std_channel_counts[index])*/) {
- profile->channel_counts[num_counts++] = std_channel_counts[index];
+ if (channel_counts[index] >= min && channel_counts[index] <= max /* &&
+ profile_test_channel_count(profile, channel_counts[index])*/) {
+ profile->channel_counts[num_counts++] = channel_counts[index];
}
}
diff --git a/modules/usbaudio/alsa_device_profile.h b/modules/usbaudio/alsa_device_profile.h
index b75e1dc..2c0da39 100644
--- a/modules/usbaudio/alsa_device_profile.h
+++ b/modules/usbaudio/alsa_device_profile.h
@@ -61,6 +61,8 @@ typedef struct {
void profile_init(alsa_device_profile* profile, int direction);
bool profile_is_initialized(alsa_device_profile* profile);
bool profile_is_valid(alsa_device_profile* profile);
+bool profile_is_cached_for(alsa_device_profile* profile, int card, int device);
+void profile_decache(alsa_device_profile* profile);
bool profile_read_device_info(alsa_device_profile* profile);
diff --git a/modules/usbaudio/alsa_device_proxy.c b/modules/usbaudio/alsa_device_proxy.c
index e15f093..081c05b 100644
--- a/modules/usbaudio/alsa_device_proxy.c
+++ b/modules/usbaudio/alsa_device_proxy.c
@@ -27,20 +27,6 @@
#define DEFAULT_PERIOD_SIZE 1024
#define DEFAULT_PERIOD_COUNT 2
-//void proxy_init(alsa_device_proxy * proxy)
-//{
-// proxy->profile = NULL;
-//
-// proxy->alsa_config.format = DEFAULT_SAMPLE_FORMAT;
-// proxy->alsa_config.rate = DEFAULT_SAMPLE_RATE;
-// proxy->alsa_config.channels = DEFAULT_CHANNEL_COUNT;
-//
-// proxy->alsa_config.period_size = DEFAULT_PERIOD_SIZE;
-// proxy->alsa_config.period_count = DEFAULT_PERIOD_COUNT;
-//
-// proxy->pcm = NULL;
-//}
-
void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
struct pcm_config * config)
{
@@ -79,7 +65,6 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
int proxy_open(alsa_device_proxy * proxy)
{
alsa_device_profile* profile = proxy->profile;
-
ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device,
profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN");
@@ -103,8 +88,12 @@ int proxy_open(alsa_device_proxy * proxy)
void proxy_close(alsa_device_proxy * proxy)
{
- pcm_close(proxy->pcm);
- proxy->pcm = NULL;
+ ALOGV("proxy_close() [pcm:%p]", proxy->pcm);
+
+ if (proxy->pcm != NULL) {
+ pcm_close(proxy->pcm);
+ proxy->pcm = NULL;
+ }
}
/*
diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c
index 7e65ab5..caddf97 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hw.c
@@ -253,7 +253,6 @@ static size_t out_get_buffer_size(const struct audio_stream *stream)
const struct stream_out* out = (const struct stream_out*)stream;
size_t buffer_size =
proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream));
- ALOGV("out_get_buffer_size() = %zu", buffer_size);
return buffer_size;
}
@@ -271,7 +270,6 @@ static audio_format_t out_get_format(const struct audio_stream *stream)
*/
alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
- ALOGV("out_get_format() = %d", format);
return format;
}
@@ -328,7 +326,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
if (param_val >= 0)
device = atoi(value);
- if (card >= 0 && device >= 0) {
+ if (card >= 0 && device >= 0 && !profile_is_cached_for(out->profile, card, device)) {
/* cannot read pcm device info if playback is active */
if (!out->standby)
ret_value = -ENOSYS;
@@ -344,6 +342,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
}
}
}
+
pthread_mutex_unlock(&out->lock);
pthread_mutex_unlock(&out->dev->lock);
str_parms_destroy(parms);
@@ -402,7 +401,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, si
}
pthread_mutex_unlock(&out->dev->lock);
-
alsa_device_proxy* proxy = &out->proxy;
const void * write_buff = buffer;
int num_write_buff_bytes = bytes;
@@ -517,6 +515,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
// build this to hand to the alsa_device_proxy
struct pcm_config proxy_config;
+ memset(&proxy_config, 0, sizeof(proxy_config));
int ret = 0;
@@ -705,7 +704,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
pthread_mutex_lock(&in->dev->lock);
pthread_mutex_lock(&in->lock);
- /* Card/Device */
+ /* Device Connection Message ("card=1,device=0") */
param_val = str_parms_get_str(parms, "card", value, sizeof(value));
if (param_val >= 0)
card = atoi(value);
@@ -714,7 +713,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
if (param_val >= 0)
device = atoi(value);
- if (card >= 0 && device >= 0) {
+ if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) {
/* cannot read pcm device info if playback is active */
if (!in->standby)
ret_value = -ENOSYS;
@@ -729,7 +728,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
in->profile->device = saved_device;
}
}
- }
+ }
pthread_mutex_unlock(&in->lock);
pthread_mutex_unlock(&in->dev->lock);
@@ -924,6 +923,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
in->profile = &in->dev->in_profile;
struct pcm_config proxy_config;
+ memset(&proxy_config, 0, sizeof(proxy_config));
/* Rate */
if (config->sample_rate == 0) {
@@ -996,6 +996,41 @@ static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_st
*/
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
+ ALOGV("audio_hw:usb adev_set_parameters(%s)", kvpairs);
+
+ struct audio_device * adev = (struct audio_device *)dev;
+
+ char value[32];
+ int param_val;
+
+ struct str_parms * parms = str_parms_create_str(kvpairs);
+
+ /* Check for the "disconnect" message */
+ param_val = str_parms_get_str(parms, "disconnect", value, sizeof(value));
+ if (param_val >= 0) {
+ audio_devices_t device = (audio_devices_t)atoi(value);
+
+ param_val = str_parms_get_str(parms, "card", value, sizeof(value));
+ int alsa_card = param_val >= 0 ? atoi(value) : -1;
+
+ param_val = str_parms_get_str(parms, "device", value, sizeof(value));
+ int alsa_device = param_val >= 0 ? atoi(value) : -1;
+
+ if (alsa_card >= 0 && alsa_device >= 0) {
+ /* "decache" the profile */
+ pthread_mutex_lock(&adev->lock);
+ if (device == AUDIO_DEVICE_OUT_USB_DEVICE &&
+ profile_is_cached_for(&adev->out_profile, alsa_card, alsa_device)) {
+ profile_decache(&adev->out_profile);
+ }
+ if (device == AUDIO_DEVICE_IN_USB_DEVICE &&
+ profile_is_cached_for(&adev->in_profile, alsa_card, alsa_device)) {
+ profile_decache(&adev->in_profile);
+ }
+ pthread_mutex_unlock(&adev->lock);
+ }
+ }
+
return 0;
}