Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4aa3448 authored by Steve Kondik's avatar Steve Kondik Committed by Rashed Abdel-Tawab
Browse files

hal: Squashed collection of fixes



 * Remove unnecessary ifdefs for PCM offload
 * Remove unnecessary property for 24-bit support (use audio policy)
 * Clean up warnings

 * Also includes these patches from Google:

audio: fix set_parameters return value.

xxx_set_parameters functions were returning the status
returned by str_parms_create_str() which is incorrect.
These functions should return 0 when no error occurs.

Change-Id: Ib4a7ac427e49f5500c99902f86d2d69d5843eda0

Scan and verify audio device parameters on open

Scanning is default disabled at this time.
Verbose logs will display device params found.

Change-Id: Id188d096ec68d2058c66ae3a51fe57d9645d03ef
Signed-off-by: default avatarAndy Hung <hunga@google.com>

audio: deprecate audio_stream_frame_size()

Bug: 15000850.
Change-Id: I1bbe614c241befa24513a2b583594680e32fd954
parent cd213abc
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -46,10 +46,6 @@ LOCAL_SRC_FILES += audio_extn/audio_extn.c \
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD)),true)
    LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
endif

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_ANC_HEADSET)),true)
    LOCAL_CFLAGS += -DANC_HEADSET_ENABLED
endif
+2 −2
Original line number Diff line number Diff line
@@ -451,8 +451,8 @@ static int get_active_offload_usecases(const struct audio_device *adev,
    return ret;
}

void audio_extn_set_parameters(struct audio_device *adev,
                               struct str_parms *parms)
void audio_extn_set_parameters(struct audio_device *adev __unused,
                               struct str_parms *parms __unused)
{
   audio_extn_set_anc_parameters(adev, parms);
   audio_extn_set_fluence_parameters(adev, parms);
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@

#include <cutils/str_parms.h>

#ifndef PCM_OFFLOAD_ENABLED
#if 0
#define AUDIO_FORMAT_PCM_OFFLOAD 0x17000000UL
#define AUDIO_FORMAT_PCM_16_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_16_BIT)
#define AUDIO_FORMAT_PCM_24_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_8_24_BIT)
+186 −22
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <cutils/sched_policy.h>

#include <hardware/audio_effect.h>
#include <hardware/audio_alsaops.h>
#include <system/thread_defs.h>
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_ns.h>
@@ -68,6 +69,11 @@
static unsigned int configured_low_latency_capture_period_size =
        LOW_LATENCY_CAPTURE_PERIOD_SIZE;

/* This constant enables extended precision handling.
 * TODO The flag is off until more testing is done.
 */
static const bool k_enable_extended_precision = true;

struct pcm_config pcm_config_deep_buffer = {
    .channels = 2,
    .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
@@ -1445,6 +1451,7 @@ int start_output_stream(struct stream_out *out)

    ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
          __func__, adev->snd_card, out->pcm_device_id, out->config.format);

    if (!is_offload_usecase(out->usecase)) {
        unsigned int flags = PCM_OUT;
        unsigned int pcm_open_retry_count = 0;
@@ -1757,6 +1764,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
    char value[32];
    int ret = 0, val = 0, err;
    bool select_new_device = false;
    int status = 0;

    ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
          __func__, out->usecase, use_case_table[out->usecase], kvpairs);
@@ -1833,8 +1841,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)

    str_parms_destroy(parms);
error:
    ALOGV("%s: exit: code(%d)", __func__, ret);
    return ret;
    ALOGV("%s: exit: code(%d)", __func__, status);
    return status;
}

static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
@@ -2031,7 +2039,7 @@ exit:

    if (ret != 0) {
        if (out->pcm)
            ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
            ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
        if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
            pthread_mutex_lock(&adev->lock);
            voice_extn_compress_voip_close_output_stream(&out->stream.common);
@@ -2041,7 +2049,6 @@ exit:
        out_standby(&out->stream.common);
        usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
                        out_get_sample_rate(&out->stream.common));

    }
    return bytes;
}
@@ -2351,6 +2358,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
    char *str;
    char value[32];
    int ret = 0, val = 0, err;
    int status = 0;

    ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
    parms = str_parms_create_str(kvpairs);
