Merge "configs: enable 3D Audio on msmnile/sdm710"
diff --git a/configs/apq8098_latv/apq8098_latv.mk b/configs/apq8098_latv/apq8098_latv.mk
index 088f3ed..582cd5c 100644
--- a/configs/apq8098_latv/apq8098_latv.mk
+++ b/configs/apq8098_latv/apq8098_latv.mk
@@ -253,10 +253,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msm8998/msm8998.mk b/configs/msm8998/msm8998.mk
index d91fa57..368a7ec 100644
--- a/configs/msm8998/msm8998.mk
+++ b/configs/msm8998/msm8998.mk
@@ -212,10 +212,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmnile/mixer_paths_tavil.xml b/configs/msmnile/mixer_paths_tavil.xml
old mode 100755
new mode 100644
index 2e0f9c5..dc4f0b4
--- a/configs/msmnile/mixer_paths_tavil.xml
+++ b/configs/msmnile/mixer_paths_tavil.xml
@@ -1937,6 +1937,14 @@
<ctl name="SLIM0_RX_VI_FB_RCH_MUX" value="SLIM4_TX" />
</path>
+ <path name="speaker-protected-qrd">
+ <ctl name="AIF4_VI Mixer SPKR_VI_2" value="1" />
+ <ctl name="SLIM_4_TX Format" value="PACKED_16B" />
+ <path name="speaker-qrd" />
+ <ctl name="VI_FEED_TX Channels" value="One" />
+ <ctl name="SLIM0_RX_VI_FB_LCH_MUX" value="SLIM4_TX" />
+ </path>
+
<path name="voice-speaker-protected">
<ctl name="AIF4_VI Mixer SPKR_VI_1" value="1" />
<ctl name="SLIM_4_TX Format" value="PACKED_16B" />
@@ -1945,6 +1953,10 @@
<ctl name="SLIM0_RX_VI_FB_LCH_MUX" value="SLIM4_TX" />
</path>
+ <path name="voice-speaker-protected-qrd">
+ <path name="speaker-protected-qrd" />
+ </path>
+
<path name="voice-speaker-stereo-protected">
<path name="speaker-protected" />
</path>
diff --git a/configs/msmnile/msmnile.mk b/configs/msmnile/msmnile.mk
index aaa18f7..14a8128 100644
--- a/configs/msmnile/msmnile.mk
+++ b/configs/msmnile/msmnile.mk
@@ -67,6 +67,7 @@
AUDIO_FEATURE_ENABLED_DLKM := true
AUDIO_FEATURE_ENABLED_USB_BURST_MODE := true
AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
+AUDIO_FEATURE_ENABLED_BATTERY_LISTENER := true
##AUDIO_FEATURE_FLAGS
ifneq ($(strip $(TARGET_USES_QSSI)), true)
@@ -200,10 +201,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml b/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
index 55dd42f..1e3d4e7 100644
--- a/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
+++ b/configs/msmnile/sound_trigger_mixer_paths_wcd9340.xml
@@ -348,4 +348,11 @@
<ctl name="EC Reference SampleRate" value="48000"/>
</path>
+ <path name="echo-reference a2dp">
+ <ctl name="AUDIO_REF_EC_UL1 MUX" value="SLIM_7_RX"/>
+ <ctl name="EC Reference Channels" value="Two"/>
+ <ctl name="EC Reference Bit Format" value="S16_LE"/>
+ <ctl name="EC Reference SampleRate" value="48000"/>
+ </path>
+
</mixer>
diff --git a/configs/msmnile/sound_trigger_platform_info.xml b/configs/msmnile/sound_trigger_platform_info.xml
index 27a6c04..34c3401 100644
--- a/configs/msmnile/sound_trigger_platform_info.xml
+++ b/configs/msmnile/sound_trigger_platform_info.xml
@@ -42,6 +42,7 @@
<param support_device_switch="false" />
<!-- Transition will only occur if execution_type="DYNAMIC" -->
<param transit_to_adsp_on_playback="false" />
+ <param transit_to_adsp_on_battery_charging="false" />
<!-- Below backend params must match with port used in mixer path file -->
<!-- param used to configure backend sample rate, format and channels -->
<param backend_port_name="SLIM_0_TX" />
diff --git a/configs/msmnile_au/msmnile_au.mk b/configs/msmnile_au/msmnile_au.mk
index 111cbd2..933ba80 100644
--- a/configs/msmnile_au/msmnile_au.mk
+++ b/configs/msmnile_au/msmnile_au.mk
@@ -194,10 +194,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/msmsteppe/msmsteppe.mk b/configs/msmsteppe/msmsteppe.mk
index 4fa0eb7..4c482b9 100644
--- a/configs/msmsteppe/msmsteppe.mk
+++ b/configs/msmsteppe/msmsteppe.mk
@@ -191,10 +191,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/sdm660/sdm660.mk b/configs/sdm660/sdm660.mk
index 555340a..e961a0e 100644
--- a/configs/sdm660/sdm660.mk
+++ b/configs/sdm660/sdm660.mk
@@ -220,10 +220,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/configs/sdm710/sdm710.mk b/configs/sdm710/sdm710.mk
index 4116232..dc21eb4 100644
--- a/configs/sdm710/sdm710.mk
+++ b/configs/sdm710/sdm710.mk
@@ -69,6 +69,7 @@
AUDIO_FEATURE_ENABLED_RAS := true
AUDIO_FEATURE_ENABLED_SND_MONITOR := true
AUDIO_FEATURE_ENABLED_DLKM := true
+AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
##AUDIO_FEATURE_FLAGS
ifneq ($(strip $(TARGET_USES_QSSI)), true)
@@ -241,10 +242,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
@@ -266,4 +263,4 @@
android.hardware.audio@2.0-service \
android.hardware.audio@2.0-impl \
android.hardware.audio.effect@2.0-impl \
- android.hardware.soundtrigger@2.0-impl
+ android.hardware.soundtrigger@2.1-impl
diff --git a/configs/sdm710/sound_trigger_platform_info.xml b/configs/sdm710/sound_trigger_platform_info.xml
index cb39f39..b37753e 100644
--- a/configs/sdm710/sound_trigger_platform_info.xml
+++ b/configs/sdm710/sound_trigger_platform_info.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--- Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. -->
+<!--- Copyright (c) 2013-2018, 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 -->
@@ -78,6 +78,23 @@
<!-- wdsp_fluence_type: fluence disabled: "NONE" -->
<!-- fluence enabled: "FLUENCE_DMIC", "FLUENCE_TMIC", "FLUENCE_QMIC" -->
<param wdsp_fluence_type="NONE" />
+ <arm_ss_usecase>
+ <!-- Options are "KEYWORD_DETECTION", "USER_VERIFICATION", "CUSTOM_DETECTION" -->
+ <param sm_detection_type= "KEYWORD_DETECTION" />
+ <param sm_id="0x2" />
+ <param module_lib="libcapiv2svacnn.so"/>
+ <param sample_rate="16000"/>
+ <param bit_wdith="16"/>
+ <param channel_count="1"/>
+ </arm_ss_usecase>
+ <arm_ss_usecase>
+ <param sm_detection_type= "USER_VERIFICATION" />
+ <param sm_id="0x4" />
+ <param module_lib="libcapiv2vop.so"/>
+ <param sample_rate="16000"/>
+ <param bit_wdith="16"/>
+ <param channel_count="1"/>
+ </arm_ss_usecase>
<gcs_usecase>
<param uid="0x1" />
<!-- module_id, instance_id, param_id -->
diff --git a/configs/sdm845/sdm845.mk b/configs/sdm845/sdm845.mk
index bcfe3af..7650379 100644
--- a/configs/sdm845/sdm845.mk
+++ b/configs/sdm845/sdm845.mk
@@ -207,10 +207,6 @@
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.hw.aac.encoder=true
-#Disable FM a2dp concurrency
-PRODUCT_PROPERTY_OVERRIDES += \
-vendor.fm.a2dp.conc.disabled=true
-
#audio becoming noisy intent broadcast delay
PRODUCT_PROPERTY_OVERRIDES += \
vendor.audio.noisy.broadcast.delay=600
diff --git a/hal/Android.mk b/hal/Android.mk
index fb03343..94c21bd 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -405,6 +405,15 @@
LOCAL_CFLAGS += -DUSB_BURST_MODE_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_BATTERY_LISTENER)), true)
+ LOCAL_CFLAGS += -DBATTERY_LISTENER_ENABLED
+ LOCAL_SRC_FILES += audio_extn/battery_listener.cpp
+ LOCAL_SHARED_LIBRARIES += android.hardware.health@1.0 android.hardware.health@2.0 \
+ libhidltransport libbase libhidlbase libhwbinder \
+ libutils android.hardware.power@1.2
+ LOCAL_STATIC_LIBRARIES := libhealthhalutils
+endif
+
LOCAL_CFLAGS += -Wall -Werror
LOCAL_COPY_HEADERS_TO := mm-audio
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index d228123..0d0a48b 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -55,6 +55,7 @@
#define ENC_MEDIA_FMT_AAC 0x00010DA6
#define ENC_MEDIA_FMT_APTX 0x000131ff
#define ENC_MEDIA_FMT_APTX_HD 0x00013200
+#define ENC_MEDIA_FMT_APTX_AD 0x00013204
#define ENC_MEDIA_FMT_SBC 0x00010BF2
#define ENC_MEDIA_FMT_CELT 0x00013221
#define ENC_MEDIA_FMT_LDAC 0x00013224
@@ -112,6 +113,10 @@
// Instance identifier for A2DP
#define MAX_INSTANCE_ID (UINT32_MAX / 2)
+#define SAMPLING_RATE_48K 48000
+#define SAMPLING_RATE_441K 44100
+#define CH_STEREO 2
+#define CH_MONO 1
/*
* Below enum values are extended from audio_base.h to
* to keep encoder codec type local to bthost_ipc
@@ -129,8 +134,33 @@
#endif
ENC_CODEC_TYPE_LDAC = AUDIO_FORMAT_LDAC, // 0x23000000UL
ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
+ ENC_CODEC_TYPE_APTX_AD = 620756992u, // 0x25000000UL
}enc_codec_t;
+/*
+ * enums which describes the APTX Adaptive
+ * channel mode, these values are used by encoder
+ */
+ typedef enum {
+ APTX_AD_CHANNEL_UNCHANGED = -1,
+ APTX_AD_CHANNEL_JOINT_STEREO = 0, // default
+ APTX_AD_CHANNEL_MONO = 1,
+ APTX_AD_CHANNEL_DUAL_MONO = 2,
+ APTX_AD_CHANNEL_STEREO_TWS = 4,
+ APTX_AD_CHANNEL_EARBUD = 8,
+} enc_aptx_ad_channel_mode;
+
+/*
+ * enums which describes the APTX Adaptive
+ * sampling frequency, these values are used
+ * by encoder
+ */
+typedef enum {
+ APTX_AD_SR_UNCHANGED = 0x0,
+ APTX_AD_48 = 0x1, // 48 KHz default
+ APTX_AD_44_1 = 0x2, // 44.1kHz
+} enc_aptx_ad_s_rate;
+
typedef int (*audio_stream_open_t)(void);
typedef int (*audio_stream_close_t)(void);
typedef int (*audio_start_stream_t)(void);
@@ -215,6 +245,7 @@
bool is_a2dp_offload_supported;
bool is_handoff_in_progress;
bool is_aptx_dual_mono_supported;
+ bool is_aptx_adaptive;
/* Adaptive bitrate config for A2DP codecs */
struct a2dp_abr_config abr_config;
};
@@ -373,6 +404,27 @@
struct aptx_v2_enc_cfg_ext_t aptx_v2_cfg;
} __attribute__ ((packed));
+/* APTX AD structure */
+struct aptx_ad_enc_cfg_ext_t
+{
+ uint32_t sampling_freq;
+ uint32_t mtu;
+ uint32_t channel_mode;
+ uint32_t min_sink_modeA;
+ uint32_t max_sink_modeA;
+ uint32_t min_sink_modeB;
+ uint32_t max_sink_modeB;
+ uint32_t min_sink_modeC;
+ uint32_t max_sink_modeC;
+} __attribute__ ((packed));
+
+struct aptx_ad_enc_cfg_t
+{
+ struct custom_enc_cfg_t custom_cfg;
+ struct aptx_ad_enc_cfg_ext_t aptx_ad_cfg;
+ struct abr_enc_cfg_t abr_cfg;
+} __attribute__ ((packed));
+
struct ldac_specific_enc_cfg_t
{
uint32_t bit_rate;
@@ -421,6 +473,22 @@
} audio_aptx_default_config;
typedef struct {
+ uint8_t sampling_rate;
+ uint8_t channel_mode;
+ uint16_t mtu;
+ uint8_t min_sink_modeA;
+ uint8_t max_sink_modeA;
+ uint8_t min_sink_modeB;
+ uint8_t max_sink_modeB;
+ uint8_t min_sink_modeC;
+ uint8_t max_sink_modeC;
+ uint8_t TTP_modeA_low;
+ uint8_t TTP_modeA_high;
+ uint8_t TTP_modeB_low;
+ uint8_t TTP_modeB_high;
+} audio_aptx_ad_config;
+
+typedef struct {
uint16_t sampling_rate;
uint8_t channels;
uint32_t bitrate;
@@ -430,6 +498,7 @@
typedef union {
audio_aptx_default_config *default_cfg;
audio_aptx_dual_mono_config *dual_mono_cfg;
+ audio_aptx_ad_config *ad_cfg;
} audio_aptx_encoder_config;
/* Information about BT AAC encoder configuration
@@ -509,6 +578,9 @@
ALOGD("%s: ldac offload supported\n",__func__);
a2dp.is_a2dp_offload_supported = true;
break;
+ } else if( strcmp(tok, "aptxadaptive") == 0) {
+ ALOGD("%s: aptx adaptive offload supported\n",__func__);
+ a2dp.is_a2dp_offload_supported = true;
}
tok = strtok_r(NULL, "-", &saveptr);
};
@@ -1021,6 +1093,73 @@
}
#ifndef LINUX_ENABLED
+static int update_aptx_ad_dsp_config(struct aptx_ad_enc_cfg_t *aptx_dsp_cfg,
+ audio_aptx_encoder_config *aptx_bt_cfg)
+{
+ int ret = 0;
+
+ if(aptx_dsp_cfg == NULL || aptx_bt_cfg == NULL) {
+ ALOGE("Invalid param, aptx_dsp_cfg %p aptx_bt_cfg %p",
+ aptx_dsp_cfg, aptx_bt_cfg);
+ return -EINVAL;
+ }
+
+ memset(aptx_dsp_cfg, 0x0, sizeof(struct aptx_ad_enc_cfg_t));
+ aptx_dsp_cfg->custom_cfg.enc_format = ENC_MEDIA_FMT_APTX_AD;
+
+
+ aptx_dsp_cfg->aptx_ad_cfg.sampling_freq = aptx_bt_cfg->ad_cfg->sampling_rate;
+ aptx_dsp_cfg->aptx_ad_cfg.mtu = aptx_bt_cfg->ad_cfg->mtu;
+ aptx_dsp_cfg->aptx_ad_cfg.channel_mode = aptx_bt_cfg->ad_cfg->channel_mode;
+ aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeA = aptx_bt_cfg->ad_cfg->min_sink_modeA;
+ aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeA = aptx_bt_cfg->ad_cfg->max_sink_modeA;
+ aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeB = aptx_bt_cfg->ad_cfg->min_sink_modeB;
+ aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeB = aptx_bt_cfg->ad_cfg->max_sink_modeB;
+ aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeC = aptx_bt_cfg->ad_cfg->min_sink_modeC;
+ aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeC = aptx_bt_cfg->ad_cfg->max_sink_modeC;
+ aptx_dsp_cfg->abr_cfg.imc_info.direction = IMC_RECEIVE;
+ aptx_dsp_cfg->abr_cfg.imc_info.enable = IMC_ENABLE;
+ aptx_dsp_cfg->abr_cfg.imc_info.purpose = IMC_PURPOSE_ID_BT_INFO;
+ aptx_dsp_cfg->abr_cfg.imc_info.comm_instance = a2dp.abr_config.imc_instance;
+
+
+ switch(aptx_dsp_cfg->aptx_ad_cfg.channel_mode) {
+ case APTX_AD_CHANNEL_UNCHANGED:
+ case APTX_AD_CHANNEL_JOINT_STEREO:
+ case APTX_AD_CHANNEL_DUAL_MONO:
+ case APTX_AD_CHANNEL_STEREO_TWS:
+ case APTX_AD_CHANNEL_EARBUD:
+ default:
+ a2dp.enc_channels = CH_STEREO;
+ aptx_dsp_cfg->custom_cfg.num_channels = CH_STEREO;
+ aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+ aptx_dsp_cfg->custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+ break;
+ case APTX_AD_CHANNEL_MONO:
+ a2dp.enc_channels = CH_MONO;
+ aptx_dsp_cfg->custom_cfg.num_channels = CH_MONO;
+ aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+ break;
+ }
+ switch(aptx_dsp_cfg->aptx_ad_cfg.sampling_freq) {
+ case APTX_AD_SR_UNCHANGED:
+ case APTX_AD_48:
+ default:
+ a2dp.enc_sampling_rate = SAMPLING_RATE_48K;
+ aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_48K;
+ break;
+ case APTX_AD_44_1:
+ a2dp.enc_sampling_rate = SAMPLING_RATE_441K;
+ aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_441K;
+ break;
+ }
+ ALOGV("Successfully updated APTX AD enc format with \
+ samplingrate: %d channels:%d",
+ aptx_dsp_cfg->custom_cfg.sample_rate,
+ aptx_dsp_cfg->custom_cfg.num_channels);
+
+ return ret;
+}
static int update_aptx_dsp_config_v2(struct aptx_enc_cfg_t *aptx_dsp_cfg,
audio_aptx_encoder_config *aptx_bt_cfg)
{
@@ -1118,8 +1257,13 @@
#ifndef LINUX_ENABLED
struct aptx_enc_cfg_t aptx_dsp_cfg;
- mixer_size = sizeof(struct aptx_enc_cfg_t);
- sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+ struct aptx_ad_enc_cfg_t aptx_ad_dsp_cfg;
+ if(a2dp.is_aptx_adaptive)
+ mixer_size = sizeof(struct aptx_ad_enc_cfg_t);
+ else {
+ mixer_size = sizeof(struct aptx_enc_cfg_t);
+ sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+ }
#else
struct custom_enc_cfg_t aptx_dsp_cfg;
mixer_size = sizeof(struct custom_enc_cfg_t);
@@ -1134,7 +1278,11 @@
}
#ifndef LINUX_ENABLED
- ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
+ if(a2dp.is_aptx_adaptive) {
+ ret = update_aptx_ad_dsp_config(&aptx_ad_dsp_cfg, aptx_bt_cfg);
+ sample_rate_backup = aptx_ad_dsp_cfg.custom_cfg.sample_rate;
+ } else
+ ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
#else
ret = update_aptx_dsp_config_v1(&aptx_dsp_cfg, aptx_bt_cfg);
#endif
@@ -1143,7 +1291,11 @@
is_configured = false;
goto fail;
}
- ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
+ if(a2dp.is_aptx_adaptive)
+ ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_ad_dsp_cfg,
+ mixer_size);
+ else
+ ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
mixer_size);
if (ret != 0) {
ALOGE("%s: Failed to set APTX encoder config", __func__);
@@ -1157,7 +1309,10 @@
is_configured = false;
goto fail;
} else {
- ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+ if (a2dp.is_aptx_adaptive)
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
+ else
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
if (ret != 0) {
ALOGE("%s: Failed to set bit format to encoder", __func__);
is_configured = false;
@@ -1165,7 +1320,10 @@
}
}
is_configured = true;
- a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
+ if (a2dp.is_aptx_adaptive)
+ a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_AD;
+ else
+ a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
fail:
/*restore sample rate */
if(!is_configured)
@@ -1465,6 +1623,7 @@
// ABR disabled by default for all codecs
a2dp.abr_config.is_abr_enabled = false;
+ a2dp.is_aptx_adaptive = false;
switch(codec_type) {
case ENC_CODEC_TYPE_SBC:
@@ -1519,6 +1678,18 @@
(configure_ldac_enc_format((audio_ldac_encoder_config *)codec_info) &&
configure_a2dp_decoder_format(ENC_CODEC_TYPE_LDAC));
break;
+ case ENC_CODEC_TYPE_APTX_AD:
+ ALOGD(" Received APTX AD encoder supported BT device");
+ if (!instance_id || instance_id > MAX_INSTANCE_ID)
+ instance_id = MAX_INSTANCE_ID;
+ a2dp.abr_config.imc_instance = instance_id--;
+ a2dp.abr_config.is_abr_enabled = true; // for APTX Adaptive ABR is Always on
+ a2dp.is_aptx_adaptive = true;
+ aptx_encoder_cfg.ad_cfg = (audio_aptx_ad_config *)codec_info;
+ is_configured =
+ (configure_aptx_enc_format(&aptx_encoder_cfg) &&
+ configure_a2dp_decoder_format(ENC_MEDIA_FMT_APTX_AD));
+ break;
default:
ALOGD(" Received Unsupported encoder formar");
is_configured = false;
@@ -1819,6 +1990,7 @@
a2dp.is_a2dp_offload_supported = false;
a2dp.is_handoff_in_progress = false;
a2dp.is_aptx_dual_mono_supported = false;
+ a2dp.is_aptx_adaptive = false;
a2dp.abr_config.is_abr_enabled = false;
a2dp.abr_config.abr_started = false;
a2dp.abr_config.imc_instance = 0;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e7d2386..7231955 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -41,6 +41,7 @@
#include <cutils/str_parms.h>
#include "adsp_hdlr.h"
#include "ip_hdlr_intf.h"
+#include "battery_listener.h"
#ifndef AFE_PROXY_ENABLED
#define AUDIO_DEVICE_OUT_PROXY 0x40000
@@ -156,10 +157,13 @@
#define audio_extn_get_anc_enabled() (0)
#define audio_extn_should_use_fb_anc() (0)
#define audio_extn_should_use_handset_anc(in_channels) (0)
+#define audio_extn_set_aanc_noise_level(adev, parms) (0)
#else
bool audio_extn_get_anc_enabled(void);
bool audio_extn_should_use_fb_anc(void);
bool audio_extn_should_use_handset_anc(int in_channels);
+void audio_extn_set_aanc_noise_level(struct audio_device *adev,
+ struct str_parms *parms);
#endif
#ifndef VBAT_MONITOR_ENABLED
@@ -378,6 +382,7 @@
#define audio_extn_sound_trigger_deinit(adev) (0)
#define audio_extn_sound_trigger_update_device_status(snd_dev, event) (0)
#define audio_extn_sound_trigger_update_stream_status(uc_info, event) (0)
+#define audio_extn_sound_trigger_update_battery_status(charging) (0)
#define audio_extn_sound_trigger_set_parameters(adev, parms) (0)
#define audio_extn_sound_trigger_get_parameters(adev, query, reply) (0)
#define audio_extn_sound_trigger_check_and_get_session(in) (0)
@@ -399,6 +404,7 @@
st_event_type_t event);
void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
st_event_type_t event);
+void audio_extn_sound_trigger_update_battery_status(bool charging);
void audio_extn_sound_trigger_set_parameters(struct audio_device *adev,
struct str_parms *parms);
void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in);
diff --git a/hal/audio_extn/battery_listener.cpp b/hal/audio_extn/battery_listener.cpp
new file mode 100644
index 0000000..582e9e6
--- /dev/null
+++ b/hal/audio_extn/battery_listener.cpp
@@ -0,0 +1,247 @@
+/*
+* Copyright (c) 2018, 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 "audio_hw::BatteryListener"
+#include <log/log.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hardware/health/2.0/IHealth.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <hidl/HidlTransportSupport.h>
+#include <thread>
+#include "battery_listener.h"
+
+using android::hardware::interfacesEqual;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V1_0::toString;
+using android::hardware::health::V2_0::get_health_service;
+using android::hardware::health::V2_0::HealthInfo;
+using android::hardware::health::V2_0::IHealth;
+using android::hardware::health::V2_0::Result;
+using android::hidl::manager::V1_0::IServiceManager;
+using namespace std::literals::chrono_literals;
+
+namespace android {
+
+#define GET_HEALTH_SVC_RETRY_CNT 5
+#define GET_HEALTH_SVC_WAIT_TIME_MS 500
+
+struct BatteryListenerImpl : public hardware::health::V2_0::IHealthInfoCallback,
+ public hardware::hidl_death_recipient {
+ typedef std::function<void(bool)> cb_fn_t;
+ BatteryListenerImpl(cb_fn_t cb);
+ virtual ~BatteryListenerImpl ();
+ virtual hardware::Return<void> healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info);
+ virtual void serviceDied(uint64_t cookie,
+ const wp<hidl::base::V1_0::IBase>& who);
+ bool isCharging() {
+ std::lock_guard<std::mutex> _l(mLock);
+ return statusToBool(mStatus);
+ }
+ private:
+ sp<hardware::health::V2_0::IHealth> mHealth;
+ status_t init();
+ BatteryStatus mStatus;
+ cb_fn_t mCb;
+ std::mutex mLock;
+ std::condition_variable mCond;
+ std::unique_ptr<std::thread> mThread;
+ bool mDone;
+ bool statusToBool(const BatteryStatus &s) const {
+ return (s == BatteryStatus::CHARGING) ||
+ (s == BatteryStatus::FULL);
+ }
+};
+
+status_t BatteryListenerImpl::init()
+{
+ int tries = 0;
+
+ if (mHealth != NULL)
+ return INVALID_OPERATION;
+
+ do {
+ mHealth = get_health_service();
+ if (mHealth != NULL)
+ break;
+ usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
+ tries++;
+ } while(tries < GET_HEALTH_SVC_RETRY_CNT);
+
+ if (mHealth == NULL) {
+ ALOGE("no health service found, retries %d", tries);
+ return NO_INIT;
+ } else {
+ ALOGI("Get health service in %d tries", tries);
+ }
+ mStatus = BatteryStatus::UNKNOWN;
+ auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) {
+ if (r != Result::SUCCESS) {
+ ALOGE("batterylistener: cannot get battery status");
+ return;
+ }
+ mStatus = status;
+ });
+ if (!ret.isOk())
+ ALOGE("batterylistener: get charge status transaction error");
+
+ if (mStatus == BatteryStatus::UNKNOWN)
+ ALOGW("batterylistener: init: invalid battery status");
+ mDone = false;
+ mThread = std::make_unique<std::thread>([this]() {
+ std::unique_lock<std::mutex> l(mLock);
+ BatteryStatus local_status = mStatus;
+ while (!mDone) {
+ if (local_status == mStatus) {
+ mCond.wait(l);
+ continue;
+ }
+ local_status = mStatus;
+ switch (local_status) {
+ // NOT_CHARGING is a special event that indicates, a battery is connected,
+ // but not charging. This is seen for approx a second
+ // after charger is plugged in. A charging event is eventually received.
+ // We must try to avoid an unnecessary cb to HAL
+ // only to call it again shortly.
+ // An option to deal with this transient event would be to ignore this.
+ // Or process this event with a slight delay (i.e cancel this event
+ // if a different event comes in within a timeout
+ case BatteryStatus::NOT_CHARGING : {
+ auto mStatusnot_ncharging =
+ [this, local_status]() { return mStatus != local_status; };
+ mCond.wait_for(l, 3s, mStatusnot_ncharging);
+ if (mStatusnot_ncharging()) // i.e event changed
+ break;
+ }
+ default:
+ bool c = statusToBool(local_status);
+ ALOGI("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING");
+ l.unlock();
+ mCb(c);
+ l.lock();
+ break;
+ }
+ }
+ });
+ mHealth->registerCallback(this);
+ mHealth->linkToDeath(this, 0 /* cookie */);
+ return NO_ERROR;
+}
+
+BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
+ mCb(cb)
+{
+ init();
+}
+
+BatteryListenerImpl::~BatteryListenerImpl()
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth != NULL)
+ mHealth->unlinkToDeath(this);
+ }
+ mDone = true;
+ mThread->join();
+}
+
+void BatteryListenerImpl::serviceDied(uint64_t cookie __unused,
+ const wp<hidl::base::V1_0::IBase>& who)
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) {
+ ALOGE("health not initialized or unknown interface died");
+ return;
+ }
+ ALOGI("health service died, reinit");
+ mDone = true;
+ }
+ mThread->join();
+ std::lock_guard<std::mutex> _l(mLock);
+ init();
+}
+
+// this callback seems to be a SYNC callback and so
+// waits for return before next event is issued.
+// therefore we need not have a queue to process
+// NOT_CHARGING and CHARGING concurrencies.
+// Replace single var by a list if this assumption is broken
+Return<void> BatteryListenerImpl::healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info)
+{
+ ALOGV("healthInfoChanged: %d", info.legacy.batteryStatus);
+ std::unique_lock<std::mutex> l(mLock);
+ if (info.legacy.batteryStatus != mStatus) {
+ mStatus = info.legacy.batteryStatus;
+ mCond.notify_one();
+ }
+ return Void();
+}
+
+static sp<BatteryListenerImpl> batteryListener;
+status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb)
+{
+ batteryListener = new BatteryListenerImpl(cb);
+ return NO_ERROR;
+}
+
+status_t batteryPropertiesListenerDeinit()
+{
+ batteryListener.clear();
+ return OK;
+}
+
+bool batteryPropertiesListenerIsCharging()
+{
+ return batteryListener->isCharging();
+}
+
+} // namespace android
+
+extern "C" {
+void audio_extn_battery_properties_listener_init(battery_status_change_fn_t fn)
+{
+ android::batteryPropertiesListenerInit([=](bool charging) {
+ fn(charging);
+ });
+}
+
+void audio_extn_battery_properties_listener_deinit()
+{
+ android::batteryPropertiesListenerDeinit();
+}
+
+bool audio_extn_battery_properties_is_charging()
+{
+ return android::batteryPropertiesListenerIsCharging();
+}
+
+} // extern C
diff --git a/hal/audio_extn/battery_listener.h b/hal/audio_extn/battery_listener.h
new file mode 100644
index 0000000..2fcd010
--- /dev/null
+++ b/hal/audio_extn/battery_listener.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2018, 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.
+*/
+#ifdef BATTERY_LISTENER_ENABLED
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef void (* battery_status_change_fn_t)(bool);
+void audio_extn_battery_properties_listener_init(battery_status_change_fn_t fn);
+void audio_extn_battery_properties_listener_deinit();
+bool audio_extn_battery_properties_is_charging();
+#ifdef __cplusplus
+}
+#endif
+#else
+#define audio_extn_battery_properties_listener_init(fn) do { } while(0)
+#define audio_extn_battery_properties_listener_deinit() do { } while(0)
+#define audio_extn_battery_properties_is_charging() (false)
+#endif
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 0fa30d0..b2e1bef 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -80,6 +80,7 @@
AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
+ AUDIO_EVENT_BATTERY_STATUS_CHANGED,
} audio_event_type_t;
typedef enum {
@@ -500,12 +501,16 @@
__func__, uc_info->id, uc_info->type, event, raise_event);
if (raise_event) {
if (uc_info->type == PCM_PLAYBACK) {
+ if (uc_info->stream.out)
+ ev_info.device_info.device = uc_info->stream.out->devices;
+ else
+ ev_info.device_info.device = AUDIO_DEVICE_OUT_SPEAKER;
switch(event) {
case ST_EVENT_STREAM_FREE:
- st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, NULL);
+ st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
break;
case ST_EVENT_STREAM_BUSY:
- st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, NULL);
+ st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
break;
default:
ALOGW("%s:invalid event %d, for usecase %d",
@@ -525,6 +530,18 @@
}
}
+void audio_extn_sound_trigger_update_battery_status(bool charging)
+{
+ struct audio_event_info ev_info;
+
+ if (!st_dev || st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
+ return;
+
+ ev_info.u.value = charging;
+ st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
+}
+
+
void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
struct str_parms *params)
{
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 34a9937..fa36879 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -7390,6 +7390,15 @@
return ret;
}
+void adev_on_battery_status_changed(bool charging)
+{
+ pthread_mutex_lock(&adev->lock);
+ ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
+ adev->is_charging = charging;
+ audio_extn_sound_trigger_update_battery_status(charging);
+ pthread_mutex_unlock(&adev->lock);
+}
+
static int adev_open(const hw_module_t *module, const char *name,
hw_device_t **device)
{
@@ -7635,8 +7644,16 @@
pthread_mutex_lock(&adev->lock);
audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
adev->card_status = CARD_STATUS_ONLINE;
- pthread_mutex_unlock(&adev->lock);
+ audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
+ /*
+ * if the battery state callback happens before charging can be queried,
+ * it will be guarded with the adev->lock held in the cb function and so
+ * the callback value will reflect the latest state
+ */
+ adev->is_charging = audio_extn_battery_properties_is_charging();
audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
+ audio_extn_sound_trigger_update_battery_status(adev->is_charging);
+ pthread_mutex_unlock(&adev->lock);
/* Allocate memory for Device config params */
adev->device_cfg_params = (struct audio_device_config_param*)
calloc(platform_get_max_codec_backend(),
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 497b5c8..c29f7b8 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -486,6 +486,7 @@
unsigned int cur_wfd_channels;
bool bt_wb_speech_enabled;
bool allow_afe_proxy_usage;
+ bool is_charging; // from battery listener
int snd_card;
card_status_t card_status;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 41d6e6b..6e0a75a 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -233,6 +233,11 @@
static int max_be_dai_names = 0;
static const struct be_dai_name_struct *be_dai_name_table;
+struct snd_device_to_mic_map {
+ struct mic_info microphones[AUDIO_MICROPHONE_MAX_COUNT];
+ size_t mic_count;
+};
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -298,6 +303,9 @@
struct listnode acdb_meta_key_list;
bool use_generic_handset;
struct acdb_init_data_v4 acdb_init_data;
+ uint32_t declared_mic_count;
+ struct audio_microphone_characteristic_t microphones[AUDIO_MICROPHONE_MAX_COUNT];
+ struct snd_device_to_mic_map mic_map[SND_DEVICE_MAX];
};
static bool is_external_codec = false;
@@ -935,6 +943,8 @@
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
{TO_NAME_INDEX(USECASE_AUDIO_EC_REF_LOOPBACK)},
{TO_NAME_INDEX(USECASE_AUDIO_A2DP_ABR_FEEDBACK)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_VOIP)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
};
#define NO_COLS 2
@@ -2073,6 +2083,8 @@
if(snd_card_name) {
if ((!strncmp(snd_card_name, "msm8953-snd-card-mtp",
sizeof("msm8953-snd-card-mtp")) ||
+ (!strncmp(snd_card_name, "msm8953-sku4-snd-card",
+ sizeof("msm8953-sku4-snd-card"))) ||
(!strncmp(snd_card_name, "msm8952-skum-snd-card",
sizeof("msm8952-skum-snd-card"))))) {
*is_wsa_combo_supported = true;
@@ -2280,6 +2292,7 @@
my_data->hw_dep_fd = -1;
my_data->mono_speaker = SPKR_1;
my_data->voice_speaker_stereo = false;
+ my_data->declared_mic_count = 0;
be_dai_name_table = NULL;
@@ -5735,7 +5748,7 @@
rate_str = "KHZ_8";
break;
case 11025:
- rate_str = "HZ_11P025";
+ rate_str = "KHZ_11P025";
break;
case 16000:
rate_str = "KHZ_16";
@@ -7433,6 +7446,7 @@
(!strcmp(snd_card_name, "msm8976-skun-snd-card")) ||
(!strcmp(snd_card_name, "msm8953-snd-card-mtp")) ||
(!strcmp(snd_card_name, "msm8953-sku4-snd-card")) ||
+ (!strcmp(snd_card_name, "sdm439-sku1-snd-card")) ||
(!strcmp(snd_card_name, "sdm439-snd-card-mtp")))
return 1;
else
@@ -8117,25 +8131,103 @@
return id_string;
}
-bool platform_set_microphone_characteristic(void *platform __unused,
- struct audio_microphone_characteristic_t mic __unused) {
- return -ENOSYS;
+bool platform_set_microphone_characteristic(void *platform,
+ struct audio_microphone_characteristic_t mic) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (my_data->declared_mic_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+ ALOGE("mic number is more than maximum number");
+ return false;
+ }
+ for (size_t ch = 0; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+ mic.channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ }
+ my_data->microphones[my_data->declared_mic_count++] = mic;
+ return true;
}
-int platform_get_microphones(void *platform __unused,
- struct audio_microphone_characteristic_t *mic_array __unused,
- size_t *mic_count __unused) {
- return -ENOSYS;
+int platform_get_microphones(void *platform,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (mic_count == NULL)
+ return -EINVAL;
+ if (mic_array == NULL)
+ return -EINVAL;
+
+ if (*mic_count == 0) {
+ *mic_count = my_data->declared_mic_count;
+ return 0;
+ }
+
+ size_t max_mic_count = *mic_count;
+ size_t actual_mic_count = 0;
+ for (size_t i = 0; i < max_mic_count && i < my_data->declared_mic_count; i++) {
+ mic_array[i] = my_data->microphones[i];
+ actual_mic_count++;
+ }
+ *mic_count = actual_mic_count;
+ ALOGV("%s: returning number of mics %d", __func__, (int)*mic_count);
+ return 0;
}
-bool platform_set_microphone_map(void *platform __unused, snd_device_t in_snd_device __unused,
- const struct mic_info *info __unused) {
- return false;
+bool platform_set_microphone_map(void *platform, snd_device_t in_snd_device,
+ const struct mic_info *info) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (in_snd_device < SND_DEVICE_IN_BEGIN || in_snd_device >= SND_DEVICE_IN_END) {
+ ALOGE("%s: Sound device not valid", __func__);
+ return false;
+ }
+ size_t m_count = my_data->mic_map[in_snd_device].mic_count++;
+ if (m_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+ ALOGE("%s: Microphone count is greater than max allowed value", __func__);
+ my_data->mic_map[in_snd_device].mic_count--;
+ return false;
+ }
+ my_data->mic_map[in_snd_device].microphones[m_count] = *info;
+ return true;
}
-int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused,
- audio_usecase_t usecase __unused,
- struct audio_microphone_characteristic_t *mic_array __unused,
- size_t *mic_count __unused) {
- return -ENOSYS;
+int platform_get_active_microphones(void *platform, unsigned int channels,
+ audio_usecase_t uc_id,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_usecase *usecase = get_usecase_from_list(my_data->adev, uc_id);
+ if (mic_count == NULL || mic_array == NULL || usecase == NULL) {
+ return -EINVAL;
+ }
+ size_t max_mic_count = my_data->declared_mic_count;
+ size_t actual_mic_count = 0;
+
+ snd_device_t active_input_snd_device =
+ platform_get_input_snd_device(platform, usecase->stream.in->device);
+ if (active_input_snd_device == SND_DEVICE_NONE) {
+ ALOGI("%s: No active microphones found", __func__);
+ goto end;
+ }
+
+ size_t active_mic_count = my_data->mic_map[active_input_snd_device].mic_count;
+ struct mic_info *m_info = my_data->mic_map[active_input_snd_device].microphones;
+
+ for (size_t i = 0; i < active_mic_count; i++) {
+ unsigned int channels_for_active_mic = channels;
+ if (channels_for_active_mic > m_info[i].channel_count) {
+ channels_for_active_mic = m_info[i].channel_count;
+ }
+ for (size_t j = 0; j < max_mic_count; j++) {
+ if (strcmp(my_data->microphones[j].device_id,
+ m_info[i].device_id) == 0) {
+ mic_array[actual_mic_count] = my_data->microphones[j];
+ for (size_t ch = 0; ch < channels_for_active_mic; ch++) {
+ mic_array[actual_mic_count].channel_mapping[ch] =
+ m_info[i].channel_mapping[ch];
+ }
+ actual_mic_count++;
+ break;
+ }
+ }
+ }
+end:
+ *mic_count = actual_mic_count;
+ return 0;
}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 92f92aa..aeab831 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -920,6 +920,8 @@
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_SILENCE)},
{TO_NAME_INDEX(USECASE_AUDIO_A2DP_ABR_FEEDBACK)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_VOIP)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
};
#define NO_COLS 2
@@ -5712,7 +5714,7 @@
rate_str = "KHZ_8";
break;
case 11025:
- rate_str = "HZ_11P025";
+ rate_str = "KHZ_11P025";
break;
case 16000:
rate_str = "KHZ_16";
diff --git a/hal/platform_info.c b/hal/platform_info.c
index d27d689..dca577b 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -569,7 +569,7 @@
ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
goto done;
}
- strcpy(microphone.device_id, attr[curIdx++]);
+ strlcpy(microphone.device_id, attr[curIdx++], sizeof(microphone.device_id));
if (strcmp(attr[curIdx++], "type")) {
ALOGE("%s: device not found", __func__);
@@ -590,13 +590,13 @@
ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
goto done;
}
- strcpy(microphone.address, attr[curIdx++]);
+ strlcpy(microphone.address, attr[curIdx++], sizeof(microphone.address));
if (strlen(microphone.address) == 0) {
// If the address is empty, populate the address according to device type.
if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ strlcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS, sizeof(microphone.address));
} else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
- strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
+ strlcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS, sizeof(microphone.address));
}
}
@@ -648,7 +648,8 @@
ALOGE("%s: frequencies not found", __func__);
goto done;
}
- char *token = strtok((char *)attr[curIdx++], " ");
+ char *context = NULL;
+ char *token = strtok_r((char *)attr[curIdx++], " ", &context);
uint32_t num_frequencies = 0;
while (token) {
microphone.frequency_responses[0][num_frequencies++] = atof(token);
@@ -656,14 +657,14 @@
ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
goto done;
}
- token = strtok(NULL, " ");
+ token = strtok_r(NULL, " ", &context);
}
if (strcmp(attr[curIdx++], "responses")) {
ALOGE("%s: responses not found", __func__);
goto done;
}
- token = strtok((char *)attr[curIdx++], " ");
+ token = strtok_r((char *)attr[curIdx++], " ", &context);
uint32_t num_responses = 0;
while (token) {
microphone.frequency_responses[1][num_responses++] = atof(token);
@@ -671,7 +672,7 @@
ALOGE("%s: num %u of response is too large", __func__, num_responses);
goto done;
}
- token = strtok(NULL, " ");
+ token = strtok_r(NULL, " ", &context);
}
if (num_frequencies != num_responses
@@ -717,7 +718,8 @@
ALOGE("%s: orientation not found", __func__);
goto done;
}
- char *token = strtok((char *)attr[curIdx++], " ");
+ char *context = NULL;
+ char *token = strtok_r((char *)attr[curIdx++], " ", &context);
float orientation[3];
uint32_t idx = 0;
while (token) {
@@ -726,7 +728,7 @@
ALOGE("%s: orientation invalid", __func__);
goto done;
}
- token = strtok(NULL, " ");
+ token = strtok_r(NULL, " ", &context);
}
if (idx != 3) {
ALOGE("%s: orientation invalid", __func__);
@@ -746,7 +748,8 @@
ALOGE("%s: geometric_location not found", __func__);
goto done;
}
- char *token = strtok((char *)attr[curIdx++], " ");
+ char *context = NULL;
+ char *token = strtok_r((char *)attr[curIdx++], " ", &context);
float geometric_location[3];
uint32_t idx = 0;
while (token) {
@@ -755,7 +758,7 @@
ALOGE("%s: geometric_location invalid", __func__);
goto done;
}
- token = strtok(NULL, " ");
+ token = strtok_r(NULL, " ", &context);
}
if (idx != 3) {
ALOGE("%s: geometric_location invalid", __func__);
@@ -813,7 +816,8 @@
ALOGE("%s: channel_mapping not found", __func__);
goto on_error;
}
- const char *token = strtok((char *)attr[curIdx++], " ");
+ char *context = NULL;
+ const char *token = strtok_r((char *)attr[curIdx++], " ", &context);
uint32_t idx = 0;
while (token) {
if (!find_enum_by_string(mic_channel_mapping, token,
@@ -823,7 +827,7 @@
__func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
goto on_error;
}
- token = strtok(NULL, " ");
+ token = strtok_r(NULL, " ", &context);
}
microphone.channel_count = idx;