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

Commit da572061 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: Update synchronization and error handling for audio patches"

parents 8bf3c313 bc774848
Loading
Loading
Loading
Loading
+74 −87
Original line number Diff line number Diff line
@@ -682,23 +682,20 @@ static inline void free_map(Hashmap *map)
    }
}

static inline void patch_map_remove(struct audio_device *adev,
static inline void patch_map_remove_l(struct audio_device *adev,
                                audio_patch_handle_t patch_handle)
{
    if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
        return;

    pthread_mutex_lock(&adev->lock);
    struct audio_patch_info *p_info =
        hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
    if (p_info) {
        ALOGV("%s: Remove patch %d", __func__, patch_handle);
        hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
        free(p_info->patch);
        pthread_mutex_destroy(&p_info->lock);
        free(p_info);
    }
    pthread_mutex_unlock(&adev->lock);
}

static inline int io_streams_map_insert(struct audio_device *adev,
@@ -715,14 +712,13 @@ static inline int io_streams_map_insert(struct audio_device *adev,
    }
    s_info->stream = stream;
    s_info->patch_handle = patch_handle;
    pthread_mutex_init(&s_info->lock, (const pthread_mutexattr_t *) NULL);

    pthread_mutex_lock(&adev->lock);
    struct audio_stream_info *stream_info =
            hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
    pthread_mutex_unlock(&adev->lock);
    if (stream_info != NULL)
        free(stream_info);
    pthread_mutex_unlock(&adev->lock);
    ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
    return 0;
}
@@ -733,24 +729,22 @@ static inline void io_streams_map_remove(struct audio_device *adev,
    pthread_mutex_lock(&adev->lock);
    struct audio_stream_info *s_info =
            hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
    pthread_mutex_unlock(&adev->lock);
    if (s_info == NULL)
        return;
        goto done;
    ALOGD("%s: Removed stream with handle %d", __func__, handle);
    patch_map_remove(adev, s_info->patch_handle);
    pthread_mutex_destroy(&s_info->lock);
    patch_map_remove_l(adev, s_info->patch_handle);
    free(s_info);
done:
    pthread_mutex_unlock(&adev->lock);
    return;
}

static struct audio_patch_info* fetch_patch_info(struct audio_device *adev,
static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
                                    audio_patch_handle_t handle)
{
    struct audio_patch_info *p_info = NULL;
    pthread_mutex_lock(&adev->lock);
    p_info = (struct audio_patch_info *)
                 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
    pthread_mutex_unlock(&adev->lock);
    return p_info;
}

@@ -9729,61 +9723,55 @@ int adev_create_audio_patch(struct audio_hw_device *dev,
            break;
        case AUDIO_PORT_TYPE_SESSION:
        case AUDIO_PORT_TYPE_NONE:
            break;
    }

    pthread_mutex_lock(&adev->lock);
    s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
    pthread_mutex_unlock(&adev->lock);
    if (s_info == NULL) {
        ALOGE("%s: Failed to obtain stream info", __func__);
            ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
            ret = -EINVAL;
            goto done;
    }
    ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);

    pthread_mutex_lock(&s_info->lock);
    pthread_mutex_lock(&adev->lock);

    // Generate patch info and update patch
    if (*handle == AUDIO_PATCH_HANDLE_NONE) {
        if (s_info->patch_handle != AUDIO_PATCH_HANDLE_NONE) {
            // Use patch handle cached in s_info to update patch
            *handle = s_info->patch_handle;
            p_info = fetch_patch_info(adev, *handle);
            if (p_info == NULL) {
                ALOGE("%s: Unable to fetch patch for stream patch handle %d",
                      __func__, *handle);
                pthread_mutex_unlock(&s_info->lock);
                ret = -EINVAL;
                goto done;
            }
        } else {
        *handle = generate_patch_handle();
            p_info = (struct audio_patch_info *) calloc(1, sizeof(struct audio_patch_info));
        p_info = (struct audio_patch_info *)
                      calloc(1, sizeof(struct audio_patch_info));
        if (p_info == NULL) {
            ALOGE("%s: Failed to allocate memory", __func__);
                pthread_mutex_unlock(&s_info->lock);
            pthread_mutex_unlock(&adev->lock);
            ret = -ENOMEM;
            goto done;
        }
        new_patch = true;
            pthread_mutex_init(&p_info->lock, (const pthread_mutexattr_t *) NULL);
            s_info->patch_handle = *handle;
        }
    } else {
        p_info = fetch_patch_info(adev, *handle);
        p_info = fetch_patch_info_l(adev, *handle);
        if (p_info == NULL) {
            ALOGE("%s: Unable to fetch patch for received patch handle %d",
                  __func__, *handle);
            pthread_mutex_unlock(&s_info->lock);
            pthread_mutex_unlock(&adev->lock);
            ret = -EINVAL;
            goto done;
        }
        s_info->patch_handle = *handle;
    }
    pthread_mutex_lock(&p_info->lock);
    update_patch(num_sources, sources, num_sinks, sinks,
             *handle, p_info, patch_type, new_patch);

    // Fetch stream info of associated mix for playback or capture patches
    if (p_info->patch_type == PATCH_PLAYBACK ||
            p_info->patch_type == PATCH_CAPTURE) {
        s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
        if (s_info == NULL) {
            ALOGE("%s: Failed to obtain stream info", __func__);
            if (new_patch)
                free(p_info);
            pthread_mutex_unlock(&adev->lock);
            ret = -EINVAL;
            goto done;
        }
        ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
        s_info->patch_handle = *handle;
        stream = s_info->stream;
    }
    pthread_mutex_unlock(&adev->lock);

    // Update routing for stream
    if (stream != NULL) {
@@ -9791,26 +9779,25 @@ int adev_create_audio_patch(struct audio_hw_device *dev,
            ret = route_output_stream((struct stream_out *) stream, &devices);
        else if (p_info->patch_type == PATCH_CAPTURE)
            ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
    }

        if (ret < 0) {
            pthread_mutex_lock(&adev->lock);
            s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
            if (new_patch)
                free(p_info);
            pthread_mutex_unlock(&adev->lock);
            ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
        pthread_mutex_unlock(&p_info->lock);
        pthread_mutex_unlock(&s_info->lock);
            goto done;
        }
    }

    // Add new patch to patch map
    if (!ret && new_patch) {
        pthread_mutex_lock(&adev->lock);
        hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
        pthread_mutex_unlock(&adev->lock);
        ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
        pthread_mutex_unlock(&adev->lock);
    }

    pthread_mutex_unlock(&p_info->lock);
    pthread_mutex_unlock(&s_info->lock);
