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

Commit db1b4f9c authored by Md Mansoor Ahmed's avatar Md Mansoor Ahmed Committed by Gerrit - the friendly Code Review server
Browse files

hal: Update keep_alive to support silence playback on non-hdmi devices



Keep_alive can now handle silence playback on multiple concurrent
devices such as primary output devices as well as HDMI

Change-Id: I08cbec51394d23255e1a61928e0b2cad552b2ac0
Signed-off-by: default avatarMd Mansoor Ahmed <mansoor@codeaurora.org>
parent cc8d7f65
Loading
Loading
Loading
Loading

hal/audio_extn/audio_defs.h

100644 → 100755
+8 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015, 2017-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
@@ -190,6 +190,13 @@ struct audio_out_correct_drift {
    int64_t        adjust_time;
};

/* Device playback mode passed to keep_alive_start & keep_alive_stop*/
typedef enum {
    KEEP_ALIVE_OUT_NONE = 0,
    KEEP_ALIVE_OUT_PRIMARY,
    KEEP_ALIVE_OUT_HDMI,
} ka_mode_t;

/* type of asynchronous write callback events. Mutually exclusive
 * event enums append those defined for stream_callback_event_t in audio.h */
typedef enum {

hal/audio_extn/audio_extn.c

100644 → 100755
+2 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2013 The Android Open Source Project
@@ -833,6 +833,7 @@ void audio_extn_set_parameters(struct audio_device *adev,
   audio_extn_source_track_set_parameters(adev, parms);
   audio_extn_fbsp_set_parameters(parms);
   audio_extn_keep_alive_set_parameters(adev, parms);
   audio_extn_passthru_set_parameters(adev, parms);
   audio_extn_ext_disp_set_parameters(adev, parms);
   audio_extn_qaf_set_parameters(adev, parms);
   if (adev->offload_effects_set_parameters != NULL)

hal/audio_extn/audio_extn.h

100644 → 100755
+8 −6
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2013 The Android Open Source Project
@@ -769,15 +769,17 @@ int audio_extn_bt_hal_get_latency(void *handle);
#endif

#ifndef KEEP_ALIVE_ENABLED
#define audio_extn_keep_alive_init(a) do {} while(0)
#define audio_extn_keep_alive_start() do {} while(0)
#define audio_extn_keep_alive_stop() do {} while(0)
#define audio_extn_keep_alive_init(adev) do {} while(0)
#define audio_extn_keep_alive_deinit() do {} while(0)
#define audio_extn_keep_alive_start(ka_mode) do {} while(0)
#define audio_extn_keep_alive_stop(ka_mode) do {} while(0)
#define audio_extn_keep_alive_is_active() (false)
#define audio_extn_keep_alive_set_parameters(adev, parms) (0)
#else
void audio_extn_keep_alive_init(struct audio_device *adev);
void audio_extn_keep_alive_start();
void audio_extn_keep_alive_stop();
void audio_extn_keep_alive_deinit();
void audio_extn_keep_alive_start(ka_mode_t ka_mode);
void audio_extn_keep_alive_stop(ka_mode_t ka_mode);
bool audio_extn_keep_alive_is_active();
int audio_extn_keep_alive_set_parameters(struct audio_device *adev,
                                         struct str_parms *parms);

hal/audio_extn/keep_alive.c

100644 → 100755
+202 −217
Original line number Diff line number Diff line
/*
* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-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
@@ -55,6 +55,7 @@ typedef enum {

typedef enum {
    REQUEST_WRITE,
    REQUEST_QUIT,
} request_t;

typedef struct {
@@ -66,8 +67,11 @@ typedef struct {
    state_t state;
    struct listnode cmd_list;
    struct pcm *pcm;
    struct stream_out *out;
    ka_mode_t prev_mode;
    bool done;
    void * userdata;
    audio_devices_t active_devices;
} keep_alive_t;

struct keep_alive_cmd {
@@ -89,19 +93,40 @@ static struct pcm_config silence_config = {
};

static void * keep_alive_loop(void * context);
static int keep_alive_cleanup();
static int keep_alive_start_l();

static void send_cmd_l(request_t r)
{
    if (ka.state == STATE_DEINIT || ka.state == STATE_DISABLED)
        return;

    struct keep_alive_cmd *cmd =
        (struct keep_alive_cmd *)calloc(1, sizeof(struct keep_alive_cmd));

    if (cmd == NULL) {
        ALOGE("%s: cmd is NULL", __func__);
        return;
    }

    cmd->req = r;
    list_add_tail(&ka.cmd_list, &cmd->node);
    pthread_cond_signal(&ka.cond);
}

void audio_extn_keep_alive_init(struct audio_device *adev)
{
    ka.userdata = adev;
    ka.state = STATE_IDLE;
    ka.pcm = NULL;

    if (property_get_bool("audio.keep_alive.disabled", false)) {
        ALOGE("keep alive disabled");
        ka.state = STATE_DISABLED;
        return;
    }

    ka.done = false;
    ka.prev_mode = KEEP_ALIVE_OUT_NONE;
    ka.active_devices = AUDIO_DEVICE_NONE;
    pthread_mutex_init(&ka.lock, (const pthread_mutexattr_t *) NULL);
    pthread_cond_init(&ka.cond, (const pthread_condattr_t *) NULL);
    pthread_cond_init(&ka.wake_up_cond, (const pthread_condattr_t *) NULL);
@@ -112,298 +137,252 @@ void audio_extn_keep_alive_init(struct audio_device *adev)
        ALOGW("Failed to create keep_alive_thread");
        /* can continue without keep alive */
        ka.state = STATE_DEINIT;
        return;
    }
    ALOGV("%s init done", __func__);
}

