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

Commit 3bb73585 authored by Shiv Maliyappanahalli's avatar Shiv Maliyappanahalli
Browse files

hal: end all calls when setmode(AUDIO_MODE_NORMAL) is called

Telephony will call set_mode(AUDIO_MODE_NORMAL) when a
call is ended which will trigger audio policy manager setting
routing with audio usecase compatible device. Voice calls can
still be active if RIL has not yet called
setparameters(vsid,callstate). This would result in routing
voice call usecases with incompatible device for voice calls.
Fix this by ending all voice calls when set_mode(MODE_NORMAL)
is called.

Change-Id: Id2c9f2ff9ed46969e5cbd27b525b81735c1d49d8
parent 9381e58a
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ struct pcm_config pcm_config_audio_capture = {
    .format = PCM_FORMAT_S16_LE,
};

static const char * const use_case_table[AUDIO_USECASE_MAX] = {
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",
@@ -2083,7 +2083,9 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
    int val;
    int ret;

    ALOGV("%s: enter: %s", __func__, kvpairs);
    ALOGD("%s: enter: %s", __func__, kvpairs);

    pthread_mutex_lock(&adev->lock);
    parms = str_parms_create_str(kvpairs);

    voice_set_parameters(adev, parms);
@@ -2125,7 +2127,6 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
        default:
            ALOGE("%s: unexpected rotation of %d", __func__, val);
        }
        pthread_mutex_lock(&adev->lock);
        if (adev->speaker_lr_swap != reverse_speakers) {
            adev->speaker_lr_swap = reverse_speakers;
            // only update the selected device if there is active pcm playback
@@ -2139,11 +2140,12 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
                }
            }
        }
        pthread_mutex_unlock(&adev->lock);
    }

    audio_extn_set_parameters(adev, parms);
    str_parms_destroy(parms);

    pthread_mutex_unlock(&adev->lock);
    ALOGV("%s: exit with code(%d)", __func__, ret);
    return ret;
}
@@ -2156,12 +2158,15 @@ static char* adev_get_parameters(const struct audio_hw_device *dev,
    struct str_parms *query = str_parms_create_str(keys);
    char *str;

    pthread_mutex_lock(&adev->lock);

    audio_extn_get_parameters(adev, query, reply);
    platform_get_parameters(adev->platform, query, reply);
    str = str_parms_to_str(reply);
    str_parms_destroy(query);
    str_parms_destroy(reply);

    pthread_mutex_unlock(&adev->lock);
    ALOGV("%s: exit: returns - %s", __func__, str);
    return str;
}
@@ -2217,7 +2222,13 @@ static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)

static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
{
    return voice_set_mic_mute((struct audio_device *)dev, state);
    int ret;

    pthread_mutex_lock(&adev->lock);
    ret = voice_set_mic_mute((struct audio_device *)dev, state);
    pthread_mutex_unlock(&adev->lock);

    return ret;
}

static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
+0 −6
Original line number Diff line number Diff line
@@ -1033,19 +1033,15 @@ int platform_set_parameters(void *platform, struct str_parms *parms)
    ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
    if (ret >= 0) {
        str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
        pthread_mutex_lock(&my_data->adev->lock);
        my_data->btsco_sample_rate = val;
        pthread_mutex_unlock(&my_data->adev->lock);
    }

    ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SLOWTALK, &val);
    if (ret >= 0) {
        str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK);
        pthread_mutex_lock(&my_data->adev->lock);
        ret = platform_set_slowtalk(my_data, val);
        if (ret)
            ALOGE("%s: Failed to set slow talk err: %d", __func__, ret);
        pthread_mutex_unlock(&my_data->adev->lock);
    }

    ALOGV("%s: exit with code(%d)", __func__, ret);
@@ -1095,7 +1091,6 @@ void platform_get_parameters(void *platform,
    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
                            value, sizeof(value));
    if (ret >= 0) {
        pthread_mutex_lock(&my_data->adev->lock);
        if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
            strlcpy(value, "fluencepro", sizeof(value));
        } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
@@ -1103,7 +1098,6 @@ void platform_get_parameters(void *platform,
        } else {
            strlcpy(value, "none", sizeof(value));
        }
        pthread_mutex_unlock(&my_data->adev->lock);

        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
    }