@@ -2380,14 +2388,15 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
        }
    }

    err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
    if (err >= 0) {
    ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));

    if (ret >= 0) {
        val = atoi(value);
        if (((int)in->device != val) && (val != 0)) {
            in->device = val;
            /* If recording is in progress, change the tx device to new device */
            if (!in->standby && !in->is_st_session)
                ret = select_devices(adev, in->usecase);
                status = select_devices(adev, in->usecase);
        }
    }

@@ -2397,8 +2406,8 @@ done:

    str_parms_destroy(parms);
error:
    ALOGV("%s: exit: status(%d)", __func__, ret);
    return ret;
    ALOGV("%s: exit: status(%d)", __func__, status);
    return status;
}

static char* in_get_parameters(const struct audio_stream *stream,
@@ -2690,6 +2699,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
        else
            out->compr_config.codec->id =
                get_snd_codec_id(config->offload_info.format);

        if (audio_is_offload_pcm(config->offload_info.format)) {
            out->compr_config.fragment_size =
                       platform_get_pcm_offload_buffer_size(&config->offload_info);
@@ -2714,9 +2724,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
        if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
            out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;

        if (out->bit_width == 24) {
        if (out->bit_width == 24)
            out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
        }

        if (config->offload_info.format == AUDIO_FORMAT_FLAC)
            out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
@@ -2764,16 +2773,31 @@ 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_FAST) {
        format = AUDIO_FORMAT_PCM_16_BIT;
    } else {
        if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
            out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
            out->config = pcm_config_low_latency;
        out->sample_rate = out->config.rate;
        } else {
            /* primary path is the default path selected if no other outputs are available/suitable */
        format = AUDIO_FORMAT_PCM_16_BIT;
            out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
            out->config = pcm_config_deep_buffer;
        }
        if (config->format != audio_format_from_pcm_format(out->config.format)) {
            if (k_enable_extended_precision
                    && pcm_params_format_test(adev->use_case_table[out->usecase],
                            pcm_format_from_audio_format(config->format))) {
                out->config.format = pcm_format_from_audio_format(config->format);
                /* out->format already set to config->format */
            } else {
                /* deny the externally proposed config format
                 * and use the one specified in audio_hw layer configuration.
                 * Note: out->format is returned by out->stream.common.get_format()
                 * and is used to set config->format in the code several lines below.
                 */
                out->format = audio_format_from_pcm_format(out->config.format);
            }
        }

        out->sample_rate = out->config.rate;
    }

