summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-11-04 13:59:25 -0800
committerSteve Kondik <steve@cyngn.com>2015-11-04 13:59:25 -0800
commite995fd7d13ae3945ba1aaf8545d2b4c161b7ffc2 (patch)
treed6482860c733321f8eb0d5f694c172a5892a16a9
parent789da11e6c3c65b8e9c5265e8a43263606364f48 (diff)
parente4881591c9272456a9f1869a24669c192e4c4980 (diff)
downloadandroid_hardware_qcom_audio-e995fd7d13ae3945ba1aaf8545d2b4c161b7ffc2.tar.gz
android_hardware_qcom_audio-e995fd7d13ae3945ba1aaf8545d2b4c161b7ffc2.tar.bz2
android_hardware_qcom_audio-e995fd7d13ae3945ba1aaf8545d2b4c161b7ffc2.zip
Merge branch 'LA.BF64.1.2.2_rb4.6' of git://codeaurora.org/platform/hardware/qcom/audio into cm-13.0
Change-Id: Id805aac771873aae865d263f2f99d6941d8e1bf8
-rw-r--r--hal/audio_extn/audio_defs.h2
-rw-r--r--hal/audio_hw.c108
-rw-r--r--hal/audio_hw.h22
-rw-r--r--hal/msm8916/platform.c31
-rw-r--r--hal/msm8974/platform.c26
-rw-r--r--hal/msm8974/platform.h1
-rw-r--r--policy_hal/Android.mk8
-rw-r--r--[-rwxr-xr-x]policy_hal/AudioPolicyManager.cpp170
-rw-r--r--policy_hal/AudioPolicyManager.h23
-rw-r--r--visualizer/offload_visualizer.c38
10 files changed, 307 insertions, 122 deletions
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 9d801120..1c5da54e 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -101,4 +101,6 @@
/* Query if Proxy can be Opend */
#define AUDIO_PARAMETER_KEY_CAN_OPEN_PROXY "can_open_proxy"
+#define AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED "is_hw_dec_session_allowed"
+
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 5db37540..13dc8c75 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.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.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -166,7 +166,8 @@ struct pcm_config pcm_config_afe_proxy_record = {
const char * const use_case_table[AUDIO_USECASE_MAX] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
- [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
+ [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
+ [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
#ifdef MULTIPLE_OFFLOAD_ENABLED
[USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
@@ -554,7 +555,7 @@ int enable_audio_route(struct audio_device *adev,
audio_extn_utils_send_app_type_cfg(usecase);
strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
platform_add_backend_name(mixer_path, snd_device);
- ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
+ ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
audio_route_apply_and_update_path(adev->audio_route, mixer_path);
ALOGV("%s: exit", __func__);
return 0;
@@ -576,7 +577,7 @@ int disable_audio_route(struct audio_device *adev,
snd_device = usecase->out_snd_device;
strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
platform_add_backend_name(mixer_path, snd_device);
- ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
+ ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
audio_route_reset_and_update_path(adev->audio_route, mixer_path);
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
@@ -632,8 +633,7 @@ int enable_snd_device(struct audio_device *adev,
return -EINVAL;
}
} else {
- ALOGV("%s: snd_device(%d: %s)", __func__,
- snd_device, device_name);
+ ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
/* due to the possibility of calibration overwrite between listen
and audio, notify listen hal before audio calibration is sent */
audio_extn_sound_trigger_update_device_status(snd_device,
@@ -678,8 +678,7 @@ int disable_snd_device(struct audio_device *adev,
}
if (adev->snd_dev_ref_cnt[snd_device] == 0) {
- ALOGV("%s: snd_device(%d: %s)", __func__,
- snd_device, device_name);
+ ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
/* exit usb play back thread */
if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
@@ -1249,9 +1248,20 @@ int start_input_stream(struct stream_in *in)
}
break;
}
+
+ ALOGV("%s: pcm_prepare", __func__);
+ ret = pcm_prepare(in->pcm);
+ if (ret < 0) {
+ ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+ pcm_close(in->pcm);
+ in->pcm = NULL;
+ goto error_open;
+ }
+
audio_extn_perf_lock_release();
- ALOGV("%s: exit", __func__);
+ ALOGD("%s: exit", __func__);
+
return ret;
error_open:
@@ -1445,7 +1455,7 @@ static void *offload_thread_loop(void *context)
lock_output_stream(out);
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
- if (send_callback) {
+ if (send_callback && out->offload_callback) {
ALOGVV("%s: sending offload_callback event %d", __func__, event);
out->offload_callback(event, NULL, out->offload_cookie);
}
@@ -1733,8 +1743,20 @@ int start_output_stream(struct stream_out *out)
}
break;
}
+
platform_set_stream_channel_map(adev->platform, out->channel_mask,
out->pcm_device_id);
+
+ ALOGV("%s: pcm_prepare", __func__);
+ if (pcm_is_ready(out->pcm)) {
+ ret = pcm_prepare(out->pcm);
+ if (ret < 0) {
+ ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+ pcm_close(out->pcm);
+ out->pcm = NULL;
+ goto error_open;
+ }
+ }
} else {
platform_set_stream_channel_map(adev->platform, out->channel_mask,
out->pcm_device_id);
@@ -1780,7 +1802,9 @@ int start_output_stream(struct stream_out *out)
audio_extn_check_and_set_dts_hpx_state(adev);
}
}
- ALOGV("%s: exit", __func__);
+
+ ALOGD("%s: exit", __func__);
+
return 0;
error_open:
stop_output_stream(out);
@@ -1916,6 +1940,9 @@ static int out_standby(struct audio_stream *stream)
lock_output_stream(out);
if (!out->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, out->handle);
+
pthread_mutex_lock(&adev->lock);
amplifier_output_stream_standby((struct audio_stream_out *) stream);
@@ -2266,6 +2293,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
out->standby = true;
goto exit;
}
+ if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
+ adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
}
if (is_offload_usecase(out->usecase)) {
@@ -2312,15 +2341,24 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
if (out->pcm) {
if (out->muted)
memset((void *)buffer, 0, bytes);
+
ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, out->handle);
+
if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
else
ret = pcm_write(out->pcm, (void *)buffer, bytes);
+
if (ret < 0)
ret = -errno;
else if (ret == 0)
out->written += bytes / (out->config.channels * sizeof(short));
+
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, out->handle);
}
}
@@ -2620,6 +2658,9 @@ static int in_standby(struct audio_stream *stream)
}
if (!in->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
+
pthread_mutex_lock(&adev->lock);
amplifier_input_stream_standby((struct audio_stream_in *) stream);
@@ -2775,8 +2816,13 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
}
}
in->standby = 0;
+ if (adev->adm_register_input_stream)
+ adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
}
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, in->capture_handle);
+
if (in->pcm) {
if (audio_extn_ssr_get_enabled() && (audio_extn_ssr_get_stream() == in))
ret = audio_extn_ssr_read(stream, buffer, bytes);
@@ -2790,6 +2836,9 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
ret = -errno;
}
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
+
/*
* Instead of writing zeroes here, we could trust the hardware
* to always provide zeroes when muted.
@@ -3132,6 +3181,10 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
out->config = pcm_config_afe_proxy_playback;
adev->voice_tx_output = out;
+ } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
+ out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
+ out->config = pcm_config_low_latency;
+ out->sample_rate = out->config.rate;
} else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
format = AUDIO_FORMAT_PCM_16_BIT;
out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
@@ -3548,7 +3601,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
- audio_input_flags_t flags __unused,
+ audio_input_flags_t flags,
const char *address __unused,
audio_source_t source)
{
@@ -3598,6 +3651,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
in->standby = 1;
in->channel_mask = config->channel_mask;
in->capture_handle = handle;
+ in->flags = flags;
/* Update config params with the requested sample rate and channels */
in->usecase = USECASE_AUDIO_RECORD;
@@ -3753,10 +3807,13 @@ static int adev_close(hw_device_t *device)
audio_route_free(adev->audio_route);
free(adev->snd_dev_ref_cnt);
platform_deinit(adev->platform);
+ if (adev->adm_deinit)
+ adev->adm_deinit(adev->adm_data);
free(device);
adev = NULL;
}
pthread_mutex_unlock(&adev_init_lock);
+
return 0;
}
@@ -3768,6 +3825,7 @@ static int period_size_is_plausible_for_low_latency(int period_size)
{
switch (period_size) {
case 160:
+ case 192:
case 240:
case 320:
case 480:
@@ -3895,6 +3953,29 @@ static int adev_open(const hw_module_t *module, const char *name,
}
}
+ if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
+ adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
+ if (adev->adm_lib == NULL) {
+ ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
+ } else {
+ ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
+ adev->adm_init = (adm_init_t)
+ dlsym(adev->adm_lib, "adm_init");
+ adev->adm_deinit = (adm_deinit_t)
+ dlsym(adev->adm_lib, "adm_deinit");
+ adev->adm_register_input_stream = (adm_register_input_stream_t)
+ dlsym(adev->adm_lib, "adm_register_input_stream");
+ adev->adm_register_output_stream = (adm_register_output_stream_t)
+ dlsym(adev->adm_lib, "adm_register_output_stream");
+ adev->adm_deregister_stream = (adm_deregister_stream_t)
+ dlsym(adev->adm_lib, "adm_deregister_stream");
+ adev->adm_request_focus = (adm_request_focus_t)
+ dlsym(adev->adm_lib, "adm_request_focus");
+ adev->adm_abandon_focus = (adm_abandon_focus_t)
+ dlsym(adev->adm_lib, "adm_abandon_focus");
+ }
+ }
+
adev->bt_wb_speech_enabled = false;
audio_extn_ds2_enable(adev);
@@ -3929,6 +4010,9 @@ static int adev_open(const hw_module_t *module, const char *name,
pthread_mutex_unlock(&adev_init_lock);
+ if (adev->adm_init)
+ adev->adm_data = adev->adm_init();
+
ALOGV("%s: exit", __func__);
return 0;
}
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 652f28b5..26445931 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -51,6 +51,7 @@
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
+#define ADM_LIBRARY_PATH "/system/vendor/lib/libadm.so"
/* Flags used to initialize acdb_settings variable that goes to ACDB library */
#define NONE_FLAG 0x00000000
@@ -95,6 +96,7 @@ enum {
USECASE_AUDIO_PLAYBACK_OFFLOAD8,
USECASE_AUDIO_PLAYBACK_OFFLOAD9,
#endif
+ USECASE_AUDIO_PLAYBACK_ULL,
USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
@@ -240,6 +242,7 @@ struct stream_in {
bool enable_ns;
audio_format_t format;
audio_io_handle_t capture_handle;
+ audio_input_flags_t flags;
bool is_st_session;
bool is_st_session_active;
@@ -292,6 +295,14 @@ struct streams_output_cfg {
struct stream_app_type_cfg app_type_cfg;
};
+typedef void* (*adm_init_t)();
+typedef void (*adm_deinit_t)(void *);
+typedef void (*adm_register_output_stream_t)(void *, audio_io_handle_t, audio_output_flags_t);
+typedef void (*adm_register_input_stream_t)(void *, audio_io_handle_t, audio_input_flags_t);
+typedef void (*adm_deregister_stream_t)(void *, audio_io_handle_t);
+typedef void (*adm_request_focus_t)(void *, audio_io_handle_t);
+typedef void (*adm_abandon_focus_t)(void *, audio_io_handle_t);
+
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -329,7 +340,18 @@ struct audio_device {
struct sound_card_status snd_card_status;
int (*offload_effects_set_hpx_state)(bool);
+
amplifier_device_t *amp;
+
+ void *adm_data;
+ void *adm_lib;
+ adm_init_t adm_init;
+ adm_deinit_t adm_deinit;
+ adm_register_input_stream_t adm_register_input_stream;
+ adm_register_output_stream_t adm_register_output_stream;
+ adm_deregister_stream_t adm_deregister_stream;
+ adm_request_focus_t adm_request_focus;
+ adm_abandon_focus_t adm_abandon_focus;
};
int select_devices(struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8e3ac78e..064431ce 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.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.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -56,15 +56,14 @@
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
/* Used in calculating fragment size for pcm offload */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 2000 /* 2 secs */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 100 /* 100 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION 40 /* 40 millisecs */
/* MAX PCM fragment size cannot be increased further due
* to flinger's cblk size of 1mb,and it has to be a multiple of
* 24 - lcm of channels supported by DSP
*/
#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
-#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (4 * 1024)
#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
/*
@@ -2575,27 +2574,19 @@ uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
{
uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
uint32_t bits_per_sample = 16;
+ uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
bits_per_sample = 32;
}
- if (!info->has_video) {
- fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
-
- } else if (info->has_video && info->is_streaming) {
- fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING
- * info->sample_rate
- * bits_per_sample
- * popcount(info->channel_mask))/1000;
-
- } else if (info->has_video) {
- fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV
- * info->sample_rate
- * bits_per_sample
- * popcount(info->channel_mask))/1000;
- }
-
+ //duration is set to 40 ms worth of stereo data at 48Khz
+ //with 16 bit per sample, modify this when the channel
+ //configuration is different
+ fragment_size = (pcm_offload_time
+ * info->sample_rate
+ * (bits_per_sample >> 3)
+ * popcount(info->channel_mask))/1000;
fragment_size = ALIGN( fragment_size, 1024);
if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index f0e0e03c..aa023474 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -61,10 +61,7 @@
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
/* Used in calculating fragment size for pcm offload */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 1000 /* 1 sec */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 80 /* 80 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS 20 /* 20 millisecs */
-#define PCM_OFFLOAD_BUFFER_DURATION_MAX 1200 /* 1200 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION 40 /* 40 millisecs */
/* MAX PCM fragment size cannot be increased further due
* to flinger's cblk size of 1mb,and it has to be a multiple of
@@ -207,8 +204,10 @@ static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
DEEP_BUFFER_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
+ MULTIMEDIA3_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
- MULTIMEDIA2_PCM_DEVICE},
+ MULTIMEDIA2_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_OFFLOAD] =
{PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
#ifdef MULTIPLE_OFFLOAD_ENABLED
@@ -572,6 +571,7 @@ static char * backend_table[SND_DEVICE_MAX] = {0};
static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
#ifdef MULTIPLE_OFFLOAD_ENABLED
@@ -2962,25 +2962,13 @@ uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
{
uint32_t fragment_size = 0;
uint32_t bits_per_sample = 16;
- uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
+ uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
bits_per_sample = 32;
}
- if (platform_use_small_buffer(info)) {
- pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
- } else {
- if (!info->has_video) {
- pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_MAX;
- } else if (info->has_video && info->is_streaming) {
- pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING;
- } else if (info->has_video) {
- pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV;
- }
- }
-
- //duration is set to 20 ms worth of stereo data at 48Khz
+ //duration is set to 40 ms worth of stereo data at 48Khz
//with 16 bit per sample, modify this when the channel
//configuration is different
fragment_size = (pcm_offload_time
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 31d422e3..a9ff9497 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -206,6 +206,7 @@ enum {
#define AUDIO_RECORD_PCM_DEVICE 0
#define AUDIO_RECORD_3MIC_PCM_DEVICE 44
#define MULTIMEDIA2_PCM_DEVICE 1
+#define MULTIMEDIA3_PCM_DEVICE 4
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 2ef080b8..9f778cad 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -47,6 +47,14 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FORMATS)),true)
LOCAL_CFLAGS += -DAUDIO_EXTN_FORMATS_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_SPK)),true)
+LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
+LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
+endif
+
LOCAL_MODULE := libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index cbea368a..b9d75054 100755..100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -122,6 +122,15 @@ status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t d
// handle output device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
}
@@ -129,6 +138,20 @@ status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t d
// register new device as available
index = mAvailableOutputDevices.add(devDesc);
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ if (mHdmiAudioDisabled || !mHdmiAudioEvent) {
+ mAvailableOutputDevices.remove(devDesc);
+ ALOGW("HDMI sink not connected, do not route audio to HDMI out");
+ return INVALID_OPERATION;
+ }
+ }
+#endif
if (index >= 0) {
sp<HwModule> module = mHwModules.getModuleForDevice(device);
if (module == 0) {
@@ -164,6 +187,15 @@ status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t d
// handle output device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
if (index < 0) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device not connected: %x", device);
return INVALID_OPERATION;
}
@@ -177,7 +209,15 @@ status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t d
// remove device from available output devices
mAvailableOutputDevices.remove(devDesc);
-
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
// Propagate device availability to Engine
@@ -522,9 +562,8 @@ audio_devices_t AudioPolicyManagerCustom::getNewOutputDevice(const sp<AudioOutpu
(isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION)
&& (!isStrategyActive(mPrimaryOutput,STRATEGY_MEDIA)))) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
- } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)||
- (isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION_RESPECTFUL)
- && (!isStrategyActive(mPrimaryOutput, STRATEGY_MEDIA)))) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL) ||
+ isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
@@ -545,6 +584,7 @@ void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
{
ALOGV("setPhoneState() state %d", state);
// store previous phone state for management of sonification strategy below
+ audio_devices_t newDevice = AUDIO_DEVICE_NONE;
int oldState = mEngine->getPhoneState();
if (mEngine->setPhoneState(state) != NO_ERROR) {
@@ -562,8 +602,7 @@ void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
if (stream == AUDIO_STREAM_PATCH) {
continue;
}
-
- handleIncallSonification((audio_stream_type_t)stream, false, true, curOutput);
+ handleIncallSonification((audio_stream_type_t)stream, false, true, curOutput);
}
}
@@ -835,7 +874,14 @@ void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
}
}
-
+ //update device for all non-primary outputs
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ audio_io_handle_t output = mOutputs.keyAt(i);
+ if (output != mPrimaryOutput->mIoHandle) {
+ newDevice = getNewOutputDevice(mOutputs.valueFor(output), false /*fromCache*/);
+ setOutputDevice(mOutputs.valueFor(output), newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ }
+ }
// if entering in call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
if (isStateInCall(state)) {
@@ -846,7 +892,7 @@ void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
if (stream == AUDIO_STREAM_PATCH) {
continue;
}
- handleIncallSonification((audio_stream_type_t)stream, true, true, curOutput);
+ handleIncallSonification((audio_stream_type_t)stream, true, true, curOutput);
}
}
}
@@ -859,18 +905,23 @@ void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
mLimitRingtoneVolume = false;
}
}
-status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> outputDesc,
+
+status_t AudioPolicyManagerCustom::stopSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate)
{
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+ ALOGW("stopSource() invalid stream %d", stream);
+ return INVALID_OPERATION;
+ }
// always handle stream stop, check which stream type is stopping
handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
// handle special case for sonification while in call
- if (isInCall()) {
+ if (isInCall() && (outputDesc->mRefCount[stream] == 1)) {
if (outputDesc->isDuplicated()) {
- handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
- handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
+ handleIncallSonification(stream, false, false, outputDesc->subOutput1()->mIoHandle);
+ handleIncallSonification(stream, false, false, outputDesc->subOutput2()->mIoHandle);
}
handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
}
@@ -882,6 +933,7 @@ status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> output
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->mRefCount[stream] == 0 || forceDeviceUpdate) {
outputDesc->mStopTime[stream] = systemTime();
+ audio_devices_t prevDevice = outputDesc->device();
audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
// the track stop() command is received and at that time the audio track buffer can
@@ -899,10 +951,17 @@ status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> output
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
(newDevice != desc->device())) {
- setOutputDevice(desc,
- getNewOutputDevice(desc, false /*fromCache*/),
+ audio_devices_t dev = getNewOutputDevice(mOutputs.valueFor(curOutput), false /*fromCache*/);
+ uint32_t delayMs;
+ if (dev == prevDevice) {
+ delayMs = 0;
+ } else {
+ delayMs = outputDesc->latency()*2;
+ }
+ setOutputDevice(desc,
+ dev,
true,
- outputDesc->latency()*2);
+ delayMs);
}
}
// update the outputs if stopping one with a stream that can affect notification routing
@@ -914,7 +973,7 @@ status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> output
return INVALID_OPERATION;
}
}
-status_t AudioPolicyManagerCustom::startSource(sp<SwAudioOutputDescriptor> outputDesc,
+status_t AudioPolicyManagerCustom::startSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t *delayMs)
@@ -922,6 +981,11 @@ status_t AudioPolicyManagerCustom::startSource(sp<SwAudioOutputDescriptor> outpu
// cannot start playback of STREAM_TTS if any other output is being used
uint32_t beaconMuteLatency = 0;
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+ ALOGW("startSource() invalid stream %d", stream);
+ return INVALID_OPERATION;
+ }
+
*delayMs = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
@@ -1065,10 +1129,14 @@ void AudioPolicyManagerCustom::handleNotificationRoutingForStream(audio_stream_t
}
status_t AudioPolicyManagerCustom::checkAndSetVolume(audio_stream_type_t stream,
int index,
- const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs, bool force)
{
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
+ ALOGW("checkAndSetVolume() invalid stream %d", stream);
+ return INVALID_OPERATION;
+ }
// do not change actual stream volume if the stream is muted
if (outputDesc->mMuteCount[stream] != 0) {
ALOGVV("checkAndSetVolume() stream %d muted count %d",
@@ -1359,6 +1427,7 @@ audio_io_handle_t AudioPolicyManagerCustom::getOutputForDevice(
}
#endif
+#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
/*
* WFD audio routes back to target speaker when starting a ringtone playback.
* This is because primary output is reused for ringtone, so output device is
@@ -1378,6 +1447,8 @@ audio_io_handle_t AudioPolicyManagerCustom::getOutputForDevice(
else //route every thing else to ULL path
flags = AUDIO_OUTPUT_FLAG_FAST;
}
+#endif
+
// open a direct output if required by specified parameters
// force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
@@ -1718,7 +1789,7 @@ status_t AudioPolicyManagerCustom::startInput(audio_io_handle_t input,
// Move tracks associated to this strategy from previous output to new output
for (int i = AUDIO_STREAM_SYSTEM; i < (int)AUDIO_STREAM_CNT; i++) {
// Do not call invalidate for ENFORCED_AUDIBLE (otherwise pops are seen for camcorder)
- if ((i != AUDIO_STREAM_ENFORCED_AUDIBLE && (i != AUDIO_STREAM_PATCH)) {
+ if ((i != AUDIO_STREAM_ENFORCED_AUDIBLE && (i != AUDIO_STREAM_PATCH))) {
ALOGD("Invalidate on releaseInput for stream :: %d ", i);
//FIXME see fixme on name change
mpClientInterface->invalidateStream((audio_stream_type_t)i);
@@ -1816,8 +1887,42 @@ status_t AudioPolicyManagerCustom::stopInput(audio_io_handle_t input,
}
AudioPolicyManagerCustom::AudioPolicyManagerCustom(AudioPolicyClientInterface *clientInterface)
- : AudioPolicyManager(clientInterface)
+ : AudioPolicyManager(clientInterface),
+ mHdmiAudioDisabled(false),
+ mHdmiAudioEvent(false),
+ mPrevPhoneState(0)
{
+ char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
+ bool prop_ssr_enabled = false;
+
+ if (property_get("ro.qc.sdk.audio.ssr", ssr_enabled, NULL)) {
+ prop_ssr_enabled = atoi(ssr_enabled) || !strncmp("true", ssr_enabled, 4);
+ }
+
+ for (size_t i = 0; i < mHwModules.size(); i++) {
+ ALOGV("Hw module %d", i);
+ for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
+ const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
+ ALOGV("Input profile ", j);
+ for (size_t k = 0; k < inProfile->mChannelMasks.size(); k++) {
+ audio_channel_mask_t channelMask =
+ inProfile->mChannelMasks.itemAt(k);
+ ALOGV("Channel Mask %x size %d", channelMask,
+ inProfile->mChannelMasks.size());
+ if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
+ if (!prop_ssr_enabled) {
+ ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
+ " input profile as SSR(surround sound record)"
+ " is not supported on this chipset variant");
+ inProfile->mChannelMasks.removeItemsAt(k, 1);
+ ALOGV("Channel Mask size now %d",
+ inProfile->mChannelMasks.size());
+ }
+ }
+ }
+ }
+ }
+
#ifdef RECORD_PLAY_CONCURRENCY
mIsInputRequestOnProgress = false;
#endif
@@ -1827,31 +1932,4 @@ AudioPolicyManagerCustom::AudioPolicyManagerCustom(AudioPolicyClientInterface *c
mFallBackflag = getFallBackPath();
#endif
}
-
-audio_devices_t AudioPolicyManagerCustom::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
-{
- audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
- audio_devices_t device = AUDIO_DEVICE_NONE;
- switch (strategy) {
- case STRATEGY_SONIFICATION:
- case STRATEGY_ENFORCED_AUDIBLE:
- case STRATEGY_ACCESSIBILITY:
- case STRATEGY_REROUTING:
- case STRATEGY_MEDIA:
- if (strategy != STRATEGY_SONIFICATION){
- // no sonification on WFD sink
- device |= availableOutputDeviceTypes & AUDIO_DEVICE_OUT_PROXY;
- if (device != AUDIO_DEVICE_NONE) {
- ALOGV("Found proxy for strategy %d", strategy);
- return device;
- }
- }
- break;
- default:
- ALOGV("getDeviceForStrategy() unknown strategy: %d", strategy);
- break;
- }
- device = AudioPolicyManager::getDeviceForStrategy(strategy, fromCache);
- return device;
-}
}
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 2f29c37c..f70cfb00 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -32,7 +32,7 @@ namespace android {
#define AUDIO_FORMAT_APE 0x1D000000UL
#endif
-#ifndef AFE_PROXY_ENABLED
+#ifndef AUDIO_EXTN_AFE_PROXY_ENABLED
#define AUDIO_DEVICE_OUT_PROXY 0x1000000
#endif
// ----------------------------------------------------------------------------
@@ -51,7 +51,6 @@ public:
const char *device_name);
virtual void setPhoneState(audio_mode_t state);
-
virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
virtual status_t getInputForAttr(const audio_attributes_t *attr,
@@ -70,12 +69,11 @@ public:
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session);
- virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache);
protected:
status_t checkAndSetVolume(audio_stream_type_t stream,
int index,
- const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs = 0, bool force = false);
@@ -90,16 +88,16 @@ protected:
// if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force
// the re-evaluation of the output device.
- status_t startSource(sp<SwAudioOutputDescriptor> outputDesc,
+ status_t startSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t *delayMs);
- status_t stopSource(sp<SwAudioOutputDescriptor> outputDesc,
+ status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate);
- // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON 313
- // returns 0 if no mute/unmute event happened, the largest latency of the device where 314
- // the mute/unmute happened 315
+ // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
+ // returns 0 if no mute/unmute event happened, the largest latency of the device where
+ // the mute/unmute happened
uint32_t handleEventForBeacon(int){return 0;}
uint32_t setBeaconMute(bool){return 0;}
#ifdef VOICE_CONCURRENCY
@@ -115,14 +113,9 @@ protected:
//parameter indicates if HDMI plug in/out detected
bool mHdmiAudioEvent;
private:
- static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
- int indexInUi);
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
- static bool isVirtualInputDevice(audio_devices_t device);
- static bool deviceDistinguishesOnAddress(audio_devices_t device);
- uint32_t nextUniqueId();
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevice(
audio_devices_t device,
@@ -152,8 +145,6 @@ private:
// Used for record + playback concurrency
bool mIsInputRequestOnProgress;
#endif
-
-
};
};
diff --git a/visualizer/offload_visualizer.c b/visualizer/offload_visualizer.c
index dfa4a2dc..5148f4ac 100644
--- a/visualizer/offload_visualizer.c
+++ b/visualizer/offload_visualizer.c
@@ -300,20 +300,40 @@ bool effects_enabled() {
return false;
}
-int configure_proxy_capture(struct mixer *mixer, int value) {
- const char *proxy_ctl_name = "AFE_PCM_RX Audio Mixer MultiMedia4";
+int set_control(const char* name, struct mixer *mixer, int value) {
struct mixer_ctl *ctl;
- if (value && acdb_send_audio_cal)
- acdb_send_audio_cal(AFE_PROXY_ACDB_ID, ACDB_DEV_TYPE_OUT);
-
- ctl = mixer_get_ctl_by_name(mixer, proxy_ctl_name);
+ ctl = mixer_get_ctl_by_name(mixer, name);
if (ctl == NULL) {
- ALOGW("%s: could not get %s ctl", __func__, proxy_ctl_name);
+ ALOGW("%s: could not get %s ctl", __func__, name);
return -EINVAL;
}
- if (mixer_ctl_set_value(ctl, 0, value) != 0)
- ALOGW("%s: error setting value %d on %s ", __func__, value, proxy_ctl_name);
+ if (mixer_ctl_set_value(ctl, 0, value) != 0) {
+ ALOGW("%s: error setting value %d on %s ", __func__, value, name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int configure_proxy_capture(struct mixer *mixer, int value) {
+ int retval = 0;
+
+ if (value && acdb_send_audio_cal)
+ acdb_send_audio_cal(AFE_PROXY_ACDB_ID, ACDB_DEV_TYPE_OUT);
+
+ retval = set_control("AFE_PCM_RX Audio Mixer MultiMedia4", mixer, value);
+
+ if (retval != 0)
+ return retval;
+
+ // Extending visualizer to capture for compress2 path as well.
+ // for extending it to multiple offload either this needs to be extended
+ // or need to find better solution to enable only active offload sessions
+
+ retval = set_control("AFE_PCM_RX Audio Mixer MultiMedia7", mixer, value);
+ if (retval != 0)
+ return retval;
return 0;
}