static void send_cmd_l(request_t r)
void audio_extn_keep_alive_deinit()
{
    if (ka.state == STATE_DEINIT || ka.state == STATE_DISABLED)
        return;

    struct keep_alive_cmd *cmd =
        (struct keep_alive_cmd *)calloc(1, sizeof(struct keep_alive_cmd));

    if (cmd == NULL) {
        ALOGE("%s: cmd is NULL", __func__);
        return;
    }

    cmd->req = r;
    list_add_tail(&ka.cmd_list, &cmd->node);
    pthread_cond_signal(&ka.cond);
}

static int close_silence_stream()
{
    if (!ka.pcm)
        return -ENODEV;

    pcm_close(ka.pcm);
    ka.pcm = NULL;
    return 0;
    ka.userdata = NULL;
    ka.done = true;
    pthread_mutex_lock(&ka.lock);
    send_cmd_l(REQUEST_QUIT);
    pthread_mutex_unlock(&ka.lock);
    pthread_join(ka.thread, (void **) NULL);
    pthread_mutex_destroy(&ka.lock);
    pthread_cond_destroy(&ka.cond);
    pthread_cond_destroy(&ka.wake_up_cond);
    pthread_mutex_destroy(&ka.sleep_lock);
    ALOGV("%s deinit done", __func__);
}

