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

Commit 8b4e05ec authored by Phil Burk's avatar Phil Burk
Browse files

aaudio: add AAudioStream_release()

Split close into close and release phases.
Release() will release hardware and service resources.
Close() will delete the stream object.
This allows us to defer the deletion and avoid race conditions.

The CLOSING state is used to indicate that a stream has been released.

Added some test cases to test_various.cpp.
A lone call to close() will automatically call release() so we should
have good code coverage for testing.

Bug: 136288001
Test: adb shell test_various
Test: atest CtsNativeMediaAAudioTestCases
Change-Id: Ia648838f30c521ba101f55259dbcd4594c1263cd
parent 0bc6f60e
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -1021,10 +1021,26 @@ AAUDIO_API aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* buil
// Stream Control
// ============================================================

#if __ANDROID_API__ >= 30
/**
 * Free the resources associated with a stream created by AAudioStreamBuilder_openStream()
 * Free the audio resources associated with a stream created by
 * AAudioStreamBuilder_openStream().
 * AAudioStream_close() should be called at some point after calling
 * this function.
 *
 * Available since API level 26.
 * After this call, the stream will be in {@link #AAUDIO_STREAM_STATE_CLOSING}
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return {@link #AAUDIO_OK} or a negative error.
 */
AAUDIO_API aaudio_result_t  AAudioStream_release(AAudioStream* stream) __INTRODUCED_IN(30);
#endif // __ANDROID_API__

/**
 * Delete the internal data structures associated with the stream created
 * by AAudioStreamBuilder_openStream().
 *
 * If AAudioStream_release() has not been called then it will be called automatically.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return {@link #AAUDIO_OK} or a negative error.
+4 −7
Original line number Diff line number Diff line
@@ -258,18 +258,17 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
    return result;

error:
    close();
    releaseCloseFinal();
    return result;
}

// This must be called under mStreamLock.
aaudio_result_t AudioStreamInternal::close() {
aaudio_result_t AudioStreamInternal::release_l() {
    aaudio_result_t result = AAUDIO_OK;
    ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
    if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
        // Don't close a stream while it is running.
        aaudio_stream_state_t currentState = getState();
        // Don't close a stream while it is running. Stop it first.
        // Don't release a stream while it is running. Stop it first.
        // If DISCONNECTED then we should still try to stop in case the
        // error callback is still running.
        if (isActive() || currentState == AAUDIO_STREAM_STATE_DISCONNECTED) {
@@ -282,10 +281,8 @@ aaudio_result_t AudioStreamInternal::close() {
        mServiceInterface.closeStream(serviceStreamHandle);
        delete[] mCallbackBuffer;
        mCallbackBuffer = nullptr;

        setState(AAUDIO_STREAM_STATE_CLOSED);
        result = mEndPointParcelable.close();
        aaudio_result_t result2 = AudioStream::close();
        aaudio_result_t result2 = AudioStream::release_l();
        return (result != AAUDIO_OK) ? result : result2;
    } else {
        return AAUDIO_ERROR_INVALID_HANDLE;
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ public:

    aaudio_result_t open(const AudioStreamBuilder &builder) override;

    aaudio_result_t close() override;
    aaudio_result_t release_l() override;

    aaudio_result_t setBufferSize(int32_t requestedFrames) override;

+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder)
                             getDeviceChannelCount());

        if (result != AAUDIO_OK) {
            close();
            releaseCloseFinal();
        }
        // Sample rate is constrained to common values by now and should not overflow.
        int32_t numFrames = kRampMSec * getSampleRate() / AAUDIO_MILLIS_PER_SECOND;
+29 −9
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@

#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>

#include "AudioClock.h"
#include "AudioGlobal.h"
#include "AudioStreamBuilder.h"
@@ -231,21 +230,42 @@ AAUDIO_API aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* buil
    return AAUDIO_ERROR_NULL;
}

AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
{
AAUDIO_API aaudio_result_t  AAudioStream_release(AAudioStream* stream) {
    aaudio_result_t result = AAUDIO_ERROR_NULL;
    AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
    if (audioStream != nullptr) {
        aaudio_stream_id_t id = audioStream->getId();
        ALOGD("%s(s#%u) called ---------------", __func__, id);
        result = audioStream->safeClose();
        // Close will only fail if called illegally, for example, from a callback.
        result = audioStream->safeRelease();
        // safeRelease() will only fail if called illegally, for example, from a callback.
        // That would result in the release of an active stream, which would cause a crash.
        if (result != AAUDIO_OK) {
            ALOGW("%s(s#%u) failed. Release it from another thread.",
                  __func__, id);
        }
        ALOGD("%s(s#%u) returned %d %s ---------", __func__,
                id, result, AAudio_convertResultToText(result));
    }
    return result;
}

AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream) {
    aaudio_result_t result = AAUDIO_ERROR_NULL;
    AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
    if (audioStream != nullptr) {
        aaudio_stream_id_t id = audioStream->getId();
        ALOGD("%s(s#%u) called ---------------", __func__, id);
        result = audioStream->safeRelease();
        // safeRelease will only fail if called illegally, for example, from a callback.
        // That would result in deleting an active stream, which would cause a crash.
        if (result == AAUDIO_OK) {
        if (result != AAUDIO_OK) {
            ALOGW("%s(s#%u) failed. Close it from another thread.",
                  __func__, id);
        } else {
            audioStream->unregisterPlayerBase();
             // Mark CLOSED to keep destructors from asserting.
            audioStream->closeFinal();
            delete audioStream;
        } else {
            ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
        }
        ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
    }
Loading