+6 −24
Original line number Diff line number Diff line
@@ -41,20 +41,7 @@ struct pcm_config pcm_config_voice_call = {
    .format = PCM_FORMAT_S16_LE,
};

extern struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
                                                   audio_usecase_t uc_id);
extern int disable_snd_device(struct audio_device *adev,
                              snd_device_t snd_device,
                              bool update_mixer);
extern int disable_audio_route(struct audio_device *adev,
                               struct audio_usecase *usecase,
                               bool update_mixer);

extern int disable_snd_device(struct audio_device *adev,
                              snd_device_t snd_device,
                              bool update_mixer);
extern int select_devices(struct audio_device *adev,
                          audio_usecase_t uc_id);
extern const char * const use_case_table[AUDIO_USECASE_MAX];

static struct voice_session *voice_get_session_from_use_case(struct audio_device *adev,
                              audio_usecase_t usecase_id)
@@ -76,7 +63,7 @@ int stop_call(struct audio_device *adev, audio_usecase_t usecase_id)
    struct audio_usecase *uc_info;
    struct voice_session *session = NULL;

    ALOGD("%s: enter", __func__);
    ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);

    session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
    session->state.current = CALL_INACTIVE;
@@ -124,10 +111,10 @@ int start_call(struct audio_device *adev, audio_usecase_t usecase_id)
    int pcm_dev_rx_id, pcm_dev_tx_id;
    struct voice_session *session = NULL;
    struct pcm_config voice_config = pcm_config_voice_call;
    ALOGD("%s: enter", __func__);

    session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
    ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);

    session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
    uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
    uc_info->id = usecase_id;
    uc_info->type = VOICE_CALL;
@@ -274,14 +261,11 @@ int voice_set_mic_mute(struct audio_device *adev, bool state)
{
    int err = 0;

    pthread_mutex_lock(&adev->lock);

    err = platform_set_mic_mute(adev->platform, state);
    if (!err) {
        adev->voice.mic_mute = state;
    }

    pthread_mutex_unlock(&adev->lock);
    return err;
}

@@ -319,7 +303,7 @@ int voice_start_call(struct audio_device *adev)
{
    int ret = 0;

    ret = voice_extn_update_calls(adev);
    ret = voice_extn_start_call(adev);
    if (ret == -ENOSYS) {
        ret = start_call(adev, USECASE_VOICE_CALL);
    }
@@ -331,7 +315,7 @@ int voice_stop_call(struct audio_device *adev)
{
    int ret = 0;

    ret = voice_extn_update_calls(adev);
    ret = voice_extn_stop_call(adev);
    if (ret == -ENOSYS) {
        ret = stop_call(adev, USECASE_VOICE_CALL);
    }
@@ -367,7 +351,6 @@ int voice_set_parameters(struct audio_device *adev, struct str_parms *parms)
            goto done;
        }

        pthread_mutex_lock(&adev->lock);
        if (tty_mode != adev->voice.tty_mode) {
            adev->voice.tty_mode = tty_mode;
            adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
@@ -375,7 +358,6 @@ int voice_set_parameters(struct audio_device *adev, struct str_parms *parms)
                //todo: what about voice2, volte and qchat usecases?
                select_devices(adev, USECASE_VOICE_CALL);
        }
        pthread_mutex_unlock(&adev->lock);
    }

done:
+139 −106
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ struct pcm_config pcm_config_incall_music = {

extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
int voice_extn_update_calls(struct audio_device *adev);
int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);

static bool is_valid_call_state(int call_state)
{
@@ -130,104 +130,7 @@ static uint32_t get_session_id_with_state(struct audio_device *adev,
    return session_id;
}

int voice_extn_get_active_session_id(struct audio_device *adev,
                                     uint32_t *session_id)
{
    *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
    return 0;
}

int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
{
    struct voice_session *session = NULL;
    int i = 0;
    *in_call = false;

    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
        session = &adev->voice.session[i];
        if(session->state.current != CALL_INACTIVE){
            *in_call = true;
            break;
        }
    }

    return 0;
}