static int open_silence_stream()
audio_devices_t get_device_id_from_mode(ka_mode_t ka_mode)
{
    unsigned int flags = PCM_OUT|PCM_MONOTONIC;

    if (ka.pcm)
        return -EEXIST;

    int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
                                                        PCM_PLAYBACK);

    ALOGD("opening silence device %d", silence_pcm_dev_id);
    struct audio_device * adev = (struct audio_device *)ka.userdata;
    ka.pcm = pcm_open(adev->snd_card, silence_pcm_dev_id,
                      flags, &silence_config);
    ALOGD("opened silence device %d", silence_pcm_dev_id);
    if (ka.pcm == NULL || !pcm_is_ready(ka.pcm)) {
        ALOGE("%s: %s", __func__, pcm_get_error(ka.pcm));
        if (ka.pcm != NULL) {
            pcm_close(ka.pcm);
            ka.pcm = NULL;
        }
        return -1;
    audio_devices_t out_device = AUDIO_DEVICE_NONE;
    switch (ka_mode)
    {
        case KEEP_ALIVE_OUT_PRIMARY:
            if (adev->primary_output) {
                if (adev->primary_output->devices & AUDIO_DEVICE_OUT_ALL)
                    out_device = adev->primary_output->devices & AUDIO_DEVICE_OUT_ALL;
                else
                    out_device = AUDIO_DEVICE_OUT_SPEAKER;
            }
    return 0;
            else {
                out_device = AUDIO_DEVICE_OUT_SPEAKER;
            }
            break;

        case KEEP_ALIVE_OUT_HDMI:
            out_device = AUDIO_DEVICE_OUT_AUX_DIGITAL;
            break;

static int set_mixer_control(struct mixer *mixer,
                             const char * mixer_ctl_name,
                             const char *mixer_val)
{
    struct mixer_ctl *ctl;
    if ((mixer == NULL) || (mixer_ctl_name == NULL) || (mixer_val == NULL)) {
       ALOGE("%s: Invalid input", __func__);
       return -EINVAL;
    }
    ALOGD("setting mixer ctl %s with value %s", mixer_ctl_name, mixer_val);
    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return -EINVAL;
        default:
            out_device = AUDIO_DEVICE_NONE;
    }

    return mixer_ctl_set_enum_by_string(ctl, mixer_val);
    return out_device;
}

/* must be called with adev lock held */
void audio_extn_keep_alive_start()
void audio_extn_keep_alive_start(ka_mode_t ka_mode)
{
    struct audio_device * adev = (struct audio_device *)ka.userdata;
    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
    long app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT];
    int len = 0, rc;
    struct mixer_ctl *ctl;
    int acdb_dev_id, snd_device;
    struct listnode *node;
    struct audio_usecase *usecase;
    int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;

    if (ka.state == STATE_DISABLED)
        return;
    audio_devices_t out_devices = AUDIO_DEVICE_NONE;

    pthread_mutex_lock(&ka.lock);

    if (ka.state == STATE_DEINIT) {
        ALOGE(" %s : Invalid state ",__func__);
    ALOGV("%s: mode %x", __func__, ka_mode);
    if ((ka.state == STATE_DISABLED)||(ka.state == STATE_DEINIT)) {
        ALOGE(" %s : Unexpected state %x",__func__, ka.state);
        goto exit;
    }

    if (audio_extn_passthru_is_active()) {
        ALOGE(" %s : Pass through is already active", __func__);
    out_devices = get_device_id_from_mode(ka_mode);
    if ((out_devices == ka.active_devices) && (ka.state == STATE_ACTIVE)) {
        ALOGV(" %s : Already feeding silence to device %x",__func__, out_devices);
        ka.prev_mode |= ka_mode;
        goto exit;
    }
    ALOGV(" %s : active devices %x, new device %x",__func__, ka.active_devices, out_devices);

    if (ka.state == STATE_ACTIVE) {
        ALOGV(" %s : Keep alive state is already Active",__func__ );
    if (out_devices == AUDIO_DEVICE_NONE)
        goto exit;
    }

    /* Dont start keep_alive if any other PCM session is routed to HDMI*/
    list_for_each(node, &adev->usecase_list) {
         usecase = node_to_item(node, struct audio_usecase, list);
         if (usecase->type == PCM_PLAYBACK &&
                 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
             goto exit;
    }

    ka.done = false;

    /*configure app type */
    int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
                                                        PCM_PLAYBACK);
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "Audio Stream %d App Type Cfg", silence_pcm_dev_id);

    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
              mixer_ctl_name);
        rc = -EINVAL;
    if (audio_extn_passthru_is_active()) {
        ka.active_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
        if(ka.active_devices == AUDIO_DEVICE_NONE)
            goto exit;
    }

    /* Configure HDMI/DP Backend with default values, this as well
     * helps reconfigure HDMI/DP backend after passthrough.
     */
    int ext_disp_type = platform_get_ext_disp_type(adev->platform);
    switch(ext_disp_type) {
        case EXT_DISPLAY_TYPE_HDMI:
            snd_device = SND_DEVICE_OUT_HDMI;
            set_mixer_control(adev->mixer, "HDMI RX Format", "LPCM");
            set_mixer_control(adev->mixer, "HDMI_RX SampleRate", "KHZ_48");
            set_mixer_control(adev->mixer, "HDMI_RX Channels", "Two");
            break;
        case EXT_DISPLAY_TYPE_DP:
            snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
            set_mixer_control(adev->mixer, "Display Port RX Format", "LPCM");
            set_mixer_control(adev->mixer, "Display Port RX SampleRate", "KHZ_48");
            set_mixer_control(adev->mixer, "Display Port RX Channels", "Two");
            break;
        default:
            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
            goto exit;
    ka.active_devices |= out_devices;
    ka.prev_mode |= ka_mode;
    if (ka.state == STATE_ACTIVE) {
        ka.out->devices = ka.active_devices;
        select_devices(adev, USECASE_AUDIO_PLAYBACK_SILENCE);
    } else if (ka.state == STATE_IDLE) {
        keep_alive_start_l();
    }

    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
    if (acdb_dev_id < 0) {
        ALOGE("%s: Couldn't get the acdb dev id", __func__);
        rc = -EINVAL;
        goto exit;
exit:
    pthread_mutex_unlock(&ka.lock);
}

    sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
    app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
    app_type_cfg[len++] = acdb_dev_id;
    app_type_cfg[len++] = sample_rate;
/* must be called with adev lock held */
static int keep_alive_start_l()
{
    struct audio_device * adev = (struct audio_device *)ka.userdata;
    unsigned int flags = PCM_OUT|PCM_MONOTONIC;
    struct audio_usecase *usecase;
    int rc = 0;

    ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
          __func__, __LINE__,
          platform_get_default_app_type(adev->platform),
          acdb_dev_id, sample_rate);
    mixer_ctl_set_array(ctl, app_type_cfg, len);
    int silence_pcm_dev_id =
            platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_SILENCE,
                                       PCM_PLAYBACK);

    /*send calibration*/
    ka.done = false;
    usecase = calloc(1, sizeof(struct audio_usecase));

    if (usecase == NULL) {
        ALOGE("%s: usecase is NULL", __func__);
        rc = -ENOMEM;
        goto exit;
    }

    ka.out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
    if (ka.out == NULL) {
        ALOGE("%s: keep_alive out is NULL", __func__);
        free(usecase);
        rc = -ENOMEM;
        goto exit;
    }

    ka.out->flags = 0;
    ka.out->devices = ka.active_devices;
    ka.out->dev = adev;
    ka.out->format = AUDIO_FORMAT_PCM_16_BIT;
    ka.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
    ka.out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
    ka.out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
    ka.out->config = silence_config;

    usecase->stream.out = ka.out;
    usecase->type = PCM_PLAYBACK;
    usecase->out_snd_device = snd_device;
    usecase->id = USECASE_AUDIO_PLAYBACK_SILENCE;
    usecase->out_snd_device = SND_DEVICE_NONE;
    usecase->in_snd_device = SND_DEVICE_NONE;

    platform_send_audio_calibration(adev->platform, usecase,
                platform_get_default_app_type(adev->platform), sample_rate);
    list_add_tail(&adev->usecase_list, &usecase->list);
    select_devices(adev, USECASE_AUDIO_PLAYBACK_SILENCE);

    /*apply audio route */
    switch(ext_disp_type) {
        case EXT_DISPLAY_TYPE_HDMI:
            audio_route_apply_and_update_path(adev->audio_route, "silence-playback hdmi");
            break;
        case EXT_DISPLAY_TYPE_DP:
            audio_route_apply_and_update_path(adev->audio_route, "silence-playback display-port");
            break;
        default:
            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
    ALOGD("opening pcm device for silence playback %x", silence_pcm_dev_id);
    ka.pcm = pcm_open(adev->snd_card, silence_pcm_dev_id,
                      flags, &silence_config);
    if (ka.pcm == NULL || !pcm_is_ready(ka.pcm)) {
        ALOGE("%s: %s", __func__, pcm_get_error(ka.pcm));
        if (ka.pcm != NULL) {
            pcm_close(ka.pcm);
            ka.pcm = NULL;
        }
        goto exit;
    }

    if (open_silence_stream() == 0) {
    send_cmd_l(REQUEST_WRITE);
    while (ka.state != STATE_ACTIVE) {
        pthread_cond_wait(&ka.cond, &ka.lock);
    }
    }

    return rc;
exit:
    pthread_mutex_unlock(&ka.lock);
    keep_alive_cleanup();
    return rc;
}

/* must be called with adev lock held */
void audio_extn_keep_alive_stop()
void audio_extn_keep_alive_stop(ka_mode_t ka_mode)
{
    struct audio_device * adev = (struct audio_device *)ka.userdata;

    audio_devices_t out_devices;
    if (ka.state == STATE_DISABLED)
        return;

    pthread_mutex_lock(&ka.lock);

    if ((ka.state == STATE_DEINIT) || (ka.state == STATE_IDLE))
    ALOGV("%s: mode %x", __func__, ka_mode);
    if (ka_mode && (ka.state != STATE_ACTIVE)) {
        ALOGV(" %s : Can't stop, keep_alive",__func__);
        ALOGV(" %s : keep_alive is not running on device %x",__func__, get_device_id_from_mode(ka_mode));
        ka.prev_mode |= ka_mode;
        goto exit;
    }
    out_devices = get_device_id_from_mode(ka_mode);
    if (ka.prev_mode & ka_mode) {
        ka.prev_mode &= ~ka_mode;
        ka.active_devices = get_device_id_from_mode(ka.prev_mode);
    }

    if (ka.active_devices == AUDIO_DEVICE_NONE) {
        keep_alive_cleanup();
    } else if (ka.out->devices != ka.active_devices){
        ka.out->devices = ka.active_devices;
        select_devices(adev, USECASE_AUDIO_PLAYBACK_SILENCE);
    }
exit:
    pthread_mutex_unlock(&ka.lock);
}

/* must be called with adev lock held */
static int keep_alive_cleanup()
{
    struct audio_device * adev = (struct audio_device *)ka.userdata;
    struct audio_usecase *uc_info;

    pthread_mutex_lock(&ka.sleep_lock);
    ka.done = true;
    if (ka.out != NULL)
        free(ka.out);

    pthread_mutex_lock(&ka.sleep_lock);
    pthread_cond_signal(&ka.wake_up_cond);
    pthread_mutex_unlock(&ka.sleep_lock);
    while (ka.state != STATE_IDLE) {
        pthread_cond_wait(&ka.cond, &ka.lock);
    }
    close_silence_stream();
    ALOGV("%s: keep_alive state changed to %x", __func__, ka.state);

    /*apply audio route */
    int ext_disp_type = platform_get_ext_disp_type(adev->platform);
    switch(ext_disp_type) {
        case EXT_DISPLAY_TYPE_HDMI:
            audio_route_reset_and_update_path(adev->audio_route, "silence-playback hdmi");
            break;
        case EXT_DISPLAY_TYPE_DP:
            audio_route_reset_and_update_path(adev->audio_route, "silence-playback display-port");
            break;
        default:
            ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
    uc_info = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_SILENCE);
    if (uc_info == NULL) {
        ALOGE("%s: Could not find keep alive usecase in the list", __func__);
    } else {
        disable_audio_route(adev, uc_info);
        disable_snd_device(adev, uc_info->out_snd_device);
        list_remove(&uc_info->list);
        free(uc_info);
    }

exit:
    pthread_mutex_unlock(&ka.lock);
}

bool audio_extn_keep_alive_is_active()
{
    return ka.state == STATE_ACTIVE;
    pcm_close(ka.pcm);
    ka.pcm = NULL;
    ka.active_devices = KEEP_ALIVE_OUT_NONE;
    return 0;
}

int audio_extn_keep_alive_set_parameters(struct audio_device *adev __unused,
                                         struct str_parms *parms)
                                         struct str_parms *parms __unused)
{
    char value[32];
    int ret;

