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

Commit 9d027a65 authored by Naresh Tanniru's avatar Naresh Tanniru Committed by Gerrit - the friendly Code Review server
Browse files

audio: Add support to enable split A2DP

- Add new audio extension module for a2dp
- Add support to configure AFE encoder based
  on BT device capabilities
- Add support for soft handoff to re-configure
  AFE based on new BT device capability

Change-Id: I5d710fda1a8d8fa3b5d85aaa2b3096cff8fd7ce5
parent 207afaab
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -243,6 +243,11 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SOURCE_TRACKING)),true)
    LOCAL_SRC_FILES += audio_extn/source_track.c
endif

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SPLIT_A2DP)),true)
    LOCAL_CFLAGS += -DSPLIT_A2DP_ENABLED
    LOCAL_SRC_FILES += audio_extn/a2dp.c
endif

LOCAL_SHARED_LIBRARIES := \
	liblog \
	libcutils \
@@ -251,6 +256,7 @@ LOCAL_SHARED_LIBRARIES := \
	libaudioroute \
	libdl \
	libaudioutils \
	libhardware \
	libexpat

LOCAL_C_INCLUDES += \

hal/audio_extn/a2dp.c

0 → 100644
+733 −0

File added.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Diff line number Diff line
@@ -755,6 +755,7 @@ void audio_extn_set_parameters(struct audio_device *adev,
   audio_extn_ssr_set_parameters(adev, parms);
   audio_extn_hfp_set_parameters(adev, parms);
   audio_extn_dts_eagle_set_parameters(adev, parms);
   audio_extn_a2dp_set_parameters(parms);
   audio_extn_ddp_set_parameters(adev, parms);
   audio_extn_ds2_set_parameters(adev, parms);
   audio_extn_customstereo_set_parameters(adev, parms);
+14 −0
Original line number Diff line number Diff line
@@ -171,6 +171,20 @@ int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
                                     char *value, int len);
#endif

#ifndef SPLIT_A2DP_ENABLED
#define audio_extn_a2dp_init(adev)                       (0)
#define audio_extn_a2dp_start_playback()                 (0)
#define audio_extn_a2dp_stop_playback()                  (0)
#define audio_extn_a2dp_set_parameters(parms)            (0)
#define audio_extn_a2dp_is_force_device_switch()         (0)
#else
void audio_extn_a2dp_init(void *adev);
int audio_extn_a2dp_start_playback();
void audio_extn_a2dp_stop_playback();
void audio_extn_a2dp_set_parameters(struct str_parms *parms);
bool audio_extn_a2dp_is_force_device_switch();
#endif

#ifndef SSR_ENABLED
#define audio_extn_ssr_check_and_set_usecase(in)      (0)
#define audio_extn_ssr_init(in, num_out_chan)         (0)
+60 −4
Original line number Diff line number Diff line
@@ -716,6 +716,13 @@ int enable_snd_device(struct audio_device *adev,
         audio_extn_spkr_prot_calib_cancel(adev);


    if (((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
       (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
        && (audio_extn_a2dp_start_playback() < 0)) {
           ALOGE(" fail to configure A2dp control path ");
           return -EINVAL;
    }

    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) {
@@ -791,6 +798,11 @@ int disable_snd_device(struct audio_device *adev,

    if (adev->snd_dev_ref_cnt[snd_device] == 0) {
        ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);

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

        if (platform_can_enable_spkr_prot_on_device(snd_device) &&
             audio_extn_spkr_prot_is_enabled()) {
            audio_extn_spkr_prot_stop_processing(snd_device);
@@ -832,7 +844,7 @@ static void check_usecases_codec_backend(struct audio_device *adev,
    struct audio_usecase *usecase;
    bool switch_device[AUDIO_USECASE_MAX];
    int i, num_uc_to_switch = 0;

    bool force_restart_session = false;
    /*
     * This function is to make sure that all the usecases that are active on
     * the hardware codec backend are always routed to any one device that is
@@ -852,7 +864,15 @@ static void check_usecases_codec_backend(struct audio_device *adev,
     */
    bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
                         snd_device);

    /* For a2dp device reconfigure all active sessions
     * with new AFE encoder format based on a2dp state
     */
    if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
         SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
         audio_extn_a2dp_is_force_device_switch()) {
         force_routing = true;
         force_restart_session = true;
    }
    ALOGD("%s:becf: force routing %d", __func__, force_routing);

    /* Disable all the usecases on the shared backend other than the
@@ -872,7 +892,8 @@ static void check_usecases_codec_backend(struct audio_device *adev,
        if (usecase->type != PCM_CAPTURE &&
            usecase != uc_info &&
            (usecase->out_snd_device != snd_device || force_routing) &&
            usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
            (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
            force_restart_session) &&
            platform_check_backends_match(snd_device, usecase->out_snd_device)) {
                ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
                    __func__, use_case_table[usecase->id],
@@ -1163,6 +1184,14 @@ static bool force_device_switch(struct audio_usecase *usecase)
        }
    }

    // Force all a2dp output devices to reconfigure for proper AFE encode format
    if((usecase->stream.out) &&
       (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
       audio_extn_a2dp_is_force_device_switch()) {
         ALOGD("Force a2dp device switch to update new encoder config");
         ret = true;
     }

    return ret;
}

@@ -2452,6 +2481,17 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
                (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
            val = AUDIO_DEVICE_OUT_SPEAKER;
        }
        /*
         * When A2DP is disconnected the
         * music playback is paused and the policy manager sends routing=0
         * But the audioflingercontinues to write data until standby time
         * (3sec). As BT is turned off, the write gets blocked.
         * Avoid this by routing audio to speaker until standby.
         */
        if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
                (val == AUDIO_DEVICE_NONE)) {
                val = AUDIO_DEVICE_OUT_SPEAKER;
        }

        /*
         * select_devices() call below switches all the usecases on the same
@@ -4174,6 +4214,22 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
    }

    audio_extn_set_parameters(adev, parms);
    // reconfigure should be done only after updating a2dpstate in audio extn
    ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
    if (ret >= 0) {
        struct audio_usecase *usecase;
        struct listnode *node;
        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_BLUETOOTH_A2DP)){
                ALOGD("reconfigure a2dp... forcing device switch");
                //force device switch to re configure encoder
                select_devices(adev, usecase->id);
                break;
            }
        }
    }

done:
    str_parms_destroy(parms);
Loading