hal: remote merge from master to LA.BR.1 branch
- Merge commit 'b87c2eeacfec214f198169319b11e4aca8ab8e87'
Conflicts:
hal/Android.mk
hal/audio_extn/audio_extn.c
hal/audio_extn/audio_extn.h
hal/audio_extn/dolby.c
hal/audio_hw.c
hal/msm8916/hw_info.c
hal/msm8916/platform.c
hal/msm8916/platform.h
hal/msm8974/platform.c
hal/platform_api.h
policy_hal/AudioPolicyManager.cpp
Change-Id: Ic9e8a18a5d82719b02038999c92c9991f843981b
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 335a629..96b0a8b 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -48,6 +48,30 @@
#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
+#define AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH "music_offload_alac_frame_length"
+#define AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION "music_offload_alac_compatible_version"
+#define AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH "music_offload_alac_bit_depth"
+#define AUDIO_OFFLOAD_CODEC_ALAC_PB "music_offload_alac_pb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MB "music_offload_alac_mb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_KB "music_offload_alac_kb"
+#define AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS "music_offload_alac_num_channels"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN "music_offload_alac_max_run"
+#define AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES "music_offload_alac_max_frame_bytes"
+#define AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE "music_offload_alac_avg_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE "music_offload_alac_sampling_rate"
+#define AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG "music_offload_alac_channel_layout_tag"
+
+#define AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION "music_offload_ape_compatible_version"
+#define AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL "music_offload_ape_compression_level"
+#define AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS "music_offload_ape_format_flags"
+#define AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME "music_offload_ape_blocks_per_frame"
+#define AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS "music_offload_ape_final_frame_blocks"
+#define AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES "music_offload_ape_total_frames"
+#define AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE "music_offload_ape_bits_per_sample"
+#define AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS "music_offload_ape_num_channels"
+#define AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
+#define AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
+
/* Query handle fm parameter*/
#define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index cae961d..ca5fd59 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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_extn"
@@ -31,6 +49,9 @@
#include "audio_extn.h"
#include "platform.h"
#include "platform_api.h"
+#include "edid.h"
+
+#include "sound/compress_params.h"
#define MAX_SLEEP_RETRY 100
#define WIFI_INIT_WAIT_SLEEP 50
@@ -40,6 +61,7 @@
bool aanc_enabled;
bool custom_stereo_enabled;
uint32_t proxy_channel_num;
+ bool hpx_enabled;
};
static struct audio_extn_module aextnmod = {
@@ -47,6 +69,7 @@
.aanc_enabled = 0,
.custom_stereo_enabled = 0,
.proxy_channel_num = 2,
+ .hpx_enabled = 0,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
@@ -55,6 +78,9 @@
#define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono"
/* Query offload playback instances count */
#define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
+#define AUDIO_PARAMETER_HPX "HPX"
+#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE "asphere_enable"
+#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
#ifndef FM_ENABLED
#define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -69,6 +95,17 @@
struct str_parms *parms);
#endif
+#ifndef SOURCE_TRACKING_ENABLED
+#define audio_extn_source_track_set_parameters(adev, parms) (0)
+#define audio_extn_source_track_get_parameters(adev, query, reply) (0)
+#else
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply);
+#endif
+
#ifndef CUSTOM_STEREO_ENABLED
#define audio_extn_customstereo_set_parameters(adev, parms) (0)
#else
@@ -108,6 +145,76 @@
}
#endif /* CUSTOM_STEREO_ENABLED */
+#ifndef DTS_EAGLE
+#define audio_extn_hpx_set_parameters(adev, parms) (0)
+#define audio_extn_hpx_get_parameters(query, reply) (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev) (0)
+#else
+void audio_extn_hpx_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int ret = 0;
+ char value[32]={0};
+ char prop[PROPERTY_VALUE_MAX] = "false";
+ bool hpx_state = false;
+ const char *mixer_ctl_name = "Set HPX OnOff";
+ struct mixer_ctl *ctl = NULL;
+ ALOGV("%s", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HPX, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (!strncmp("ON", value, sizeof("ON")))
+ hpx_state = true;
+
+ if (hpx_state == aextnmod.hpx_enabled)
+ return;
+
+ aextnmod.hpx_enabled = hpx_state;
+ /* set HPX state on stream pp */
+ if (adev->offload_effects_set_hpx_state != NULL)
+ adev->offload_effects_set_hpx_state(hpx_state);
+
+ /* set HPX state on device pp */
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (ctl)
+ mixer_ctl_set_value(ctl, 0, aextnmod.hpx_enabled);
+ }
+}
+
+static int audio_extn_hpx_get_parameters(struct str_parms *query,
+ struct str_parms *reply)
+{
+ int ret;
+ char value[32]={0};
+
+ ALOGV("%s: hpx %d", __func__, aextnmod.hpx_enabled);
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_HPX, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (aextnmod.hpx_enabled)
+ str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "ON");
+ else
+ str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "OFF");
+ }
+ return ret;
+}
+
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+ if (adev->offload_effects_set_hpx_state)
+ adev->offload_effects_set_hpx_state(aextnmod.hpx_enabled);
+}
+#endif
+
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
#else
@@ -236,35 +343,11 @@
#define audio_extn_set_afe_proxy_parameters(adev, parms) (0)
#define audio_extn_get_afe_proxy_parameters(query, reply) (0)
#else
-/* Front left channel. */
-#define PCM_CHANNEL_FL 1
-
-/* Front right channel. */
-#define PCM_CHANNEL_FR 2
-
-/* Front center channel. */
-#define PCM_CHANNEL_FC 3
-
-/* Left surround channel.*/
-#define PCM_CHANNEL_LS 4
-
-/* Right surround channel.*/
-#define PCM_CHANNEL_RS 5
-
-/* Low frequency effect channel. */
-#define PCM_CHANNEL_LFE 6
-
-/* Left back channel; Rear left channel. */
-#define PCM_CHANNEL_LB 8
-
-/* Right back channel; Rear right channel. */
-#define PCM_CHANNEL_RB 9
-
static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
int channel_count)
{
struct mixer_ctl *ctl;
- const char *mixer_ctl_name = "Playback Channel Map";
+ const char *mixer_ctl_name = "Playback Device Channel Map";
int set_values[8] = {0};
int ret;
ALOGV("%s channel_count:%d",__func__, channel_count);
@@ -451,6 +534,103 @@
return ret;
}
+#ifndef AUDIOSPHERE_ENABLED
+#define audio_extn_asphere_set_parameters(adev, parms) (0)
+#define audio_extn_asphere_get_parameters(adev, query, reply) (0)
+#else
+int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int ret = 0, val[2];
+ char value[32] = {0};
+ int set_enable, set_strength;
+ int enable = -1, strength = -1;
+ struct mixer_ctl *ctl = NULL;
+ const char *mixer_ctl_name = "MSM ASphere Set Param";
+ char propValue[PROPERTY_VALUE_MAX] = {0};
+ bool asphere_prop_enabled = false;
+
+ if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
+ if (!strncmp("true", propValue, 4))
+ asphere_prop_enabled = true;
+ }
+
+ if (!asphere_prop_enabled) {
+ ALOGV("%s: property not set!!! not doing anything", __func__);
+ return ret;
+ }
+
+ set_enable = str_parms_get_str(parms,
+ AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+ value, sizeof(value));
+ if (set_enable > 0)
+ enable = atoi(value);
+
+ set_strength = str_parms_get_str(parms,
+ AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+ value, sizeof(value));
+ if (set_strength > 0)
+ strength = atoi(value);
+
+ if (set_enable >= 0 || set_strength >= 0) {
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ ALOGD("%s: set ctl \"%s:%d,%d\"",
+ __func__, mixer_ctl_name, enable, strength);
+ val[0] = enable;
+ val[1] = strength;
+ ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
+ if (ret)
+ ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
+ __func__, mixer_ctl_name, enable, strength);
+ }
+ ALOGV("%s: exit ret %d", __func__, ret);
+ return ret;
+}
+
+int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ int ret = 0, val[2] = {-1, -1};
+ char value[32] = {0};
+ int get_enable, get_strength;
+ struct mixer_ctl *ctl = NULL;
+ const char *mixer_ctl_name = "MSM ASphere Set Param";
+
+ get_enable = str_parms_get_str(query,
+ AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+ value, sizeof(value));
+ get_strength = str_parms_get_str(query,
+ AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+ value, sizeof(value));
+ if (get_enable > 0 || get_strength > 0) {
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
+ if (ret)
+ ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
+ __func__, mixer_ctl_name, val[0], val[1]);
+ if (get_enable > 0)
+ str_parms_add_int(reply,
+ AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
+ if (get_strength > 0)
+ str_parms_add_int(reply,
+ AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
+ }
+ ALOGV("%s: exit ret %d", __func__, ret);
+ return ret;
+}
+#endif
+
void audio_extn_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
@@ -461,10 +641,14 @@
audio_extn_sound_trigger_set_parameters(adev, parms);
audio_extn_listen_set_parameters(adev, parms);
audio_extn_hfp_set_parameters(adev, parms);
+ audio_extn_dts_eagle_set_parameters(adev, parms);
audio_extn_ddp_set_parameters(adev, parms);
audio_extn_ds2_set_parameters(adev, parms);
audio_extn_customstereo_set_parameters(adev, parms);
+ audio_extn_hpx_set_parameters(adev, parms);
audio_extn_pm_set_parameters(parms);
+ audio_extn_source_track_set_parameters(adev, parms);
+ audio_extn_asphere_set_parameters(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -475,12 +659,250 @@
audio_extn_get_afe_proxy_parameters(query, reply);
audio_extn_get_fluence_parameters(adev, query, reply);
get_active_offload_usecases(adev, query, reply);
+ audio_extn_dts_eagle_get_parameters(adev, query, reply);
+ audio_extn_hpx_get_parameters(query, reply);
+ audio_extn_source_track_get_parameters(adev, query, reply);
+ audio_extn_asphere_get_parameters(adev, query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
free(kv_pairs);
}
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
+#else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+ struct str_parms *parms)
+{
+ int ret = 0;
+ char value[32];
+
+ if (out->format == AUDIO_FORMAT_FLAC) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->gapless_mdata.min_blk_size =
+ out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->gapless_mdata.max_blk_size =
+ out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
+ out->compr_config.codec->options.flac_dec.min_blk_size,
+ out->compr_config.codec->options.flac_dec.max_blk_size,
+ out->compr_config.codec->options.flac_dec.min_frame_size,
+ out->compr_config.codec->options.flac_dec.max_frame_size);
+ }
+
+ else if (out->format == AUDIO_FORMAT_ALAC) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.frame_length = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.compatible_version = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.bit_depth = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.pb = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.mb = atoi(value);
+ out->send_new_metadata = 1;
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.kb = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.num_channels = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.max_run = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.sample_rate = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
+ " maxFrameBytes %d, avgBitRate %d, sampleRate %d",
+ out->compr_config.codec->options.alac.frame_length,
+ out->compr_config.codec->options.alac.bit_depth,
+ out->compr_config.codec->options.alac.num_channels,
+ out->compr_config.codec->options.alac.max_frame_bytes,
+ out->compr_config.codec->options.alac.avg_bit_rate,
+ out->compr_config.codec->options.alac.sample_rate);
+ }
+
+ else if (out->format == AUDIO_FORMAT_APE) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.compatible_version = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.compression_level = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.format_flags = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.total_frames = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.num_channels = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.sample_rate = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.ape.seek_table_present = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
+ " formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
+ " totalFrames %d bitsPerSample %d numChannels %d"
+ " sampleRate %d seekTablePresent %d",
+ out->compr_config.codec->options.ape.compatible_version,
+ out->compr_config.codec->options.ape.compression_level,
+ out->compr_config.codec->options.ape.format_flags,
+ out->compr_config.codec->options.ape.blocks_per_frame,
+ out->compr_config.codec->options.ape.final_frame_blocks,
+ out->compr_config.codec->options.ape.total_frames,
+ out->compr_config.codec->options.ape.bits_per_sample,
+ out->compr_config.codec->options.ape.num_channels,
+ out->compr_config.codec->options.ape.sample_rate,
+ out->compr_config.codec->options.ape.seek_table_present);
+ }
+
+ else if (out->format == AUDIO_FORMAT_VORBIS) {
+ // transcoded bitstream mode
+ out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
+ out->send_new_metadata = 1;
+ }
+
+ else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->format = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.super_block_align = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.channelmask = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.super_block_align,
+ out->compr_config.codec->options.wma.bits_per_sample,
+ out->compr_config.codec->options.wma.channelmask,
+ out->compr_config.codec->options.wma.encodeopt,
+ out->compr_config.codec->options.wma.encodeopt1,
+ out->compr_config.codec->options.wma.encodeopt2);
+ }
+
+ return ret;
+}
+#endif
+
#ifdef AUXPCM_BT_ENABLED
int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
const char* mixer_xml_path,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 6baa37f..98b2672 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 AUDIO_EXTN_H
@@ -51,15 +69,34 @@
#define AUDIO_DEVICE_IN_FM_RX_A2DP (AUDIO_DEVICE_BIT_IN | 0x10000)
#endif
-#ifndef QTI_FLAC_DECODER
-#define AUDIO_FORMAT_FLAC 0x19000000UL
-#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE "music_offload_flac_min_blk_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE "music_offload_flac_max_blk_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
-#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
-#define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
+#ifndef FLAC_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_FLAC 0x1D000000UL
+#endif
+
+#ifndef WMA_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_WMA 0x13000000UL
+#define AUDIO_FORMAT_WMAPRO 0x14000000UL
+#endif
+
+#ifndef ALAC_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_ALAC 0x1F000000UL
+#endif
+
+#ifndef APE_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_APE 0x20000000UL
+#endif
+
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
#else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+ struct str_parms *parms);
+#endif
+
+#ifdef PCM_OFFLOAD_ENABLED_24
#define PCM_OUTPUT_BIT_WIDTH (config->offload_info.bit_width)
+#else
+#define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
#endif
#define MAX_LENGTH_MIXER_CONTROL_IN_INT (128)
@@ -251,6 +288,28 @@
void audio_extn_compr_cap_deinit();
#endif
+#ifndef DTS_EAGLE
+#define audio_extn_dts_eagle_set_parameters(adev, parms) (0)
+#define audio_extn_dts_eagle_get_parameters(adev, query, reply) (0)
+#define audio_extn_dts_eagle_fade(adev, fade_in, out) (0)
+#define audio_extn_dts_create_state_notifier_node(stream_out) (0)
+#define audio_extn_dts_notify_playback_state(stream_out, has_video, sample_rate, \
+ channels, is_playing) (0)
+#define audio_extn_dts_remove_state_notifier_node(stream_out) (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev) (0)
+#else
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply);
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in, const struct stream_out *out);
+void audio_extn_dts_create_state_notifier_node(int stream_out);
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+ int channels, int is_playing);
+void audio_extn_dts_remove_state_notifier_node(int stream_out);
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev);
+#endif
+
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED)
void audio_extn_dolby_set_dmid(struct audio_device *adev);
#else
@@ -288,6 +347,34 @@
void audio_extn_ddp_set_parameters(struct audio_device *adev,
struct str_parms *parms);
void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev);
+
+#endif
+
+#ifndef HDMI_PASSTHROUGH_ENABLED
+#define audio_extn_dolby_update_passt_formats(adev, out) (0)
+#define audio_extn_dolby_update_passt_stream_configuration(adev, out) (0)
+#define audio_extn_dolby_is_passt_convert_supported(adev, out) (0)
+#define audio_extn_dolby_is_passt_supported(adev, out) (0)
+#define audio_extn_dolby_is_passthrough_stream(flags) (0)
+#define audio_extn_dolby_set_hdmi_config(adev, out) (0)
+#define audio_extn_dolby_get_passt_buffer_size(info) (0)
+#define audio_extn_dolby_set_passt_volume(out, mute) (0)
+#define audio_extn_dolby_set_passt_latency(out, latency) (0)
+#else
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+ struct stream_out *out);
+void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passthrough_stream(int flags);
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+ struct stream_out *out);
+int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info);
+int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute);
+int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency);
#endif
#ifndef HFP_ENABLED
@@ -373,11 +460,14 @@
typedef enum {
DAP_STATE_ON = 0,
DAP_STATE_BYPASS,
-};
+} dap_state;
#ifndef AUDIO_FORMAT_E_AC3_JOC
#define AUDIO_FORMAT_E_AC3_JOC 0x19000000UL
#endif
+int b64decode(char *inp, int ilen, uint8_t* outp);
+int b64encode(uint8_t *inp, int ilen, char* outp);
+
#ifndef KPI_OPTIMIZE_ENABLED
#define audio_extn_perf_lock_init() (0)
#define audio_extn_perf_lock_acquire() (0)
diff --git a/hal/audio_extn/dev_arbi.c b/hal/audio_extn/dev_arbi.c
index d3c01c5..d7ab5ff 100644
--- a/hal/audio_extn/dev_arbi.c
+++ b/hal/audio_extn/dev_arbi.c
@@ -128,7 +128,13 @@
{
static snd_aud_dev_mapping_t snd_aud_dev_map[] = {
{SND_DEVICE_OUT_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
- {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE}
+ {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
+ {SND_DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+ {SND_DEVICE_OUT_VOICE_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER},
+ {SND_DEVICE_OUT_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+ {SND_DEVICE_OUT_VOICE_HEADPHONES, AUDIO_DEVICE_OUT_WIRED_HEADPHONE},
+ {SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+ AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADPHONE}
};
audio_devices_t aud_device = AUDIO_DEVICE_NONE;
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index 6e0b0ee..92ef4ac 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2010 The Android Open Source Project
@@ -18,9 +18,8 @@
*/
#define LOG_TAG "audio_hw_dolby"
-#define LOG_NDEBUG 0
-#define LOG_NDDEBUG 0
-
+//#define LOG_NDEBUG 0
+//#define LOG_NDDEBUG 0
#include <errno.h>
#include <cutils/properties.h>
#include <stdlib.h>
@@ -408,6 +407,118 @@
}
#endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
+#ifdef HDMI_PASSTHROUGH_ENABLED
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+ struct stream_out *out) {
+ int32_t i = 0, ret = -ENOSYS;
+
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) ||
+ platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) {
+ out->supported_formats[i++] = AUDIO_FORMAT_AC3;
+ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
+ /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */
+ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
+ ret = 0;
+ }
+ ALOGV("%s: ret = %d", __func__, ret);
+ return ret;
+}
+
+bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+ struct stream_out *out) {
+
+ bool convert = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
+ if (!platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__);
+ convert = true;
+ }
+ break;
+ default:
+ ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
+ __func__, out->format);
+ break;
+ }
+ ALOGE("%s: convert %d", __func__, convert);
+ return convert;
+}
+
+bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+ struct stream_out *out) {
+ bool passt = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ if (platform_is_edid_supported_format(adev->platform, out->format)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_AC3:
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
+ || platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_E_AC3_JOC:
+ /* Check for DDP capability in edid for JOC contents.*/
+ if (platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ default:
+ ALOGV("%s:Passthrough not supported", __func__);
+ }
+ return passt;
+}
+
+void audio_extn_dolby_update_passt_stream_configuration(
+ struct audio_device *adev, struct stream_out *out) {
+ if (audio_extn_dolby_is_passt_supported(adev, out)) {
+ ALOGV("%s:PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH;
+ } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){
+ ALOGV("%s:PASSTHROUGH CONVERT", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
+ } else {
+ ALOGV("%s:NO PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = LEGACY_PCM;
+ }
+}
+
+bool audio_extn_dolby_is_passthrough_stream(int flags) {
+
+ if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+ return true;
+ return false;
+}
+
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+ struct stream_out *out) {
+ return platform_set_hdmi_config(out);
+}
+
+int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) {
+ return platform_get_compress_passthrough_buffer_size(info);
+}
+
+int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute) {
+ return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
+}
+
+int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) {
+ return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
+}
+#endif /* HDMI_PASSTHROUGH_ENABLED */
+
#ifdef DS1_DOLBY_DAP_ENABLED
void audio_extn_dolby_set_endpoint(struct audio_device *adev)
{
@@ -464,7 +575,7 @@
return;
property_get("dmid",c_dmid,"0");
- i_dmid = atoi(c_dmid);
+ i_dmid = atoll(c_dmid);
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
@@ -653,7 +764,7 @@
i_key = 0;
#endif
property_get("dmid",c_dmid,"0");
- i_dmid = atoi(c_dmid);
+ i_dmid = atoll(c_dmid);
ALOGV("%s Setting DS1 License, key:0x%x dmid %d",__func__, i_key,i_dmid);
dolby_license.dmid = i_dmid;
dolby_license.license_key = i_key;
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
new file mode 100644
index 0000000..52d7abb
--- /dev/null
+++ b/hal/audio_extn/dts_eagle.c
@@ -0,0 +1,501 @@
+/*
+ * (C) 2014 DTS, Inc.
+ *
+ * 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_dts_eagle"
+/*#define LOG_NDEBUG 0*/
+
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/str_parms.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sound/asound.h>
+#include <sound/audio_effects.h>
+#include <sound/devdep_params.h>
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+
+#ifdef DTS_EAGLE
+
+#define AUDIO_PARAMETER_KEY_DTS_EAGLE "DTS_EAGLE"
+#define STATE_NOTIFY_FILE "/data/misc/dts/stream"
+#define FADE_NOTIFY_FILE "/data/misc/dts/fade"
+#define DTS_EAGLE_KEY "DTS_EAGLE"
+#define DEVICE_NODE "/dev/snd/hwC0D3"
+#define MAX_LENGTH_OF_INTEGER_IN_STRING 13
+#define PARAM_GET_MAX_SIZE 512
+
+struct dts_eagle_param_desc_alsa {
+ int alsa_effect_ID;
+ struct dts_eagle_param_desc d;
+};
+
+static struct dts_eagle_param_desc_alsa *fade_in_data = NULL;
+static struct dts_eagle_param_desc_alsa *fade_out_data = NULL;
+static int32_t mDevices = 0;
+static int32_t mCurrDevice = 0;
+static const char* DTS_EAGLE_STR = DTS_EAGLE_KEY;
+
+static int do_DTS_Eagle_params_stream(struct stream_out *out, struct dts_eagle_param_desc_alsa *t, bool get) {
+ char mixer_string[128];
+ char mixer_str_query[128];
+ struct mixer_ctl *ctl;
+ struct mixer_ctl *query_ctl;
+ int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+ snprintf(mixer_string, sizeof(mixer_string), "%s %d", "Audio Effects Config", pcm_device_id);
+ ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_string);
+ if (!ctl) {
+ ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_string);
+ } else if (t) {
+ int size = t->d.size + sizeof(struct dts_eagle_param_desc_alsa);
+ ALOGD("DTS_EAGLE_HAL (%s): opened mixer %s", __func__, mixer_string);
+ if (get) {
+ ALOGD("DTS_EAGLE_HAL (%s): get request", __func__);
+ snprintf(mixer_str_query, sizeof(mixer_str_query), "%s %d", "Query Audio Effect Param", pcm_device_id);
+ query_ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_str_query);
+ if (!query_ctl) {
+ ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_str_query);
+ return -EINVAL;
+ }
+ mixer_ctl_set_array(query_ctl, t, size);
+ return mixer_ctl_get_array(ctl, t, size);
+ }
+ ALOGD("DTS_EAGLE_HAL (%s): set request", __func__);
+ return mixer_ctl_set_array(ctl, t, size);
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): parameter data NULL", __func__);
+ }
+ return -EINVAL;
+}
+
+static int do_DTS_Eagle_params(const struct audio_device *adev, struct dts_eagle_param_desc_alsa *t, bool get, const struct stream_out *out) {
+ struct listnode *node;
+ struct audio_usecase *usecase;
+ int ret = 0, sent = 0, tret = 0;
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ if (out) {
+ /* if valid out stream is given, then send params to this stream only */
+ tret = do_DTS_Eagle_params_stream(out, t, get);
+ if (tret < 0)
+ ret = tret;
+ else
+ sent = 1;
+ } else {
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ /* set/get eagle params for offload usecases only */
+ if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
+ tret = do_DTS_Eagle_params_stream(usecase->stream.out, t, get);
+ if (tret < 0)
+ ret = tret;
+ else
+ sent = 1;
+ }
+ }
+ }
+
+ if (!sent) {
+ int fd = open(DEVICE_NODE, O_RDWR);
+
+ if (get) {
+ ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to retrieve directly from cache", __func__);
+ t->d.device &= ~DTS_EAGLE_FLAG_ALSA_GET;
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to send directly to cache", __func__);
+ t->d.device |= DTS_EAGLE_FLAG_IOCTL_JUSTSETCACHE;
+ }
+
+ if (fd > 0) {
+ int cmd = get ? DTS_EAGLE_IOCTL_GET_PARAM : DTS_EAGLE_IOCTL_SET_PARAM;
+ if (ioctl(fd, cmd, &t->d) < 0) {
+ ALOGE("DTS_EAGLE_HAL (%s): error sending/getting param\n", __func__);
+ ret = -EINVAL;
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): sent/retrieved param\n", __func__);
+ }
+ close(fd);
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, DEVICE_NODE);
+ ret = -EINVAL;
+ }
+ }
+ return ret;
+}
+
+static void fade_node(bool need_data) {
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+ int fd, n = 0;
+ if ((fd = open(FADE_NOTIFY_FILE, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGV("No fade node, create one");
+ fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd < 0) {
+ ALOGE("DTS_EAGLE_HAL (%s): Creating fade notifier node failed", __func__);
+ return;
+ }
+ chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ }
+ char *str = need_data ? "need" : "have";
+ n = write(fd, str, strlen(str));
+ close(fd);
+ if (n > 0)
+ ALOGI("DTS_EAGLE_HAL (%s): fade notifier node set to \"%s\", %i bytes written", __func__, str, n);
+ else
+ ALOGE("DTS_EAGLE_HAL (%s): error writing to fade notifier node", __func__);
+}
+
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in, const struct stream_out *out) {
+ char prop[PROPERTY_VALUE_MAX];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter with fade %s requested", __func__, fade_in ? "in" : "out");
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return 0;
+
+ if (!fade_in_data || !fade_out_data)
+ fade_node(true);
+
+ if (fade_in) {
+ if (fade_in_data)
+ return do_DTS_Eagle_params(adev, fade_in_data, false, out);
+ } else {
+ if (fade_out_data)
+ return do_DTS_Eagle_params(adev, fade_out_data, false, out);
+ }
+ return 0;
+}
+
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev, struct str_parms *parms) {
+ int ret, val;
+ char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ int *data = NULL, id, size, offset, count, dev, dts_found = 0, fade_in = 0;
+ struct dts_eagle_param_desc_alsa *t2 = NULL, **t = &t2;
+
+ ret = str_parms_get_str(parms, "fade", value, sizeof(value));
+ if (ret >= 0) {
+ fade_in = atoi(value);
+ if (fade_in > 0) {
+ t = (fade_in == 1) ? &fade_in_data : &fade_out_data;
+ }
+ }
+
+ ret = str_parms_get_str(parms, "count", value, sizeof(value));
+ if (ret >= 0) {
+ count = atoi(value);
+ if (count > 1) {
+ int tmp_size = count * 32;
+ char *tmp = malloc(tmp_size+1);
+ data = malloc(sizeof(int) * count);
+ ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+ if (data && tmp) {
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, tmp, tmp_size);
+ if (ret >= 0) {
+ int idx = 0, tidx, tcnt = 0;
+ dts_found = 1;
+ do {
+ sscanf(&tmp[idx], "%i", &data[tcnt]);
+ tidx = strcspn(&tmp[idx], ",");
+ if (idx + tidx >= ret && tcnt < count-1) {
+ ALOGE("DTS_EAGLE_HAL (%s): malformed multi value string.", __func__);
+ dts_found = 0;
+ break;
+ }
+ ALOGD("DTS_EAGLE_HAL (%s): %i:%i (next %s)", __func__, tcnt, data[tcnt], &tmp[idx+tidx]);
+ idx += tidx + 1;
+ tidx = 0;
+ tcnt++;
+ } while (tcnt < count);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for multi count param parse failed.", __func__);
+ }
+ free(tmp);
+ }
+ }
+
+ if (!dts_found) {
+ data = malloc(sizeof(int));
+ if (data) {
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ *data = atoi(value);
+ dts_found = 1;
+ count = 1;
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): malformed value string.", __func__);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for param parse failed.", __func__);
+ }
+ }
+
+ if (dts_found) {
+ dts_found = 0;
+ ret = str_parms_get_str(parms, "id", value, sizeof(value));
+ if (ret >= 0) {
+ if (sscanf(value, "%x", &id) == 1) {
+ ret = str_parms_get_str(parms, "size", value, sizeof(value));
+ if (ret >= 0) {
+ size = atoi(value);
+ ret = str_parms_get_str(parms, "offset", value, sizeof(value));
+ if (ret >= 0) {
+ offset = atoi(value);
+ ret = str_parms_get_str(parms, "device", value, sizeof(value));
+ if (ret >= 0) {
+ dev = atoi(value);
+ dts_found = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (dts_found && count > 1 && size != (int)(count * sizeof(int))) {
+ ALOGE("DTS_EAGLE_HAL (%s): size/count mismatch (size = %i bytes, count = %i integers / %u bytes).", __func__, size, count, count*sizeof(int));
+ } else if (dts_found) {
+ ALOGI("DTS_EAGLE_HAL (%s): param detected: %s", __func__, str_parms_to_str(parms));
+ if (!(*t))
+ *t = (struct dts_eagle_param_desc_alsa*)malloc(sizeof(struct dts_eagle_param_desc_alsa) + size);
+ if (*t) {
+ (*t)->alsa_effect_ID = DTS_EAGLE_MODULE;
+ (*t)->d.id = id;
+ (*t)->d.size = size;
+ (*t)->d.offset = offset;
+ (*t)->d.device = dev;
+ memcpy((void*)((char*)*t + sizeof(struct dts_eagle_param_desc_alsa)), data, size);
+ ALOGD("DTS_EAGLE_HAL (%s): id: 0x%X, size: %d, offset: %d, device: %d", __func__,
+ (*t)->d.id, (*t)->d.size, (*t)->d.offset, (*t)->d.device);
+ if (!fade_in) {
+ ret = do_DTS_Eagle_params(adev, *t, false, NULL);
+ if (ret < 0)
+ ALOGE("DTS_EAGLE_HAL (%s): failed setting params in kernel with error %i", __func__, ret);
+ }
+ free(t2);
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for dsp structure failed.", __func__);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): param detected but failed parse: %s", __func__, str_parms_to_str(parms));
+ }
+ free(data);
+
+ if (fade_in > 0 && fade_in_data && fade_out_data)
+ fade_node(false);
+ }
+ ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+}
+
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply) {
+ int ret, val;
+ char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+ char params[PARAM_GET_MAX_SIZE];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return 0;
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ int *data = NULL, id = 0, size = 0, offset = 0,
+ count = 1, dev = 0, idx = 0, dts_found = 0, i = 0;
+ const size_t chars_4_int = 16;
+ ret = str_parms_get_str(query, "count", value, sizeof(value));
+ if (ret >= 0) {
+ count = atoi(value);
+ if (count > 1) {
+ ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+ } else {
+ count = 1;
+ }
+ }
+
+ ret = str_parms_get_str(query, "id", value, sizeof(value));
+ if (ret >= 0) {
+ if (sscanf(value, "%x", &id) == 1) {
+ ret = str_parms_get_str(query, "size", value, sizeof(value));
+ if (ret >= 0) {
+ size = atoi(value);
+ ret = str_parms_get_str(query, "offset", value, sizeof(value));
+ if (ret >= 0) {
+ offset = atoi(value);
+ ret = str_parms_get_str(query, "device", value, sizeof(value));
+ if (ret >= 0) {
+ dev = atoi(value);
+ dts_found = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (dts_found) {
+ ALOGI("DTS_EAGLE_HAL (%s): param (get) detected: %s", __func__, str_parms_to_str(query));
+ struct dts_eagle_param_desc_alsa *t = (struct dts_eagle_param_desc_alsa *)params;
+ if (t) {
+ char buf[chars_4_int*count];
+ t->alsa_effect_ID = DTS_EAGLE_MODULE;
+ t->d.id = id;
+ t->d.size = size;
+ t->d.offset = offset;
+ t->d.device = dev;
+ ALOGV("DTS_EAGLE_HAL (%s): id (get): 0x%X, size: %d, offset: %d, device: %d", __func__,
+ t->d.id, t->d.size, t->d.offset, t->d.device & 0x7FFFFFFF);
+ if ((sizeof(struct dts_eagle_param_desc_alsa) + size) > PARAM_GET_MAX_SIZE) {
+ ALOGE("%s: requested data too large", __func__);
+ return -1;
+ }
+ ret = do_DTS_Eagle_params(adev, t, true, NULL);
+ if (ret >= 0) {
+ data = (int*)(params + sizeof(struct dts_eagle_param_desc_alsa));
+ for (i = 0; i < count; i++)
+ idx += snprintf(&buf[idx], chars_4_int, "%i,", data[i]);
+ buf[idx > 0 ? idx-1 : 0] = 0;
+ ALOGD("DTS_EAGLE_HAL (%s): get result: %s", __func__, buf);
+ str_parms_add_int(reply, "size", size);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_DTS_EAGLE, buf);
+ str_parms_add_int(reply, "count", count);
+ snprintf(value, sizeof(value), "0x%x", id);
+ str_parms_add_str(reply, "id", value);
+ str_parms_add_int(reply, "device", dev);
+ str_parms_add_int(reply, "offset", offset);
+ ALOGV("DTS_EAGLE_HAL (%s): reply: %s", __func__, str_parms_to_str(reply));
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): failed getting params from kernel with error %i", __func__, ret);
+ return -1;
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for (get) dsp structure failed.", __func__);
+ return -1;
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): param (get) detected but failed parse: %s", __func__, str_parms_to_str(query));
+ return -1;
+ }
+ }
+
+ ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+ return 0;
+}
+
+void audio_extn_dts_create_state_notifier_node(int stream_out)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): create_state_notifier_node - stream_out: %d", __func__, stream_out);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): no file exists", __func__);
+ } else {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): a file with the same name exists, removing it before creating it", __func__);
+ close(fd);
+ remove(path);
+ }
+ if ((fd=creat(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node failed returned", __func__);
+ return;
+ }
+ chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node successful", __func__);
+ close(fd);
+ if (!fade_in_data || !fade_out_data)
+ fade_node(true);
+ }
+}
+
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+ int channels, int is_playing) {
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ char buf[1024];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): notify_playback_state - is_playing: %d", __func__, is_playing);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+ } else {
+ snprintf(buf, sizeof(buf), "has_video=%d;sample_rate=%d;channel_mode=%d;playback_state=%d",
+ has_video, sample_rate, channels, is_playing);
+ int n = write(fd, buf, strlen(buf));
+ if (n > 0)
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): write to state notifier node successful, bytes written: %d", __func__, n);
+ else
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): write state notifier node failed", __func__);
+ close(fd);
+ }
+ }
+}
+
+void audio_extn_dts_remove_state_notifier_node(int stream_out)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop)) && (stream_out)) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): remove_state_notifier_node: stream_out - %d", __func__, stream_out);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+ } else {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node successful, removing the file", __func__);
+ close(fd);
+ remove(path);
+ }
+ }
+}
+
+#endif /* DTS_EAGLE end */
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 5f4c6ba..9051334 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -165,6 +165,7 @@
in->config = st_ses_info->st_ses.config;
in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
in->is_st_session = true;
+ in->is_st_session_active = true;
ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
break;
}
diff --git a/hal/audio_extn/source_track.c b/hal/audio_extn/source_track.c
new file mode 100644
index 0000000..316e52d
--- /dev/null
+++ b/hal/audio_extn/source_track.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "source_track"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <math.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "voice_extn.h"
+#include <stdlib.h>
+#include <cutils/str_parms.h>
+
+#ifdef SOURCE_TRACKING_ENABLED
+/* Audio Paramater Key to identify the list of start angles.
+ * Starting angle (in degrees) defines the boundary starting angle for each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES "SoundFocus.start_angles"
+/* Audio Paramater Key to identify the list of enable flags corresponding to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS "SoundFocus.enable_sectors"
+/* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors.
+ */
+#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP "SoundFocus.gain_step"
+/* Audio Paramater Key to identify the list of voice activity detector outputs corresponding
+ * to each sector.
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD "SourceTrack.vad"
+/* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker
+ * (dominant source of speech).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH "SourceTrack.doa_speech"
+/* Audio Paramater Key to identify the list of directions (in degrees) of arrival for
+ * interferers (interfering noise sources).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE "SourceTrack.doa_noise"
+/* Audio Paramater Key to identify the list of sound strength indicators at each degree
+ * of the horizontal plane referred to by a full circle (360 degrees).
+ */
+#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY "SourceTrack.polar_activity"
+
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES 0x1
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS 0x2
+#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP 0x4
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD 0x8
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH 0x10
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE 0x20
+#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY 0x40
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \
+ (BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+
+#define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \
+ (BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\
+ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY)
+
+#define MAX_SECTORS 8
+#define MAX_STR_SIZE 2048
+
+struct audio_device_to_audio_interface audio_device_to_interface_table[];
+int audio_device_to_interface_table_len;
+
+struct sound_focus_param {
+ uint16_t start_angle[MAX_SECTORS];
+ uint8_t enable[MAX_SECTORS];
+ uint16_t gain_step;
+};
+
+struct source_tracking_param {
+ uint8_t vad[MAX_SECTORS];
+ uint16_t doa_speech;
+ uint16_t doa_noise[3];
+ uint8_t polar_activity[360];
+};
+
+static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name,
+ struct audio_device_to_audio_interface *table, int len)
+{
+ int ret = 0;
+ int i;
+
+ if (table == NULL) {
+ ALOGE("%s: table is NULL", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (mixer_ctl_name == NULL) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ for (i=0; i < len; i++) {
+ if (device == table[i].device) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH);
+ break;
+ }
+ }
+
+ if (i == len) {
+ ALOGE("%s: Audio Device not found in the table", __func__);
+
+ ret = -EINVAL;
+ }
+done:
+ return ret;
+}
+
+static bool is_stt_supported_snd_device(snd_device_t snd_device)
+{
+ bool ret = false;
+
+ switch (snd_device) {
+ case SND_DEVICE_IN_HANDSET_DMIC:
+ case SND_DEVICE_IN_HANDSET_DMIC_AEC:
+ case SND_DEVICE_IN_HANDSET_DMIC_NS:
+ case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS:
+ case SND_DEVICE_IN_HANDSET_STEREO_DMIC:
+ case SND_DEVICE_IN_HANDSET_QMIC:
+ case SND_DEVICE_IN_VOICE_DMIC:
+ case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE:
+ case SND_DEVICE_IN_HEADSET_MIC_FLUENCE:
+ case SND_DEVICE_IN_SPEAKER_DMIC:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC:
+ case SND_DEVICE_IN_SPEAKER_DMIC_NS:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE:
+ case SND_DEVICE_IN_SPEAKER_QMIC_AEC:
+ case SND_DEVICE_IN_SPEAKER_QMIC_NS:
+ case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
+ case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
+ ret = true;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+audio_devices_t get_input_audio_device(audio_devices_t device)
+{
+ audio_devices_t in_device = device;
+
+ switch (device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ break;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ in_device = AUDIO_DEVICE_IN_BACK_MIC;
+ break;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ in_device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ break;
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ break;
+ default:
+ break;
+ }
+
+ return in_device;
+}
+
+static int derive_mixer_ctl_from_usecase_intf(struct audio_device *adev,
+ char *mixer_ctl_name) {
+ struct audio_usecase *usecase = NULL;
+ audio_devices_t in_device;
+ int ret = 0;
+
+ if (mixer_ctl_name == NULL) {
+ ALOGE("%s: mixer_ctl_name is NULL", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (voice_is_in_call(adev)) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev,
+ get_usecase_id_from_usecase_type(adev, VOICE_CALL));
+ } else if (voice_extn_compress_voip_is_active(adev)) {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
+ } else {
+ strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH);
+ usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE));
+ }
+
+ if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
+ if (is_stt_supported_snd_device(usecase->in_snd_device)) {
+ in_device = get_input_audio_device(usecase->devices);
+ ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name,
+ audio_device_to_interface_table, audio_device_to_interface_table_len);
+ } else {
+ ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)",
+ __func__, platform_get_snd_device_name(usecase->in_snd_device));
+
+ ret = -EINVAL;
+ }
+ } else {
+ ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking",
+ __func__);
+
+ ret = -EINVAL;
+ }
+
+done:
+ return ret;
+}
+
+static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms)
+{
+ char *str;
+ char *value = NULL;
+ int val, len;
+ int ret = 0, err;
+ char *kv_pairs = str_parms_to_str(parms);
+
+ ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
+
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if(value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("%s: failed to allocate memory", __func__);
+
+ goto done;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY,
+ value, len);
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY);
+ ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY;
+ }
+
+done:
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ ALOGV("%s: returning bitmask = %d", __func__, ret);
+
+ return ret;
+}
+
+static int get_soundfocus_sourcetracking_data(struct audio_device *adev,
+ const int bitmask,
+ struct sound_focus_param *sound_focus_data,
+ struct source_tracking_param *source_tracking_data)
+{
+ struct mixer_ctl *ctl;
+ char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+ char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking";
+ int ret = -EINVAL;
+ int i, count;
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) {
+ /* Derive the mixer control name based on the use case and the audio interface
+ * for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not get Sound Focus Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, sound_focus_mixer_ctl_name);
+
+ ret = -EINVAL;
+ goto done;
+ } else {
+ ALOGV("%s: Getting Sound Focus Params", __func__);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct sound_focus_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) {
+ /* Derive the mixer control name based on the use case and the audio interface
+ * for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not get Source Tracking Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, source_tracking_mixer_ctl_name);
+
+ ret = -EINVAL;
+ goto done;
+ } else {
+ ALOGV("%s: Getting Source Tracking Params", __func__);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct source_tracking_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+
+done:
+ return ret;
+}
+
+static void send_soundfocus_sourcetracking_params(struct str_parms *reply,
+ const int bitmask,
+ const struct sound_focus_param sound_focus_data,
+ const struct source_tracking_param source_tracking_data)
+{
+ int i = 0, len = 0;
+ char value[MAX_STR_SIZE] = "";
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.start_angle[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value);
+ }
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (sound_focus_data.enable[i] == 0xFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.enable[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value);
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step);
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) {
+ for (i = 0; i < MAX_SECTORS; i++) {
+ if ((i >=4) && (source_tracking_data.vad[i] == 0xFF))
+ continue;
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.vad[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value);
+ }
+
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH)
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech);
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) {
+ snprintf(value, MAX_STR_SIZE,
+ "%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value);
+ }
+
+ strlcpy(value, "", sizeof(""));
+ if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) {
+ for (i = 0; i < 360; i++) {
+ if (i)
+ snprintf(value + strlen(value), MAX_STR_SIZE, ",");
+ snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.polar_activity[i]);
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value);
+ }
+}
+
+void audio_extn_source_track_get_parameters(struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ int bitmask = 0, ret = 0;
+ struct sound_focus_param sound_focus_data;
+ struct source_tracking_param source_tracking_data;
+
+ memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param));
+ memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param));
+
+ // Parse the input parameters string for Source Tracking keys
+ bitmask = parse_soundfocus_sourcetracking_keys(query);
+ if (bitmask) {
+ // Get the parameter values from the backend
+ ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data);
+ if (ret == 0) {
+ // Construct the return string with key, value pairs
+ send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data);
+ }
+ }
+}
+
+void audio_extn_source_track_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int len, ret, count;;
+ struct mixer_ctl *ctl;
+ char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
+ char *value = NULL;
+ char *kv_pairs = str_parms_to_str(parms);
+
+ len = strlen(kv_pairs);
+ value = (char*)calloc(len, sizeof(char));
+ if(value == NULL) {
+ ret = -ENOMEM;
+ ALOGE("%s: failed to allocate memory", __func__);
+
+ goto done;
+ }
+
+ // Parse the input parameter string for Source Tracking key, value pairs
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
+ value, len);
+ if (ret >= 0) {
+ char *saveptr, *tok;
+ int i = 0, val;
+ struct sound_focus_param sound_focus_param;
+
+ memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param));
+
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
+ tok = strtok_r(value, ",", &saveptr);
+ while ((i < MAX_SECTORS) && (tok != NULL)) {
+ if (sscanf(tok, "%d", &val) == 1) {
+ sound_focus_param.start_angle[i++] = (uint16_t)val;
+ }
+ tok = strtok_r(NULL, ",", &saveptr);
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
+ value, len);
+ if (ret >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
+ tok = strtok_r(value, ",", &saveptr);
+ i = 0;
+ while ((i < MAX_SECTORS) && (tok != NULL)) {
+ if (sscanf(tok, "%d", &val) == 1) {
+ sound_focus_param.enable[i++] = (uint8_t)val;
+ }
+ tok = strtok_r(NULL, ",", &saveptr);
+ }
+ } else {
+ ALOGE("%s: SoundFocus.enable_sectors key not found", __func__);
+
+ goto done;
+ }
+
+ ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val);
+ if (ret >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
+ sound_focus_param.gain_step = (uint16_t)val;
+ } else {
+ ALOGE("%s: SoundFocus.gain_step key not found", __func__);
+
+ goto done;
+ }
+
+ /* Derive the mixer control name based on the use case and the audio h/w
+ * interface name for the corresponding audio device
+ */
+ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
+ if (ret != 0) {
+ ALOGE("%s: Could not set Sound Focus Params", __func__);
+
+ goto done;
+ } else {
+ ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, sound_focus_mixer_ctl_name);
+
+ goto done;
+ } else {
+ ALOGV("%s: Setting Sound Focus Params", __func__);
+
+ for (i = 0; i < MAX_SECTORS;i++) {
+ ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param.start_angle[i]);
+ }
+ for (i = 0; i < MAX_SECTORS;i++) {
+ ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param.enable[i]);
+ }
+ ALOGV("%s: gain_step = %d", __func__, sound_focus_param.gain_step);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct sound_focus_param)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__);
+
+ goto done;
+ }
+
+ // Set the parameters on the mixer control derived above
+ ret = mixer_ctl_set_array(ctl, (void *)&sound_focus_param, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params", __func__);
+
+ goto done;
+ }
+ }
+ }
+
+done:
+ free(kv_pairs);
+ if(value != NULL)
+ free(value);
+ return;
+}
+#endif /* SOURCE_TRACKING_ENABLED end */
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index a350198..312be97 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 - 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -141,7 +141,7 @@
handle.spkr_in_use = true;
else {
handle.spkr_in_use = false;
- clock_gettime(CLOCK_MONOTONIC, &handle.spkr_last_time_used);
+ clock_gettime(CLOCK_BOOTTIME, &handle.spkr_last_time_used);
}
}
@@ -181,7 +181,7 @@
*sec = 0;
return true;
} else {
- clock_gettime(CLOCK_MONOTONIC, &temp);
+ clock_gettime(CLOCK_BOOTTIME, &temp);
*sec = temp.tv_sec - handle.spkr_last_time_used.tv_sec;
return false;
}
@@ -475,9 +475,15 @@
pcm_close(handle.pcm_tx);
handle.pcm_tx = NULL;
/* Clear TX calibration to handset mic */
- platform_send_audio_calibration(adev->platform,
- SND_DEVICE_IN_HANDSET_MIC,
- platform_get_default_app_type(adev->platform), 8000);
+ if (disable_tx) {
+ uc_info_tx->id = USECASE_AUDIO_RECORD;
+ uc_info_tx->type = PCM_CAPTURE;
+ uc_info_tx->in_snd_device = SND_DEVICE_IN_HANDSET_MIC;
+ uc_info_tx->out_snd_device = SND_DEVICE_NONE;
+ platform_send_audio_calibration(adev->platform,
+ uc_info_tx,
+ platform_get_default_app_type(adev->platform), 8000);
+ }
if (!status.status) {
protCfg.mode = MSM_SPKR_PROT_CALIBRATED;
protCfg.r0[SP_V2_SPKR_1] = status.r0[SP_V2_SPKR_1];
@@ -810,6 +816,7 @@
struct audio_usecase *uc_info_tx;
struct audio_device *adev = handle.adev_handle;
int32_t pcm_dev_tx_id = -1, ret = 0;
+ bool disable_tx = false;
ALOGV("%s: Entry", __func__);
/* cancel speaker calibration */
@@ -836,6 +843,7 @@
uc_info_tx->out_snd_device = SND_DEVICE_NONE;
handle.pcm_tx = NULL;
list_add_tail(&adev->usecase_list, &uc_info_tx->list);
+ disable_tx = true;
enable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
enable_audio_route(adev, uc_info_tx);
@@ -862,14 +870,24 @@
exit:
/* Clear VI feedback cal and replace with handset MIC */
- platform_send_audio_calibration(adev->platform,
- SND_DEVICE_IN_HANDSET_MIC,
- platform_get_default_app_type(adev->platform), 8000);
- if (ret) {
+ if (disable_tx) {
+ uc_info_tx->id = USECASE_AUDIO_RECORD;
+ uc_info_tx->type = PCM_CAPTURE;
+ uc_info_tx->in_snd_device = SND_DEVICE_IN_HANDSET_MIC;
+ uc_info_tx->out_snd_device = SND_DEVICE_NONE;
+ platform_send_audio_calibration(adev->platform,
+ uc_info_tx,
+ platform_get_default_app_type(adev->platform), 8000);
+ }
+ if (ret) {
if (handle.pcm_tx)
pcm_close(handle.pcm_tx);
handle.pcm_tx = NULL;
list_remove(&uc_info_tx->list);
+ uc_info_tx->id = USECASE_AUDIO_SPKR_CALIB_TX;
+ uc_info_tx->type = PCM_CAPTURE;
+ uc_info_tx->in_snd_device = SND_DEVICE_IN_CAPTURE_VI_FEEDBACK;
+ uc_info_tx->out_snd_device = SND_DEVICE_NONE;
disable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
disable_audio_route(adev, uc_info_tx);
free(uc_info_tx);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index a4ea134..13e3138 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -111,8 +111,8 @@
// Look for the first control named ".*Playback Volume" that isn't for a microphone
for (i = 0; i < num_ctls; i++) {
ctl = mixer_get_ctl(usbMixer, i);
- if (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
- !strstr((const char *)mixer_ctl_get_name(ctl), "Mic")) {
+ if ((ctl) && (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
+ !strstr((const char *)mixer_ctl_get_name(ctl), "Mic"))) {
break;
}
}
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 273a194..82b596f 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -33,6 +33,7 @@
#include "platform.h"
#include "platform_api.h"
#include "audio_extn.h"
+#include "voice.h"
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
@@ -48,6 +49,9 @@
#define STRING_TO_ENUM(string) { #string, string }
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define BASE_TABLE_SIZE 64
+#define MAX_BASEINDEX_LEN 256
+
struct string_to_enum {
const char *name;
uint32_t value;
@@ -60,12 +64,14 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
#ifdef INCALL_MUSIC_ENABLED
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
#endif
#ifdef COMPRESS_VOIP_ENABLED
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
#endif
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
};
const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -94,9 +100,24 @@
STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_APE),
+ STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
#endif
};
+static char bTable[BASE_TABLE_SIZE] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L',
+ 'M','N','O','P','Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f','g','h','i','j',
+ 'k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7',
+ '8','9','+','/'
+};
+
static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
const char *name)
{
@@ -394,6 +415,7 @@
ss_info = node_to_item(node_i, struct stream_sample_rate, list);
if ((sample_rate <= ss_info->sample_rate) &&
(bit_width == so_info->app_type_cfg.bit_width)) {
+
app_type_cfg->app_type = so_info->app_type_cfg.app_type;
app_type_cfg->sample_rate = ss_info->sample_rate;
app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
@@ -439,6 +461,9 @@
if ((24 == bit_width) &&
(devices & AUDIO_DEVICE_OUT_SPEAKER)) {
+ int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+ if (-ENOSYS != bw)
+ bit_width = (uint32_t)bw;
sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
}
@@ -495,8 +520,8 @@
if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
(usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
(usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
- (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
- ALOGV("%s: a playback path where app type cfg is not required", __func__);
+ (!is_offload_usecase(usecase->id))) {
+ ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id);
rc = 0;
goto exit_send_app_type_cfg;
}
@@ -535,8 +560,12 @@
app_type_cfg[len++] = out->app_type_cfg.app_type;
app_type_cfg[len++] = acdb_dev_id;
- app_type_cfg[len++] = sample_rate;
-
+ if (((out->format == AUDIO_FORMAT_E_AC3) ||
+ (out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
+ (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+ app_type_cfg[len++] = sample_rate * 4;
+ else
+ app_type_cfg[len++] = sample_rate;
mixer_ctl_set_array(ctl, app_type_cfg, len);
ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
__func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
@@ -567,3 +596,145 @@
}
}
+// Base64 Encode and Decode
+// Not all features supported. This must be used only with following conditions.
+// Decode Modes: Support with and without padding
+// CRLF not handling. So no CRLF in string to decode.
+// Encode Modes: Supports only padding
+int b64decode(char *inp, int ilen, uint8_t* outp)
+{
+ int i, j, k, ii, num;
+ int rem, pcnt;
+ uint32_t res=0;
+ uint8_t getIndex[MAX_BASEINDEX_LEN];
+ uint8_t tmp, cflag;
+
+ if(inp == NULL || outp == NULL || ilen <= 0) {
+ ALOGE("[%s] received NULL pointer or zero length",__func__);
+ return -1;
+ }
+
+ memset(getIndex, MAX_BASEINDEX_LEN-1, sizeof(getIndex));
+ for(i=0;i<BASE_TABLE_SIZE;i++) {
+ getIndex[(uint8_t)bTable[i]] = (uint8_t)i;
+ }
+ getIndex[(uint8_t)'=']=0;
+
+ j=0;k=0;
+ num = ilen/4;
+ rem = ilen%4;
+ if(rem==0)
+ num = num-1;
+ cflag=0;
+ for(i=0; i<num; i++) {
+ res=0;
+ for(ii=0;ii<4;ii++) {
+ res = res << 6;
+ tmp = getIndex[(uint8_t)inp[j++]];
+ res = res | tmp;
+ cflag = cflag | tmp;
+ }
+ outp[k++] = (res >> 16)&0xFF;
+ outp[k++] = (res >> 8)&0xFF;
+ outp[k++] = res & 0xFF;
+ }
+
+ // Handle last bytes special
+ pcnt=0;
+ if(rem == 0) {
+ //With padding or full data
+ res = 0;
+ for(ii=0;ii<4;ii++) {
+ if(inp[j] == '=')
+ pcnt++;
+ res = res << 6;
+ tmp = getIndex[(uint8_t)inp[j++]];
+ res = res | tmp;
+ cflag = cflag | tmp;
+ }
+ outp[k++] = res >> 16;
+ if(pcnt == 2)
+ goto done;
+ outp[k++] = (res>>8)&0xFF;
+ if(pcnt == 1)
+ goto done;
+ outp[k++] = res&0xFF;
+ } else {
+ //without padding
+ res = 0;
+ for(i=0;i<rem;i++) {
+ res = res << 6;
+ tmp = getIndex[(uint8_t)inp[j++]];
+ res = res | tmp;
+ cflag = cflag | tmp;
+ }
+ for(i=rem;i<4;i++) {
+ res = res << 6;
+ pcnt++;
+ }
+ outp[k++] = res >> 16;
+ if(pcnt == 2)
+ goto done;
+ outp[k++] = (res>>8)&0xFF;
+ if(pcnt == 1)
+ goto done;
+ outp[k++] = res&0xFF;
+ }
+done:
+ if(cflag == 0xFF) {
+ ALOGE("[%s] base64 decode failed. Invalid character found %s",
+ __func__, inp);
+ return 0;
+ }
+ return k;
+}
+
+int b64encode(uint8_t *inp, int ilen, char* outp)
+{
+ int i,j,k, num;
+ int rem=0;
+ uint32_t res=0;
+
+ if(inp == NULL || outp == NULL || ilen<=0) {
+ ALOGE("[%s] received NULL pointer or zero input length",__func__);
+ return -1;
+ }
+
+ num = ilen/3;
+ rem = ilen%3;
+ j=0;k=0;
+ for(i=0; i<num; i++) {
+ //prepare index
+ res = inp[j++]<<16;
+ res = res | inp[j++]<<8;
+ res = res | inp[j++];
+ //get output map from index
+ outp[k++] = (char) bTable[(res>>18)&0x3F];
+ outp[k++] = (char) bTable[(res>>12)&0x3F];
+ outp[k++] = (char) bTable[(res>>6)&0x3F];
+ outp[k++] = (char) bTable[res&0x3F];
+ }
+
+ switch(rem) {
+ case 1:
+ res = inp[j++]<<16;
+ outp[k++] = (char) bTable[res>>18];
+ outp[k++] = (char) bTable[(res>>12)&0x3F];
+ //outp[k++] = '=';
+ //outp[k++] = '=';
+ break;
+ case 2:
+ res = inp[j++]<<16;
+ res = res | inp[j++]<<8;
+ outp[k++] = (char) bTable[res>>18];
+ outp[k++] = (char) bTable[(res>>12)&0x3F];
+ outp[k++] = (char) bTable[(res>>6)&0x3F];
+ //outp[k++] = '=';
+ break;
+ default:
+ break;
+ }
+done:
+ outp[k] = '\0';
+ return k;
+}