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

Commit 0d84c8ee authored by Weiyin Jiang's avatar Weiyin Jiang Committed by Gerrit - the friendly Code Review server
Browse files

hal: optimize switch from combo to solo device

For playback usecases routing change, audio HAL disables sound device
if existing sound device does not match derived sound device and
enables the derived sound device. It does not check whether existing
sound device is a combination multiple devices and if one of those
devices matches with the derived sound device.

With scenarios like ringtone over speaker-and-bt-a2dp followed by
a2dp playback, we disable and re-enable bt-a2dp. This is unneeded
if a2dp backend is already active. Optimze such scenarios by
disabling only devices that do not match the derived sound device.

This change squashes the followings.
I171fbead85746a2a34632f7580f56ef40505665c
(hal: Prevent superfluous device tear down on routing change)
Id1bd00bfa5f0236400529e5771851749421ac84c
(hal: Fix combo device issue with routing change)
I4afb4a573de68f17d0ff9af63403713065bfec12
(hal: align ref_cnt of combo device and its split devices)

Change-Id: I359b8a98c76206acd9085431c393825aa6dd0425
parent c53786af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -738,6 +738,7 @@ bool audio_extn_utils_is_dolby_format(audio_format_t format);
int audio_extn_utils_get_bit_width_from_string(const char *);
int audio_extn_utils_get_sample_rate_from_string(const char *);
int audio_extn_utils_get_channels_from_string(const char *);
void audio_extn_utils_release_snd_device(snd_device_t snd_device);

#ifdef DS2_DOLBY_DAP_ENABLED
#define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
+9 −0
Original line number Diff line number Diff line
@@ -2719,6 +2719,15 @@ int audio_extn_utils_get_channels_from_string(const char *id_string)
    return -EINVAL;
}

void audio_extn_utils_release_snd_device(snd_device_t snd_device)
{
    audio_extn_dev_arbi_release(snd_device);
    audio_extn_sound_trigger_update_device_status(snd_device,
            ST_EVENT_SND_DEVICE_FREE);
    audio_extn_listen_update_device_status(snd_device,
            LISTEN_EVENT_SND_DEVICE_FREE);
}

int audio_extn_utils_get_license_params
(
const struct audio_device *adev,
+85 −45
Original line number Diff line number Diff line
@@ -1121,19 +1121,23 @@ int enable_snd_device(struct audio_device *adev,
        return -EINVAL;
    }

    adev->snd_dev_ref_cnt[snd_device]++;

    if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
        ALOGE("%s: Invalid sound device returned", __func__);
        return -EINVAL;
    }
    if (adev->snd_dev_ref_cnt[snd_device] > 1) {

    adev->snd_dev_ref_cnt[snd_device]++;

    if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
            (platform_split_snd_device(adev->platform,
                                       snd_device,
                                       &num_devices,
                                       new_snd_devices) != 0)) {
        ALOGV("%s: snd_device(%d: %s) is already active",
              __func__, snd_device, device_name);
        return 0;
    }


    if (audio_extn_spkr_prot_is_enabled())
         audio_extn_spkr_prot_calib_cancel(adev);