static int voice_extn_update_call_states(struct audio_device *adev,
                                    const uint32_t vsid, const int call_state)
{
    struct voice_session *session = NULL;
    int i = 0;
    bool is_in_call;

    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
        if (vsid == adev->voice.session[i].vsid) {
            session = &adev->voice.session[i];
            break;
        }
    }

    if (session) {
        session->state.new = call_state;
        voice_extn_is_in_call(adev, &is_in_call);
        ALOGD("%s is_in_call:%d mode:%d\n", __func__, is_in_call, adev->mode);
        if (is_in_call || adev->mode == AUDIO_MODE_IN_CALL) {
            /* Device routing is not triggered for voice calls on the subsequent
             * subs, Hence update the call states if voice call is already
             * active on other sub.
             */
            voice_extn_update_calls(adev);
        }
    } else {
        return -EINVAL;
    }

    return 0;

}

void voice_extn_init(struct audio_device *adev)
{
    adev->voice.session[VOICE_SESS_IDX].vsid =  VOICE_VSID;
    adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
    adev->voice.session[VOLTE_SESS_IDX].vsid =  VOLTE_VSID;
    adev->voice.session[QCHAT_SESS_IDX].vsid =  QCHAT_VSID;
}

int voice_extn_get_session_from_use_case(struct audio_device *adev,
                                               const audio_usecase_t usecase_id,
                                               struct voice_session **session)
{

    switch(usecase_id)
    {
    case USECASE_VOICE_CALL:
        *session = &adev->voice.session[VOICE_SESS_IDX];
        break;

    case USECASE_VOICE2_CALL:
        *session = &adev->voice.session[VOICE2_SESS_IDX];
        break;

    case USECASE_VOLTE_CALL:
        *session = &adev->voice.session[VOLTE_SESS_IDX];
        break;

    case USECASE_QCHAT_CALL:
        *session = &adev->voice.session[QCHAT_SESS_IDX];
        break;

    default:
        ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
        *session = NULL;
        return -EINVAL;
    }

    return 0;
}

int voice_extn_update_calls(struct audio_device *adev)
static int update_calls(struct audio_device *adev)
{
    int i = 0;
    audio_usecase_t usecase_id = 0;
@@ -255,8 +158,9 @@ int voice_extn_update_calls(struct audio_device *adev)
                if(ret < 0) {
                    ALOGE("%s: voice_start_call() failed for usecase: %d\n",
                          __func__, usecase_id);
                }
                } else {
                    session->state.current = session->state.new;
                }
                break;

            case CALL_HOLD:
@@ -292,8 +196,9 @@ int voice_extn_update_calls(struct audio_device *adev)
                if(ret < 0) {
                    ALOGE("%s: voice_end_call() failed for usecase: %d\n",
                          __func__, usecase_id);
                }
                } else {
                    session->state.current = session->state.new;
                }
                break;

            default:
@@ -358,6 +263,136 @@ int voice_extn_update_calls(struct audio_device *adev)
    return ret;
}

static int update_call_states(struct audio_device *adev,
                                    const uint32_t vsid, const int call_state)
{
    struct voice_session *session = NULL;
    int i = 0;
    bool is_in_call;

    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
        if (vsid == adev->voice.session[i].vsid) {
            session = &adev->voice.session[i];
            break;
        }
    }

    if (session) {
        session->state.new = call_state;
        voice_extn_is_in_call(adev, &is_in_call);
        ALOGD("%s is_in_call:%d mode:%d\n", __func__, is_in_call, adev->mode);
        if (is_in_call || adev->mode == AUDIO_MODE_IN_CALL) {
            /* Device routing is not triggered for voice calls on the subsequent
             * subs, Hence update the call states if voice call is already
             * active on other sub.
             */
            update_calls(adev);
        }
    } else {
        return -EINVAL;
    }

    return 0;

}

int voice_extn_get_active_session_id(struct audio_device *adev,
                                     uint32_t *session_id)
{
    *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
    return 0;
}

int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
{
    struct voice_session *session = NULL;
    int i = 0;
    *in_call = false;

    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
        session = &adev->voice.session[i];
        if(session->state.current != CALL_INACTIVE){
            *in_call = true;
            break;
        }
    }

    return 0;
}

void voice_extn_init(struct audio_device *adev)
{
    adev->voice.session[VOICE_SESS_IDX].vsid =  VOICE_VSID;
    adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
    adev->voice.session[VOLTE_SESS_IDX].vsid =  VOLTE_VSID;
    adev->voice.session[QCHAT_SESS_IDX].vsid =  QCHAT_VSID;
}

