summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hal/Android.mk5
-rw-r--r--hal/audio_extn/a2dp.c2
-rw-r--r--hal/audio_extn/audiozoom.c260
-rw-r--r--hal/audio_extn/audiozoom.h31
-rw-r--r--hal/audio_hw.c86
-rw-r--r--hal/audio_hw.h2
-rw-r--r--hal/msm8974/platform.c9
7 files changed, 372 insertions, 23 deletions
diff --git a/hal/Android.mk b/hal/Android.mk
index 3bdcf127..e6be0a61 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -207,6 +207,11 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MAXX_AUDIO)), true)
LOCAL_SRC_FILES += audio_extn/maxxaudio.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUDIO_ZOOM)), true)
+ LOCAL_CFLAGS += -DAUDIOZOOM_QDSP_ENABLED
+ LOCAL_SRC_FILES += audio_extn/audiozoom.c
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_24BITS_CAMCORDER)), true)
LOCAL_CFLAGS += -DENABLED_24BITS_CAMCORDER
endif
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 6ebbfc69..d7e2e2a9 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -79,7 +79,7 @@
// System properties used for A2DP Offload
#define SYSPROP_A2DP_OFFLOAD_SUPPORTED "ro.bluetooth.a2dp_offload.supported"
#define SYSPROP_A2DP_OFFLOAD_DISABLED "persist.bluetooth.a2dp_offload.disabled"
-#define SYSPROP_BLUETOOTH_AUDIO_HAL_DISABLED "persist.vendor.bluetooth.bluetooth_audio_hal.disabled"
+#define SYSPROP_BLUETOOTH_AUDIO_HAL_DISABLED "persist.bluetooth.bluetooth_audio_hal.disabled"
#define SYSPROP_A2DP_CODEC_LATENCIES "vendor.audio.a2dp.codec.latency"
// Default encoder bit width
diff --git a/hal/audio_extn/audiozoom.c b/hal/audio_extn/audiozoom.c
new file mode 100644
index 00000000..86d53b41
--- /dev/null
+++ b/hal/audio_extn/audiozoom.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audio_hw_audiozoom"
+/*#define LOG_NDEBUG 0*/
+
+#include <errno.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <expat.h>
+#include <audio_hw.h>
+#include <system/audio.h>
+#include <platform_api.h>
+#include "audio_extn.h"
+
+#include "audiozoom.h"
+
+#include <resolv.h>
+
+#define AUDIOZOOM_PRESET_FILE "/vendor/etc/audiozoom.xml"
+#define MIN_BUFSIZE 8
+
+typedef struct qdsp_audiozoom_cfg {
+ uint32_t topo_id;
+ uint32_t module_id;
+ uint32_t instance_id;
+ uint32_t zoom_param_id;
+ uint32_t wide_param_id;
+ uint32_t dir_param_id;
+ uint32_t app_type;
+} qdsp_audiozoom_cfg_t;
+
+static qdsp_audiozoom_cfg_t qdsp_audiozoom;
+
+static void start_tag(void *userdata __unused, const XML_Char *tag_name,
+ const XML_Char **attr)
+{
+ uint32_t index = 0;
+
+ if (!attr) {
+ ALOGE("%s: NULL platform/tag_name/attr", __func__);
+ return;
+ }
+
+ if (strcmp(tag_name, "topo") == 0) {
+ if (strcmp(attr[0], "id") == 0) {
+ if (attr[1])
+ qdsp_audiozoom.topo_id = atoi(attr[1]);
+ }
+ } else if (strcmp(tag_name, "module") == 0) {
+ if (strcmp(attr[0], "id") == 0) {
+ if (attr[1])
+ qdsp_audiozoom.module_id = atoi(attr[1]);
+ }
+ } else if (strcmp(tag_name, "param") == 0) {
+ while (attr[index] != NULL) {
+ if (strcmp(attr[index], "zoom_id") == 0) {
+ index++;
+ if (attr[index])
+ qdsp_audiozoom.zoom_param_id = atoi(attr[index]);
+ else
+ break;
+ } else if (strcmp(attr[index], "wide_id") == 0) {
+ index++;
+ if (attr[index])
+ qdsp_audiozoom.wide_param_id = atoi(attr[index]);
+ else
+ break;
+ } else if (strcmp(attr[index], "dir_id") == 0) {
+ index++;
+ if (attr[index])
+ qdsp_audiozoom.dir_param_id = atoi(attr[index]);
+ else
+ break;
+ }
+ index++;
+ }
+ } else if (strcmp(tag_name, "app_type") == 0) {
+ if (strcmp(attr[0], "id") == 0) {
+ if (attr[1])
+ qdsp_audiozoom.app_type = atoi(attr[1]);
+ }
+ } else if (strcmp(tag_name, "instance") == 0) {
+ if (strcmp(attr[0], "id") == 0) {
+ if (attr[1])
+ qdsp_audiozoom.instance_id = atoi(attr[1]);
+ }
+ } else {
+ ALOGE("%s: %s is not a supported tag", __func__, tag_name);
+ }
+
+ return;
+}
+
+static void end_tag(void *userdata __unused, const XML_Char *tag_name)
+{
+ if (strcmp(tag_name, "topo") == 0) {
+ } else if (strcmp(tag_name, "module") == 0) {
+ } else if (strcmp(tag_name, "param") == 0) {
+ } else if (strcmp(tag_name, "app_type") == 0) {
+ } else if (strcmp(tag_name, "instance") == 0) {
+ } else {
+ ALOGE("%s: %s is not a supported tag", __func__, tag_name);
+ }
+}
+
+static int audio_extn_audiozoom_parse_info(const char *filename)
+{
+ XML_Parser parser;
+ FILE *file;
+ int ret = 0;
+ int bytes_read;
+ void *buf;
+ static const uint32_t kBufSize = 1024;
+
+ file = fopen(filename, "r");
+ if (!file) {
+ ALOGE("%s: Failed to open %s", __func__, filename);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ parser = XML_ParserCreate(NULL);
+ if (!parser) {
+ ALOGE("%s: Failed to create XML parser!", __func__);
+ ret = -ENODEV;
+ goto err_close_file;
+ }
+
+ XML_SetElementHandler(parser, start_tag, end_tag);
+
+ while (1) {
+ buf = XML_GetBuffer(parser, kBufSize);
+ if (buf == NULL) {
+ ALOGE("%s: XML_GetBuffer failed", __func__);
+ ret = -ENOMEM;
+ goto err_free_parser;
+ }
+
+ bytes_read = fread(buf, 1, kBufSize, file);
+ if (bytes_read < 0) {
+ ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read);
+ ret = bytes_read;
+ goto err_free_parser;
+ }
+
+ if (XML_ParseBuffer(parser, bytes_read,
+ bytes_read == 0) == XML_STATUS_ERROR) {
+ ALOGE("%s: XML_ParseBuffer failed, for %s",
+ __func__, filename);
+ ret = -EINVAL;
+ goto err_free_parser;
+ }
+
+ if (bytes_read == 0)
+ break;
+ }
+
+err_free_parser:
+ XML_ParserFree(parser);
+err_close_file:
+ fclose(file);
+done:
+ return ret;
+}
+
+int audio_extn_audiozoom_set_microphone_direction(
+ struct stream_in *in, audio_microphone_direction_t dir)
+{
+ (void)in;
+ (void)dir;
+ return 0;
+}
+
+static int audio_extn_audiozoom_set_microphone_field_dimension_zoom(
+ struct stream_in *in, float zoom)
+{
+ struct audio_device *adev = in->dev;
+ struct str_parms *parms = str_parms_create();
+ uint8_t value[MIN_BUFSIZE] = {0};
+ char data[MIN_BUFSIZE * 2] = {0};
+ int32_t ret;
+
+ if (zoom > 1.0 || zoom < 0)
+ return -EINVAL;
+
+ if (qdsp_audiozoom.topo_id == 0 || qdsp_audiozoom.module_id == 0 ||
+ qdsp_audiozoom.zoom_param_id == 0)
+ return -ENOSYS;
+
+ str_parms_add_int(parms, "cal_devid", in->device);
+ str_parms_add_int(parms, "cal_apptype", in->app_type_cfg.app_type);
+ str_parms_add_int(parms, "cal_topoid", qdsp_audiozoom.topo_id);
+ str_parms_add_int(parms, "cal_moduleid", qdsp_audiozoom.module_id);
+ str_parms_add_int(parms, "cal_instanceid", qdsp_audiozoom.instance_id);
+ str_parms_add_int(parms, "cal_paramid", qdsp_audiozoom.zoom_param_id);
+
+ zoom *= 255;
+ value[0] = (uint8_t) zoom; /* Valid value is 0 to 255 */
+
+ ret = b64_ntop(value, sizeof(value), data, sizeof(data));
+ if (ret > 0) {
+ str_parms_add_str(parms, "cal_data", data);
+
+ platform_set_parameters(adev->platform, parms);
+ } else {
+ ALOGE("%s: failed to convert data to string, ret %d", __func__, ret);
+ }
+
+ str_parms_destroy(parms);
+
+ return 0;
+}
+
+static int audio_extn_audiozoom_set_microphone_field_dimension_wide_angle(
+ struct stream_in *in, float zoom)
+{
+ (void)in;
+ (void)zoom;
+ return 0;
+}
+
+int audio_extn_audiozoom_set_microphone_field_dimension(
+ struct stream_in *in, float zoom)
+{
+ if (zoom > 1.0 || zoom < -1.0)
+ return -EINVAL;
+
+ if (zoom >= 0 && zoom <= 1.0)
+ return audio_extn_audiozoom_set_microphone_field_dimension_zoom(in, zoom);
+
+ if (zoom >= -1.0 && zoom <= 0)
+ return audio_extn_audiozoom_set_microphone_field_dimension_wide_angle(in, zoom);
+
+ return 0;
+}
+
+int audio_extn_audiozoom_init()
+{
+ audio_extn_audiozoom_parse_info(AUDIOZOOM_PRESET_FILE);
+
+ ALOGV("%s: topo_id=%d, module_id=%d, instance_id=%d, zoom__id=%d, dir_id=%d, app_type=%d",
+ __func__, qdsp_audiozoom.topo_id, qdsp_audiozoom.module_id, qdsp_audiozoom.instance_id,
+ qdsp_audiozoom.zoom_param_id, qdsp_audiozoom.dir_param_id,qdsp_audiozoom.app_type);
+
+ return 0;
+}
diff --git a/hal/audio_extn/audiozoom.h b/hal/audio_extn/audiozoom.h
new file mode 100644
index 00000000..2c0ad716
--- /dev/null
+++ b/hal/audio_extn/audiozoom.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIOZOOM_H_
+#define AUDIOZOOM_H_
+
+#ifndef AUDIOZOOM_QDSP_ENABLED
+#define audio_extn_audiozoom_init() (0)
+#define audio_extn_audiozoom_set_microphone_direction(stream, dir) (-ENOSYS)
+#define audio_extn_audiozoom_set_microphone_field_dimension(stream, zoom) (-ENOSYS)
+#else
+int audio_extn_audiozoom_init();
+int audio_extn_audiozoom_set_microphone_direction(struct stream_in *stream,
+ audio_microphone_direction_t dir);
+int audio_extn_audiozoom_set_microphone_field_dimension(struct stream_in *stream, float zoom);
+#endif
+
+#endif /* AUDIOZOOM_H_ */
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index bb62dfd8..2807bcc9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -60,6 +60,7 @@
#include "sound/compress_params.h"
#include "audio_extn/tfa_98xx.h"
#include "audio_extn/maxxaudio.h"
+#include "audio_extn/audiozoom.h"
/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
* COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
@@ -353,6 +354,11 @@ 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 set_compr_volume(struct audio_stream_out *stream, float left, float right);
+static int in_set_microphone_direction(const struct audio_stream_in *stream,
+ audio_microphone_direction_t dir);
+static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
+
+
static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
int flags __unused)
{
@@ -1492,8 +1498,9 @@ struct stream_in *get_voice_communication_input(const struct audio_device *adev)
return NULL;
}
-int select_devices(struct audio_device *adev,
- audio_usecase_t uc_id)
+int select_devices_with_force_switch(struct audio_device *adev,
+ audio_usecase_t uc_id,
+ bool force_switch)
{
snd_device_t out_snd_device = SND_DEVICE_NONE;
snd_device_t in_snd_device = SND_DEVICE_NONE;
@@ -1598,7 +1605,7 @@ int select_devices(struct audio_device *adev,
if (out_snd_device == usecase->out_snd_device &&
in_snd_device == usecase->in_snd_device) {
- if (!force_device_switch(usecase))
+ if (!force_device_switch(usecase) && !force_switch)
return 0;
}
@@ -1742,6 +1749,12 @@ int select_devices(struct audio_device *adev,
return status;
}
+int select_devices(struct audio_device *adev,
+ audio_usecase_t uc_id)
+{
+ return select_devices_with_force_switch(adev, uc_id, false);
+}
+
static int stop_input_stream(struct stream_in *in)
{
int i, ret = 0;
@@ -1886,6 +1899,8 @@ int start_input_stream(struct stream_in *in)
}
register_in_stream(in);
check_and_enable_effect(adev);
+ audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
+ audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
audio_streaming_hint_end();
audio_extn_perf_lock_release();
ALOGV("%s: exit", __func__);
@@ -4441,17 +4456,13 @@ static int in_start(const struct audio_stream_in* stream)
return ret;
}
-// Read offset for the input positional timestamp from a property.
-// This is to workaround apparent inaccuracies in the timing info that
-// are causing glitches.
+// Read offset for the positional timestamp from a persistent vendor property.
+// This is to workaround apparent inaccuracies in the timing information that
+// is used by the AAudio timing model. The inaccuracies can cause glitches.
static int64_t in_get_mmap_time_offset() {
- // Roughly 100 usec is needed on some devices to cover inaccuracy in DSP.
- // This should be set in a property. But I cannot read the property!
- // So I am setting the offset here to 101 as a test.
- const int32_t kDefaultOffsetMicros = 101; // should be zero if no bug
- // FIXME - why is the property not being read?! The default is used.
+ const int32_t kDefaultOffsetMicros = 0;
int32_t mmap_time_offset_micros = property_get_int32(
- "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
+ "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
return mmap_time_offset_micros * (int64_t)1000;
}
@@ -4580,8 +4591,8 @@ static int in_get_mmap_position(const struct audio_stream_in *stream,
ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
goto exit;
}
- position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
- position->time_nanoseconds += in->mmap_time_offset_nanos;
+ position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
+ + in->mmap_time_offset_nanos;
exit:
pthread_mutex_unlock(&in->lock);
@@ -4621,17 +4632,32 @@ static int adev_get_microphones(const struct audio_hw_device *dev,
static int in_set_microphone_direction(const struct audio_stream_in *stream,
audio_microphone_direction_t dir) {
- (void)stream;
- (void)dir;
- ALOGVV("%s", __func__);
- return -ENOSYS;
+ struct stream_in *in = (struct stream_in *)stream;
+
+ ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
+
+ in->direction = dir;
+
+ if (in->standby)
+ return 0;
+
+ return audio_extn_audiozoom_set_microphone_direction(in, dir);
}
static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
- (void)stream;
- (void)zoom;
- ALOGVV("%s", __func__);
- return -ENOSYS;
+ struct stream_in *in = (struct stream_in *)stream;
+
+ ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
+
+ if (zoom > 1.0 || zoom < -1.0)
+ return -EINVAL;
+
+ in->zoom = zoom;
+
+ if (in->standby)
+ return 0;
+
+ return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
}
static void in_update_sink_metadata(struct audio_stream_in *stream,
@@ -5493,6 +5519,19 @@ static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
voice_is_in_call(adev)) {
voice_stop_call(adev);
adev->current_call_output = NULL;
+
+ /*
+ * After stopping the call, it must check if any active capture
+ * activity device needs to be re-selected.
+ */
+ struct audio_usecase *usecase;
+ struct listnode *node;
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+ select_devices_with_force_switch(adev, usecase->id, true);
+ }
+ }
}
}
pthread_mutex_unlock(&adev->lock);
@@ -5657,6 +5696,8 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
in->standby = 1;
in->capture_handle = handle;
in->flags = flags;
+ in->direction = MIC_DIRECTION_UNSPECIFIED;
+ in->zoom = 0;
ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
if (source == AUDIO_SOURCE_VOICE_UPLINK ||
@@ -6339,6 +6380,7 @@ static int adev_open(const hw_module_t *module, const char *name,
audio_extn_tfa_98xx_init(adev);
audio_extn_ma_init(adev->platform);
+ audio_extn_audiozoom_init();
pthread_mutex_unlock(&adev_init_lock);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 6fd46f78..09926501 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -299,6 +299,8 @@ struct stream_in {
audio_format_t format;
card_status_t card_status;
int capture_started;
+ float zoom;
+ audio_microphone_direction_t direction;
struct stream_app_type_cfg app_type_cfg;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index eb4bb4a1..21f7cf57 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -961,6 +961,15 @@ static int parse_audiocal_cfg(struct str_parms *parms, acdb_audio_cal_cfg_t *cal
cal->param_id = (uint32_t)strtoul(value, NULL, 0);
ret = ret | 0x100;
}
+#ifdef PLATFORM_SM8150
+ err = str_parms_get_str(parms, "cal_instanceid", value, sizeof(value));
+ if (err >= 0) {
+ str_parms_del(parms, "cal_instanceid");
+ cal->instance_id = (uint32_t)strtoul(value, NULL, 0);
+ ret = ret | 0x200;
+ }
+#endif
+
return ret;
}