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

Commit 0499d4fc authored by Eric Laurent's avatar Eric Laurent Committed by Vineeta Srivastava
Browse files

hal: add support for external speaker driver library

Change-Id: I599c96793097ab6202412cbd55c8e9165c226eed

Bug:  17319721
parent 39ace3da
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES := \
	audio_hw.c \
	voice.c \
	platform_info.c \
	audio_extn/ext_speaker.c \
	$(AUDIO_PLATFORM)/platform.c

LOCAL_SHARED_LIBRARIES := \
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@

#include <cutils/str_parms.h>

void *audio_extn_extspk_init(struct audio_device *adev);
void audio_extn_extspk_deinit(void *extn);
void audio_extn_extspk_update(void* extn);
void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode);

#ifndef HFP_ENABLED
#define audio_extn_hfp_is_active(adev)                  (0)
#define audio_extn_hfp_get_usecase()                    (-1)
+149 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "ext_speaker"
/*#define LOG_NDEBUG 0*/
#include <cutils/log.h>

#include <audio_hw.h>
#include <dlfcn.h>

#ifdef __LP64__
        #define LIB_SPEAKER_BUNDLE "/system/lib64/soundfx/libspeakerbundle.so"
#else
        #define LIB_SPEAKER_BUNDLE "/system/lib/soundfx/libspeakerbundle.so"
#endif

typedef void (*set_mode_t)(int);
typedef void (*set_speaker_on_t)(bool);
typedef void (*set_earpiece_on_t)(bool);
typedef void (*set_voice_vol_t)(int);

struct speaker_data {
    struct audio_device *adev;
    void *speaker_bundle;
    set_mode_t set_mode;
    set_speaker_on_t set_speaker_on;
    set_earpiece_on_t set_earpiece_on;
    set_voice_vol_t set_voice_vol;
};

static struct speaker_data* open_speaker_bundle()
{
    struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));

    sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
    if (sd->speaker_bundle == NULL) {
        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
        goto error;
    } else {
        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);

        sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
                                             "set_mode");
        if (sd->set_mode == NULL) {
            ALOGE("%s: dlsym error %s for set_mode", __func__,
                  dlerror());
            goto error;
        }
        sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
                                             "set_speaker_on");
        if (sd->set_speaker_on == NULL) {
            ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
                  dlerror());
            goto error;
        }
        sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
                                             "set_earpiece_on");
        if (sd->set_earpiece_on == NULL) {
            ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
                  dlerror());
            goto error;
        }
        sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
                                             "set_voice_volume");
        if (sd->set_voice_vol == NULL) {
            ALOGE("%s: dlsym error %s for set_voice_volume",
                  __func__, dlerror());
            goto error;
        }
    }
    return sd;

error:
    free(sd);
    return 0;
}

static void close_speaker_bundle(struct speaker_data *sd)
{
    if (sd != NULL) {
        dlclose(sd->speaker_bundle);
        free(sd);
        sd = NULL;
    }
}

void *audio_extn_extspk_init(struct audio_device *adev)
{
    struct speaker_data *data = open_speaker_bundle();

    if (data)
        data->adev = adev;

    return data;
}

void audio_extn_extspk_deinit(void *extn)
{
    struct speaker_data *data = (struct speaker_data*)extn;
    close_speaker_bundle(data);
}

void audio_extn_extspk_update(void* extn)
{
    struct speaker_data *data = (struct speaker_data*)extn;

    if (data) {
        bool speaker_on = false;
        bool earpiece_on = false;
        struct listnode *node;
        struct audio_usecase *usecase;
        list_for_each(node, &data->adev->usecase_list) {
            usecase = node_to_item(node, struct audio_usecase, list);
            if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
                if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                    earpiece_on = true;
                }
            }
            if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
                if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                    speaker_on = true;
                }
            }
        }
        data->set_earpiece_on(earpiece_on);
        data->set_speaker_on(speaker_on);
    }
}

void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
{
    struct speaker_data *data = (struct speaker_data*)extn;

    if (data)
        data->set_mode(mode);
}
+13 −0
Original line number Diff line number Diff line
@@ -1005,6 +1005,8 @@ static int stop_output_stream(struct stream_out *out)
    list_remove(&uc_info->list);
    free(uc_info);

    audio_extn_extspk_update(adev->extspk);

    /* Must be called after removing the usecase from list */
    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
        check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
@@ -1045,6 +1047,8 @@ int start_output_stream(struct stream_out *out)

    select_devices(adev, out->usecase);

    audio_extn_extspk_update(adev->extspk);

    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 (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -1353,6 +1357,9 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)

        pthread_mutex_unlock(&adev->lock);
        pthread_mutex_unlock(&out->lock);

        /*handles device and call state changes*/
        audio_extn_extspk_update(adev->extspk);
    }

    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -2280,6 +2287,9 @@ static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
        adev->mode = mode;
    }
    pthread_mutex_unlock(&adev->lock);

    audio_extn_extspk_set_mode(adev->extspk, mode);

    return 0;
}

@@ -2566,6 +2576,7 @@ static int adev_close(hw_device_t *device)
    audio_route_free(adev->audio_route);
    free(adev->snd_dev_ref_cnt);
    platform_deinit(adev->platform);
    audio_extn_extspk_deinit(adev->extspk);
    for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
        pcm_params_free(adev->use_case_table[i]);
    }
@@ -2649,6 +2660,8 @@ static int adev_open(const hw_module_t *module, const char *name,
        return -EINVAL;
    }

    adev->extspk = audio_extn_extspk_init(adev);

    if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
        adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
        if (adev->visualizer_lib == NULL) {
+1 −0
Original line number Diff line number Diff line
@@ -214,6 +214,7 @@ struct audio_device {

    int snd_card;
    void *platform;
    void *extspk;

    void *visualizer_lib;
    int (*visualizer_start_output)(audio_io_handle_t, int);