int voice_extn_get_session_from_use_case(struct audio_device *adev,
                                         const audio_usecase_t usecase_id,
                                         struct voice_session **session)
{

    switch(usecase_id)
    {
    case USECASE_VOICE_CALL:
        *session = &adev->voice.session[VOICE_SESS_IDX];
        break;

    case USECASE_VOICE2_CALL:
        *session = &adev->voice.session[VOICE2_SESS_IDX];
        break;

    case USECASE_VOLTE_CALL:
        *session = &adev->voice.session[VOLTE_SESS_IDX];
        break;

    case USECASE_QCHAT_CALL:
        *session = &adev->voice.session[QCHAT_SESS_IDX];
        break;

    default:
        ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
        *session = NULL;
        return -EINVAL;
    }

    return 0;
}

int voice_extn_start_call(struct audio_device *adev)
{
    /* Start voice calls on sessions whose call state has been
     * udpated.
     */
    ALOGV("%s: enter:", __func__);
    return update_calls(adev);
}

int voice_extn_stop_call(struct audio_device *adev)
{
    int i;
    int ret = 0;

    ALOGV("%s: enter:", __func__);

    /* If BT device is enabled and voice calls are ended, telephony will call
     * set_mode(AUDIO_MODE_NORMAL) which will trigger audio policy manager to
     * set routing with device BT A2DP profile. Hence end all voice calls when
     * set_mode(AUDIO_MODE_NORMAL) before BT A2DP profile is selected.
     */
    if (adev->mode == AUDIO_MODE_NORMAL) {
        ALOGD("%s: end all calls", __func__);
        for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
            adev->voice.session[i].state.new = CALL_INACTIVE;
        }

        ret = update_calls(adev);
    }

    return ret;
}

int voice_extn_set_parameters(struct audio_device *adev,
                              struct str_parms *parms)
{
@@ -375,7 +410,6 @@ int voice_extn_set_parameters(struct audio_device *adev,
        ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
        if (ret >= 0) {
            call_state = value;
            //validate callstate
        } else {
            ALOGE("%s: call_state key not found", __func__);
            ret = -EINVAL;
@@ -383,11 +417,10 @@ int voice_extn_set_parameters(struct audio_device *adev,
        }

        if (is_valid_vsid(vsid) && is_valid_call_state(call_state)) {
            pthread_mutex_lock(&adev->lock);
            voice_extn_update_call_states(adev, vsid, call_state);
            pthread_mutex_unlock(&adev->lock);
            ret = update_call_states(adev, vsid, call_state);
        } else {
            ALOGE("%s: invalid vsid or call_state", __func__);
            ALOGE("%s: invalid vsid:%x or call_state:%d",
                  __func__, vsid, call_state);
            ret = -EINVAL;
            goto done;
        }
+10 −5
Original line number Diff line number Diff line
@@ -21,18 +21,24 @@
#define VOICE_EXTN_H

#ifdef MULTI_VOICE_SESSION_ENABLED
int voice_extn_update_calls(struct audio_device *adev);
int voice_extn_start_call(struct audio_device *adev);
int voice_extn_stop_call(struct audio_device *adev);
int voice_extn_get_session_from_use_case(struct audio_device *adev,
                                         const audio_usecase_t usecase_id,
                                         struct voice_session **session);
int voice_extn_init(struct audio_device *adev);
void voice_extn_init(struct audio_device *adev);
int voice_extn_set_parameters(struct audio_device *adev,
                              struct str_parms *parms);
int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
int voice_extn_get_active_session_id(struct audio_device *adev,
                                     uint32_t *session_id);
#else
static int voice_extn_update_calls(struct audio_device *adev)
static int voice_extn_start_call(struct audio_device *adev)
{
    return -ENOSYS;
}

static int voice_extn_stop_call(struct audio_device *adev)
{
    return -ENOSYS;
}
@@ -44,9 +50,8 @@ static int voice_extn_get_session_from_use_case(struct audio_device *adev,
    return -ENOSYS;
}

static int voice_extn_init(struct audio_device *adev)
static void voice_extn_init(struct audio_device *adev)
{
    return -ENOSYS;
}

static int voice_extn_set_parameters(struct audio_device *adev,