@@ -2784,7 +2808,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
                                                devices, flags, format, out->sample_rate,
                                                out->bit_width, &out->app_type_cfg);
    if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
        (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
            flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
        /* Ensure the default output is not selected twice */
        if(adev->primary_output == NULL)
            adev->primary_output = out;
@@ -2986,7 +3010,7 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
                list_for_each(node, &adev->usecase_list) {
                    usecase = node_to_item(node, struct audio_usecase, list);
                    if (usecase->type == PCM_PLAYBACK) {
                        select_devices(adev, usecase->id);
                        status = select_devices(adev, usecase->id);
                        break;
                    }
                }
@@ -3308,8 +3332,143 @@ static int adev_dump(const audio_hw_device_t *device __unused,
    return 0;
}

/* verifies input and output devices and their capabilities.
 *
 * This verification is required when enabling extended bit-depth or
 * sampling rates, as not all qcom products support it.
 *
 * Suitable for calling only on initialization such as adev_open().
 * It fills the audio_device use_case_table[] array.
 *
 * Has a side-effect that it needs to configure audio routing / devices
 * in order to power up the devices and read the device parameters.
 * It does not acquire any hw device lock. Should restore the devices
 * back to "normal state" upon completion.
 */
static int adev_verify_devices(struct audio_device *adev)
{
    /* enumeration is a bit difficult because one really wants to pull
     * the use_case, device id, etc from the hidden pcm_device_table[].
     * In this case there are the following use cases and device ids.
     *
     * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
     * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
     * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
     * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
     * [USECASE_AUDIO_RECORD] = {0, 0},
     * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
     * [USECASE_VOICE_CALL] = {2, 2},
     *
     * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
     * USECASE_VOICE_CALL omitted, but possible for either input or output.
     */

    /* should be the usecases enabled in adev_open_input_stream() */
    static const int test_in_usecases[] = {
             USECASE_AUDIO_RECORD,
             USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
    };
    /* should be the usecases enabled in adev_open_output_stream()*/
    static const int test_out_usecases[] = {
            USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
            USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
    };
    static const usecase_type_t usecase_type_by_dir[] = {
            PCM_PLAYBACK,
            PCM_CAPTURE,
    };
    static const unsigned flags_by_dir[] = {
            PCM_OUT,
            PCM_IN,
    };

    size_t i;
    unsigned dir;
    const unsigned card_id = adev->snd_card;
    char info[512]; /* for possible debug info */

    for (dir = 0; dir < 2; ++dir) {
        const usecase_type_t usecase_type = usecase_type_by_dir[dir];
        const unsigned flags_dir = flags_by_dir[dir];
        const size_t testsize =
                dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
        const int *testcases =
                dir ? test_in_usecases : test_out_usecases;
        const audio_devices_t audio_device =
                dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;

        for (i = 0; i < testsize; ++i) {
            const audio_usecase_t audio_usecase = testcases[i];
            int device_id;
            snd_device_t snd_device;
            struct pcm_params **pparams;
            struct stream_out out;
            struct stream_in in;
            struct audio_usecase uc_info;
            int retval;

            pparams = &adev->use_case_table[audio_usecase];
            pcm_params_free(*pparams); /* can accept null input */
            *pparams = NULL;

            /* find the device ID for the use case (signed, for error) */
            device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
            if (device_id < 0)
                continue;

            /* prepare structures for device probing */
            memset(&uc_info, 0, sizeof(uc_info));
            uc_info.id = audio_usecase;
            uc_info.type = usecase_type;
            if (dir) {
                adev->active_input = &in;
                memset(&in, 0, sizeof(in));
                in.device = audio_device;
                in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                uc_info.stream.in = &in;
            }  else {
                adev->active_input = NULL;
            }
            memset(&out, 0, sizeof(out));
            out.devices = audio_device; /* only field needed in select_devices */
            uc_info.stream.out = &out;
            uc_info.devices = audio_device;
            uc_info.in_snd_device = SND_DEVICE_NONE;
            uc_info.out_snd_device = SND_DEVICE_NONE;
            list_add_tail(&adev->usecase_list, &uc_info.list);

            /* select device - similar to start_(in/out)put_stream() */
            retval = select_devices(adev, audio_usecase);
            if (retval >= 0) {
                *pparams = pcm_params_get(card_id, device_id, flags_dir);
#if LOG_NDEBUG == 0
                if (*pparams) {
                    ALOGV("%s: (%s) card %d  device %d", __func__,
                            dir ? "input" : "output", card_id, device_id);
                    pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
                    ALOGV(info); /* print parameters */
                } else {
                    ALOGV("%s: cannot locate card %d  device %d", __func__, card_id, device_id);
                }
#endif
            }

            /* deselect device - similar to stop_(in/out)put_stream() */
            /* 1. Get and set stream specific mixer controls */
            retval = disable_audio_route(adev, &uc_info);
            /* 2. Disable the rx device */
            retval = disable_snd_device(adev,
                    dir ? uc_info.in_snd_device : uc_info.out_snd_device);
            list_remove(&uc_info.list);
        }
    }
    adev->active_input = NULL; /* restore adev state */
    return 0;
}

static int adev_close(hw_device_t *device)
{
    size_t i;
    struct audio_device *adev = (struct audio_device *)device;

    if (!adev)
@@ -3324,6 +3483,9 @@ static int adev_close(hw_device_t *device)
        audio_route_free(adev->audio_route);
        free(adev->snd_dev_ref_cnt);
        platform_deinit(adev->platform);
        for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
            pcm_params_free(adev->use_case_table[i]);
        }
        free(device);
        adev = NULL;
    }
@@ -3467,6 +3629,8 @@ static int adev_open(const hw_module_t *module, const char *name,

    audio_extn_ds2_enable(adev);
    *device = &adev->device.common;
    if (k_enable_extended_precision)
        adev_verify_devices(adev);

    audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
                                                    &adev->streams_output_cfg_list);
+8 −0
Original line number Diff line number Diff line
@@ -298,6 +298,14 @@ struct audio_device {
    int (*offload_effects_stop_output)(audio_io_handle_t, int);

    struct sound_card_status snd_card_status;

    /* The pcm_params use_case_table is loaded by adev_verify_devices() upon
     * calling adev_open().
     *
     * If an entry is not NULL, it can be used to determine if extended precision
     * or other capabilities are present for the device corresponding to that usecase.
     */
    struct pcm_params *use_case_table[AUDIO_USECASE_MAX];
};

int select_devices(struct audio_device *adev,
Loading