diff options
author | Steve Kondik <steve@cyngn.com> | 2015-11-04 13:59:25 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-11-04 13:59:25 -0800 |
commit | e995fd7d13ae3945ba1aaf8545d2b4c161b7ffc2 (patch) | |
tree | d6482860c733321f8eb0d5f694c172a5892a16a9 | |
parent | 789da11e6c3c65b8e9c5265e8a43263606364f48 (diff) | |
parent | e4881591c9272456a9f1869a24669c192e4c4980 (diff) | |
download | android_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.h | 2 | ||||
-rw-r--r-- | hal/audio_hw.c | 108 | ||||
-rw-r--r-- | hal/audio_hw.h | 22 | ||||
-rw-r--r-- | hal/msm8916/platform.c | 31 | ||||
-rw-r--r-- | hal/msm8974/platform.c | 26 | ||||
-rw-r--r-- | hal/msm8974/platform.h | 1 | ||||
-rw-r--r-- | policy_hal/Android.mk | 8 | ||||
-rw-r--r--[-rwxr-xr-x] | policy_hal/AudioPolicyManager.cpp | 170 | ||||
-rw-r--r-- | policy_hal/AudioPolicyManager.h | 23 | ||||
-rw-r--r-- | visualizer/offload_visualizer.c | 38 |
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; } |