    int ret, pcm_device_id=0;
    if (ka.state == STATE_DISABLED)
        return 0;

    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
    if ((ka.state == STATE_ACTIVE) && (ka.prev_mode & KEEP_ALIVE_OUT_PRIMARY)){
        ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
                                value, sizeof(value));
        if (ret >= 0) {
        int val = atoi(value);
        if (audio_is_output_devices(val) &&
            (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
            if (!audio_extn_passthru_is_active()) {
                ALOGV("start keep alive");
                audio_extn_keep_alive_start();
            }
        }
            pcm_device_id = atoi(value);
            if(pcm_device_id > 0)
            {
                audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
            }

    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
                            sizeof(value));
    if (ret >= 0) {
        int val = atoi(value);
        if (audio_is_output_devices(val) &&
            (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
            ALOGV("stop keep_alive");
            audio_extn_keep_alive_stop();
        }
    }
    return 0;
}


static void * keep_alive_loop(void * context __unused)
{
    struct keep_alive_cmd *cmd = NULL;
@@ -424,7 +403,11 @@ static void * keep_alive_loop(void * context __unused)
        cmd = node_to_item(item, struct keep_alive_cmd, node);
        list_remove(item);

        if (cmd->req != REQUEST_WRITE) {
        if (cmd->req == REQUEST_QUIT) {
            free(cmd);
            pthread_mutex_unlock(&ka.lock);
            break;
        } else if (cmd->req != REQUEST_WRITE) {
            free(cmd);
            pthread_mutex_unlock(&ka.lock);
            continue;
@@ -432,6 +415,7 @@ static void * keep_alive_loop(void * context __unused)

        free(cmd);
        ka.state = STATE_ACTIVE;
        ALOGV("%s: state changed to %x", __func__, ka.state);
        pthread_cond_signal(&ka.cond);
        pthread_mutex_unlock(&ka.lock);

@@ -462,6 +446,7 @@ static void * keep_alive_loop(void * context __unused)
        }
        pthread_mutex_lock(&ka.lock);
        ka.state = STATE_IDLE;
        ALOGV("%s: state changed to %x", __func__, ka.state);
        pthread_cond_signal(&ka.cond);
        pthread_mutex_unlock(&ka.lock);
    }

hal/audio_extn/passthru.c

100644 → 100755
+26 −4
Original line number Diff line number Diff line
/*
* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-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
@@ -309,8 +309,8 @@ void audio_extn_passthru_on_stop(struct stream_out * out)
    }

    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
        ALOGI("passthru on aux digital, start keep alive");
        audio_extn_keep_alive_start();
        ALOGD("%s: passthru on aux digital, start keep alive", __func__);
        audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
    }
}

@@ -321,8 +321,30 @@ void audio_extn_passthru_on_pause(struct stream_out * out __unused)
}

int audio_extn_passthru_set_parameters(struct audio_device *adev __unused,
                                       struct str_parms *parms __unused)
                                       struct str_parms *parms)
{
    char value[32];
    int ret;
    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
    if (ret >= 0) {
        int val = atoi(value);
        if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
            if (!audio_extn_passthru_is_active()) {
                ALOGV("%s: start keep alive on aux digital", __func__);
                audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
            }
        }
    }

    ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
                            sizeof(value));
    if (ret >= 0) {
        int val = atoi(value);
        if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
            ALOGV("%s: stop keep_alive on aux digital on device", __func__);
            audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
        }
    }
    return 0;
}

Loading