@@ -1142,14 +1146,13 @@ int enable_snd_device(struct audio_device *adev,
    if (platform_can_enable_spkr_prot_on_device(snd_device) &&
         audio_extn_spkr_prot_is_enabled()) {
        if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
           adev->snd_dev_ref_cnt[snd_device]--;
           return -EINVAL;
            goto err;
        }
        audio_extn_dev_arbi_acquire(snd_device);
        if (audio_extn_spkr_prot_start_processing(snd_device)) {
            ALOGE("%s: spkr_start_processing failed", __func__);
            audio_extn_dev_arbi_release(snd_device);
            return -EINVAL;
            goto err;
        }
    } else if (platform_split_snd_device(adev->platform,
                                         snd_device,
@@ -1166,13 +1169,13 @@ int enable_snd_device(struct audio_device *adev,
        if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
            (audio_extn_a2dp_start_playback() < 0)) {
            ALOGE(" fail to configure A2dp Source control path ");
           return -EINVAL;
            goto err;
        }

        if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
            (audio_extn_a2dp_start_capture() < 0)) {
            ALOGE(" fail to configure A2dp Sink control path ");
           return -EINVAL;
            goto err;
        }

        /* due to the possibility of calibration overwrite between listen
@@ -1182,12 +1185,11 @@ int enable_snd_device(struct audio_device *adev,
        audio_extn_listen_update_device_status(snd_device,
                                        LISTEN_EVENT_SND_DEVICE_BUSY);
        if (platform_get_snd_device_acdb_id(snd_device) < 0) {
            adev->snd_dev_ref_cnt[snd_device]--;
            audio_extn_sound_trigger_update_device_status(snd_device,
                                            ST_EVENT_SND_DEVICE_FREE);
            audio_extn_listen_update_device_status(snd_device,
                                        LISTEN_EVENT_SND_DEVICE_FREE);
            return -EINVAL;
            goto err;
        }
        audio_extn_dev_arbi_acquire(snd_device);
        audio_route_apply_and_update_path(adev->audio_route, device_name);
@@ -1209,6 +1211,9 @@ int enable_snd_device(struct audio_device *adev,
        }
    }
    return 0;
err:
    adev->snd_dev_ref_cnt[snd_device]--;
    return -EINVAL;;
}

int disable_snd_device(struct audio_device *adev,
@@ -1223,6 +1228,12 @@ int disable_snd_device(struct audio_device *adev,
        ALOGE("%s: Invalid sound device %d", __func__, snd_device);
        return -EINVAL;
    }

    if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
        ALOGE("%s: Invalid sound device returned", __func__);
        return -EINVAL;
    }

    if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
        ALOGE("%s: device ref cnt is already 0", __func__);
        return -EINVAL;
@@ -1230,10 +1241,6 @@ int disable_snd_device(struct audio_device *adev,

    adev->snd_dev_ref_cnt[snd_device]--;

    if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
        ALOGE("%s: Invalid sound device returned", __func__);
        return -EINVAL;
    }

    if (adev->snd_dev_ref_cnt[snd_device] == 0) {
        ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
@@ -1259,38 +1266,42 @@ int disable_snd_device(struct audio_device *adev,
            audio_route_reset_and_update_path(adev->audio_route, device_name);
        }

        if (SND_DEVICE_OUT_BT_A2DP == snd_device)
        if (snd_device == SND_DEVICE_OUT_BT_A2DP)
            audio_extn_a2dp_stop_playback();

        if (SND_DEVICE_IN_BT_A2DP == snd_device)
        else if (snd_device == SND_DEVICE_IN_BT_A2DP)
            audio_extn_a2dp_stop_capture();

        if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
        else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
                (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
            adev->is_channel_status_set = false;
        else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
        else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
                 adev->native_playback_enabled) {
            ALOGD("%s: %d: napb: disabling native mode in hardware",
                  __func__, __LINE__);
            audio_route_reset_and_update_path(adev->audio_route,
                                              "true-native-mode");
            adev->native_playback_enabled = false;
        } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
        } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
                 adev->asrc_mode_enabled) {
            ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
            disable_asrc_mode(adev);
            audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
        }
        if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
        } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
            (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
            (audio_extn_ffv_get_stream() == adev->active_input)) {
            ALOGD("%s: deinit ec ref loopback", __func__);
            audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
        }
        audio_extn_dev_arbi_release(snd_device);
        audio_extn_sound_trigger_update_device_status(snd_device,
                                        ST_EVENT_SND_DEVICE_FREE);
        audio_extn_listen_update_device_status(snd_device,
                                        LISTEN_EVENT_SND_DEVICE_FREE);

        audio_extn_utils_release_snd_device(snd_device);
    } else {
        if (platform_split_snd_device(adev->platform,
                    snd_device,
                    &num_devices,
                    new_snd_devices) == 0) {
            for (i = 0; i < num_devices; i++) {
                adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
            }
        }
    }

    return 0;
@@ -1433,7 +1444,8 @@ static void check_usecases_codec_backend(struct audio_device *adev,
    bool switch_device[AUDIO_USECASE_MAX];
    snd_device_t uc_derive_snd_device;
    snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
    int i, num_uc_to_switch = 0;
    snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
    int i, num_uc_to_switch = 0, num_devices = 0;
    int status = 0;
    bool force_restart_session = false;
    /*
@@ -1515,14 +1527,42 @@ static void check_usecases_codec_backend(struct audio_device *adev,
        list_for_each(node, &adev->usecase_list) {
            usecase = node_to_item(node, struct audio_usecase, list);
            if (switch_device[usecase->id]) {
                /* Check if output sound device to be switched can be split and if any
                   of the split devices match with derived sound device */
                if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
                                               &num_devices, split_snd_devices) == 0) {
                    adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
                    for (i = 0; i < num_devices; i++) {
                        /* Disable devices that do not match with derived sound device */
                        if (split_snd_devices[i] != derive_snd_device[usecase->id])
                            disable_snd_device(adev, split_snd_devices[i]);
                     }
                } else {
                    disable_snd_device(adev, usecase->out_snd_device);
                }
            }
        }

        list_for_each(node, &adev->usecase_list) {
            usecase = node_to_item(node, struct audio_usecase, list);
            if (switch_device[usecase->id]) {
                if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
                                               &num_devices, split_snd_devices) == 0) {
                        /* Enable derived sound device only if it does not match with
                           one of the split sound devices. This is because the matching
                           sound device was not disabled */
                        bool should_enable = true;
                        for (i = 0; i < num_devices; i++) {
                            if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
                                 should_enable = false;
                                 break;
                            }
                        }
                        if (should_enable)
                            enable_snd_device(adev, derive_snd_device[usecase->id]);
                } else {
                    enable_snd_device(adev, derive_snd_device[usecase->id]);
                }
            }
        }