done:
    audio_extn_hw_loopback_create_audio_patch(dev,
                                        num_sources,
@@ -9833,6 +9820,7 @@ int adev_release_audio_patch(struct audio_hw_device *dev,
    struct audio_device *adev = (struct audio_device *) dev;
    int ret = 0;
    audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
    struct audio_stream *stream = NULL;

    if (handle == AUDIO_PATCH_HANDLE_NONE) {
        ALOGE("%s: Invalid patch handle %d", __func__, handle);
@@ -9841,48 +9829,53 @@ int adev_release_audio_patch(struct audio_hw_device *dev,
    }

    ALOGD("%s: Remove patch with handle %d", __func__, handle);
    struct audio_patch_info *p_info = fetch_patch_info(adev, handle);
    pthread_mutex_lock(&adev->lock);
    struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
    if (p_info == NULL) {
        ALOGE("%s: Patch info not found with handle %d", __func__, handle);
        pthread_mutex_unlock(&adev->lock);
        ret = -EINVAL;
        goto done;
    }
    pthread_mutex_lock(&p_info->lock);
    struct audio_patch *patch = p_info->patch;
    if (patch == NULL) {
        ALOGE("%s: Patch not found for handle %d", __func__, handle);
        pthread_mutex_unlock(&adev->lock);
        ret = -EINVAL;
        pthread_mutex_unlock(&p_info->lock);
        goto done;
    }
    pthread_mutex_unlock(&p_info->lock);
    audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
    switch (patch->sources[0].type) {
        case AUDIO_PORT_TYPE_MIX:
            io_handle = patch->sources[0].ext.mix.handle;
            break;
        case AUDIO_PORT_TYPE_DEVICE:
            if (p_info->patch_type == PATCH_CAPTURE)
                io_handle = patch->sinks[0].ext.mix.handle;
            break;
        case AUDIO_PORT_TYPE_SESSION:
        case AUDIO_PORT_TYPE_NONE:
            break;
            pthread_mutex_unlock(&adev->lock);
            ret = -EINVAL;
            goto done;
    }

    // Remove patch and reset patch handle in stream info
    pthread_mutex_lock(&adev->lock);
    patch_map_remove_l(adev, handle);
    if (p_info->patch_type == PATCH_PLAYBACK ||
        p_info->patch_type == PATCH_CAPTURE) {
        struct audio_stream_info *s_info =
            hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
    pthread_mutex_unlock(&adev->lock);
        if (s_info == NULL) {
            ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
            pthread_mutex_unlock(&adev->lock);
            goto done;
        }
    pthread_mutex_lock(&s_info->lock);
        s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
    struct audio_stream *stream = s_info->stream;
        stream = s_info->stream;
    }
    pthread_mutex_unlock(&adev->lock);

    pthread_mutex_lock(&p_info->lock);
    if (stream != NULL) {
        struct listnode devices;
        list_init(&devices);
@@ -9895,11 +9888,6 @@ int adev_release_audio_patch(struct audio_hw_device *dev,
    if (ret < 0)
        ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);

    pthread_mutex_unlock(&p_info->lock);
    pthread_mutex_unlock(&s_info->lock);

    // Remove patch entry from map
    patch_map_remove(adev, handle);
done:
    audio_extn_hw_loopback_release_audio_patch(dev, handle);
    audio_extn_auto_hal_release_audio_patch(dev, handle);
@@ -10472,7 +10460,6 @@ static int adev_open(const hw_module_t *module, const char *name,
adev_open_err:
    free_map(adev->patch_map);
    free_map(adev->io_streams_map);
    if (adev->snd_dev_ref_cnt)
    free(adev->snd_dev_ref_cnt);
    pthread_mutex_destroy(&adev->lock);
    free(adev);
+0 −2
Original line number Diff line number Diff line
@@ -532,13 +532,11 @@ typedef enum {
struct audio_patch_info {
    struct audio_patch *patch;
    patch_type_t patch_type;
    pthread_mutex_t lock;
};

struct audio_stream_info {
    struct audio_stream *stream;
    audio_patch_handle_t patch_handle;
    pthread_mutex_t lock;
};

union stream_ptr {