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

Commit a52b4571 authored by Phil Burk's avatar Phil Burk Committed by Android (Google) Code Review
Browse files

Merge "aaudio: test matrix of state transitions"

parents 5cc83c3b 4fa3b943
Loading
Loading
Loading
Loading
+340 −39
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#include <gtest/gtest.h>
#include <unistd.h>


// Callback function that does nothing.
aaudio_data_callback_result_t NoopDataCallbackProc(
        AAudioStream *stream,
@@ -45,8 +44,15 @@ aaudio_data_callback_result_t NoopDataCallbackProc(

constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;

//int foo() { // To fix Android Studio formatting when editing.
TEST(test_various, aaudio_stop_when_open) {
enum FunctionToCall {
    CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
};

void checkStateTransition(aaudio_performance_mode_t perfMode,
                          aaudio_stream_state_t originalState,
                          FunctionToCall functionToCall,
                          aaudio_result_t expectedResult,
                          aaudio_stream_state_t expectedState) {
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    AAudioStream *aaudioStream = nullptr;

@@ -55,63 +61,359 @@ TEST(test_various, aaudio_stop_when_open) {

    // Request stream properties.
    AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);

    // Create an AAudioStream using the Builder.
    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));

    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));

    // Verify Open State
    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                         AAUDIO_STREAM_STATE_UNKNOWN, &state,
                                                         1000 * NANOS_PER_MILLISECOND));
    EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);

    EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
    // Put stream into desired state.
    aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED;
    if (originalState != AAUDIO_STREAM_STATE_OPEN) {

        ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));

        if (originalState != AAUDIO_STREAM_STATE_STARTING) {

            ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                                 AAUDIO_STREAM_STATE_STARTING,
                                                                 &state,
                                                                 1000 * NANOS_PER_MILLISECOND));
            ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, state);

            if (originalState == AAUDIO_STREAM_STATE_STOPPING) {
                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
            } else if (originalState == AAUDIO_STREAM_STATE_STOPPED) {
                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
                inputState = AAUDIO_STREAM_STATE_STOPPING;
            } else if (originalState == AAUDIO_STREAM_STATE_PAUSING) {
                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
            } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
                inputState = AAUDIO_STREAM_STATE_PAUSING;
            }
        }
    }

    // Wait until past transitional state.
    if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
        ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                             inputState,
                                                             &state,
                                                             1000 * NANOS_PER_MILLISECOND));
        ASSERT_EQ(originalState, state);
    }

    aaudio_stream_state_t transitionalState = originalState;
    switch(functionToCall) {
        case FunctionToCall::CALL_START:
            EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
            transitionalState = AAUDIO_STREAM_STATE_STARTING;
            break;
        case FunctionToCall::CALL_STOP:
            EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
            transitionalState = AAUDIO_STREAM_STATE_STOPPING;
            break;
        case FunctionToCall::CALL_PAUSE:
            EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
            transitionalState = AAUDIO_STREAM_STATE_PAUSING;
            break;
        case FunctionToCall::CALL_FLUSH:
            EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
            transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
            break;
    }

    state = AAUDIO_STREAM_STATE_UNKNOWN;
    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                         AAUDIO_STREAM_STATE_UNKNOWN, &state, 0));
    EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
                                                         transitionalState,
                                                         &state,
                                                         1000 * NANOS_PER_MILLISECOND));
    // We should not change state when a function fails.
    if (expectedResult != AAUDIO_OK) {
        ASSERT_EQ(originalState, expectedState);
    }
    EXPECT_EQ(expectedState, state);
    if (state != expectedState) {
        printf("ERROR - expected %s, actual = %s\n",
                AAudio_convertStreamStateToText(expectedState),
                AAudio_convertStreamStateToText(state));
        fflush(stdout);
    }

    AAudioStream_close(aaudioStream);
    AAudioStreamBuilder_delete(aaudioBuilder);
}

//int boo() { // To fix Android Studio formatting when editing.
TEST(test_various, aaudio_flush_when_started) {
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    AAudioStream *aaudioStream = nullptr;
// TODO Use parameterized tests instead of these individual specific tests.

// Use an AAudioStreamBuilder to contain requested parameters.
    ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
// OPEN =================================================================
TEST(test_various, aaudio_state_lowlat_open_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_START,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STARTED);
}

// Request stream properties.
    AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
TEST(test_various, aaudio_state_none_open_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_START,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STARTED);
}

// Create an AAudioStream using the Builder.
    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
    EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
TEST(test_various, aaudio_state_lowlat_open_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                         AAUDIO_STREAM_STATE_STARTING, &state,
                                                         1000 * NANOS_PER_MILLISECOND));
    EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
TEST(test_various, aaudio_state_none_open_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestFlush(aaudioStream));
TEST(test_various, aaudio_state_lowlat_open_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

    state = AAUDIO_STREAM_STATE_UNKNOWN;
    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                         AAUDIO_STREAM_STATE_UNKNOWN, &state, 0));
    EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
TEST(test_various, aaudio_state_none_open_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

    AAudioStream_close(aaudioStream);
    AAudioStreamBuilder_delete(aaudioBuilder);
TEST(test_various, aaudio_state_lowlat_open_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_FLUSHED);
}

//int main() { // To fix Android Studio formatting when editing.
TEST(test_various, aaudio_state_none_open_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_OPEN,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_FLUSHED);
}


// STARTED =================================================================
TEST(test_various, aaudio_state_lowlat_started_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_START,
            AAUDIO_ERROR_INVALID_STATE,
            AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_none_started_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_START,
            AAUDIO_ERROR_INVALID_STATE,
            AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_lowlat_started_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_none_started_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_lowlat_started_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_none_started_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_lowlat_started_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_ERROR_INVALID_STATE,
            AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_none_started_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STARTED,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_ERROR_INVALID_STATE,
            AAUDIO_STREAM_STATE_STARTED);
}

// STOPPED =================================================================
TEST(test_various, aaudio_state_lowlat_stopped_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_START,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_none_stopped_start) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_START,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_lowlat_stopped_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_none_stopped_stop) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_STOP,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_lowlat_stopped_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_none_stopped_pause) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_PAUSE,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_lowlat_stopped_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_FLUSHED);
}

TEST(test_various, aaudio_state_none_stopped_flush) {
    checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
            AAUDIO_STREAM_STATE_STOPPED,
            FunctionToCall::CALL_FLUSH,
            AAUDIO_OK,
            AAUDIO_STREAM_STATE_FLUSHED);
}

// PAUSED =================================================================
TEST(test_various, aaudio_state_lowlat_paused_start) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_START,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_none_paused_start) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_START,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_STARTED);
}

TEST(test_various, aaudio_state_lowlat_paused_stop) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_STOP,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_none_paused_stop) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_STOP,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_STOPPED);
}

TEST(test_various, aaudio_state_lowlat_paused_pause) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_PAUSE,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_none_paused_pause) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_PAUSE,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_PAUSED);
}

TEST(test_various, aaudio_state_lowlat_paused_flush) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_FLUSH,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_FLUSHED);
}

TEST(test_various, aaudio_state_none_paused_flush) {
checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
        AAUDIO_STREAM_STATE_PAUSED,
        FunctionToCall::CALL_FLUSH,
        AAUDIO_OK,
        AAUDIO_STREAM_STATE_FLUSHED);
}

// ==========================================================================
TEST(test_various, aaudio_set_buffer_size) {

    int32_t bufferCapacity;
@@ -174,7 +476,6 @@ TEST(test_various, aaudio_set_buffer_size) {
    AAudioStreamBuilder_delete(aaudioBuilder);
}


// ************************************************************
// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.