libaaudio: remove LEGACY sharing mode
It was a poor API. Choosing the AudioTrack path is not a sharing mode.
Instead we decide internally, which path to choose based on sharing
mode and availability.
Test: CTS nativemedia/aaudio/test_aaudio.cpp
Change-Id: I8b6246b95cea807dcd0fc82e08a16f68f17b47f3
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 090f371..a16dfdc 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -32,15 +32,9 @@
case AAUDIO_SHARING_MODE_EXCLUSIVE:
modeText = "EXCLUSIVE";
break;
- case AAUDIO_SHARING_MODE_LEGACY:
- modeText = "LEGACY";
- break;
case AAUDIO_SHARING_MODE_SHARED:
modeText = "SHARED";
break;
- case AAUDIO_SHARING_MODE_PUBLIC_MIX:
- modeText = "PUBLIC_MIX";
- break;
default:
break;
}
@@ -61,8 +55,7 @@
aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_PCM16;
const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
- //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_LEGACY;
- aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_LEGACY;
+ aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
AAudioStreamBuilder aaudioBuilder = AAUDIO_STREAM_BUILDER_NONE;
AAudioStream aaudioStream = AAUDIO_STREAM_NONE;
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_threaded.cpp b/media/libaaudio/examples/write_sine/src/write_sine_threaded.cpp
index 4ea2807..7cb14f9 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_threaded.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_threaded.cpp
@@ -29,7 +29,7 @@
#define NUM_SECONDS 10
#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
-//#define SHARING_MODE AAUDIO_SHARING_MODE_LEGACY
+//#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
// Prototype for a callback.
typedef int audio_callback_proc_t(float *outputBuffer,
diff --git a/media/libaaudio/include/aaudio/AAudioDefinitions.h b/media/libaaudio/include/aaudio/AAudioDefinitions.h
index 979b8c9..5b72b94 100644
--- a/media/libaaudio/include/aaudio/AAudioDefinitions.h
+++ b/media/libaaudio/include/aaudio/AAudioDefinitions.h
@@ -124,14 +124,8 @@
AAUDIO_STREAM_STATE_CLOSED,
} aaudio_stream_state_t;
-// TODO review API
typedef enum {
/**
- * This will use an AudioTrack object for playing audio
- * and an AudioRecord for recording data.
- */
- AAUDIO_SHARING_MODE_LEGACY,
- /**
* This will be the only stream using a particular source or sink.
* This mode will provide the lowest possible latency.
* You should close EXCLUSIVE streams immediately when you are not using them.
@@ -142,12 +136,7 @@
* This will have higher latency than the EXCLUSIVE mode.
*/
AAUDIO_SHARING_MODE_SHARED,
- /**
- * Multiple applications will do their own mixing into a memory mapped buffer.
- * It may be possible for malicious applications to read the data produced by
- * other apps. So do not use this for private data such as telephony or messaging.
- */
- AAUDIO_SHARING_MODE_PUBLIC_MIX,
+
AAUDIO_SHARING_MODE_COUNT // This should always be last.
} aaudio_sharing_mode_t;
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 8e4aa05..acfed97 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -257,7 +257,7 @@
aaudio_sample_rate_t mSampleRate = AAUDIO_UNSPECIFIED;
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
aaudio_device_id_t mDeviceId = AAUDIO_UNSPECIFIED;
- aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_LEGACY;
+ aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index decd53c..5a54e62 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -42,13 +42,12 @@
}
aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
- // TODO Is there a better place to put the code that decides which class to use?
AudioStream* audioStream = nullptr;
const aaudio_sharing_mode_t sharingMode = getSharingMode();
switch (getDirection()) {
case AAUDIO_DIRECTION_INPUT:
switch (sharingMode) {
- case AAUDIO_SHARING_MODE_LEGACY:
+ case AAUDIO_SHARING_MODE_SHARED:
audioStream = new(std::nothrow) AudioStreamRecord();
break;
default:
@@ -59,7 +58,7 @@
break;
case AAUDIO_DIRECTION_OUTPUT:
switch (sharingMode) {
- case AAUDIO_SHARING_MODE_LEGACY:
+ case AAUDIO_SHARING_MODE_SHARED:
audioStream = new(std::nothrow) AudioStreamTrack();
break;
case AAUDIO_SHARING_MODE_EXCLUSIVE:
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index e72633d..f366688 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -107,7 +107,7 @@
int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
aaudio_sample_rate_t mSampleRate = AAUDIO_UNSPECIFIED;
aaudio_device_id_t mDeviceId = AAUDIO_DEVICE_UNSPECIFIED;
- aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_LEGACY;
+ aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
aaudio_size_frames_t mBufferCapacity = AAUDIO_UNSPECIFIED;
diff --git a/media/libaaudio/tests/Android.mk b/media/libaaudio/tests/Android.mk
index 24dad4a..7899cf5 100644
--- a/media/libaaudio/tests/Android.mk
+++ b/media/libaaudio/tests/Android.mk
@@ -6,19 +6,6 @@
frameworks/av/media/libaaudio/include \
frameworks/av/media/libaaudio/src/core \
frameworks/av/media/libaaudio/src/utility
-LOCAL_SRC_FILES := test_aaudio_api.cpp
-LOCAL_SHARED_LIBRARIES := libaudioclient libaudioutils libbinder \
- libcutils liblog libmedia libutils
-LOCAL_STATIC_LIBRARIES := libaaudio
-LOCAL_MODULE := test_aaudio_api
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include \
- frameworks/av/media/libaaudio/src/core \
- frameworks/av/media/libaaudio/src/utility
LOCAL_SRC_FILES:= test_handle_tracker.cpp
LOCAL_SHARED_LIBRARIES := libaudioclient libaudioutils libbinder \
libcutils liblog libmedia libutils
diff --git a/media/libaaudio/tests/test_aaudio_api.cpp b/media/libaaudio/tests/test_aaudio_api.cpp
deleted file mode 100644
index 7db3688..0000000
--- a/media/libaaudio/tests/test_aaudio_api.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// Unit tests for AAudio 'C' API.
-
-#include <stdlib.h>
-#include <math.h>
-
-#include <gtest/gtest.h>
-
-#include <aaudio/AAudioDefinitions.h>
-#include <aaudio/AAudio.h>
-#include "AAudioUtilities.h"
-
-#define DEFAULT_STATE_TIMEOUT (500 * AAUDIO_NANOS_PER_MILLISECOND)
-
-// Test AAudioStreamBuilder
-TEST(test_aaudio_api, aaudio_stream_builder) {
- const aaudio_sample_rate_t requestedSampleRate1 = 48000;
- const aaudio_sample_rate_t requestedSampleRate2 = 44100;
- const int32_t requestedSamplesPerFrame = 2;
- const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM16;
-
- aaudio_sample_rate_t sampleRate = 0;
- int32_t samplesPerFrame = 0;
- aaudio_audio_format_t actualDataFormat;
- AAudioStreamBuilder aaudioBuilder1;
- AAudioStreamBuilder aaudioBuilder2;
-
- aaudio_result_t result = AAUDIO_OK;
-
- // Use an AAudioStreamBuilder to define the stream.
- result = AAudio_createStreamBuilder(&aaudioBuilder1);
- ASSERT_EQ(AAUDIO_OK, result);
-
- // Request stream properties.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSampleRate(aaudioBuilder1, requestedSampleRate1));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSamplesPerFrame(aaudioBuilder1, requestedSamplesPerFrame));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setFormat(aaudioBuilder1, requestedDataFormat));
-
- // Check to make sure builder saved the properties.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getSampleRate(aaudioBuilder1, &sampleRate));
- EXPECT_EQ(requestedSampleRate1, sampleRate);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getSamplesPerFrame(aaudioBuilder1, &samplesPerFrame));
- EXPECT_EQ(requestedSamplesPerFrame, samplesPerFrame);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getFormat(aaudioBuilder1, &actualDataFormat));
- EXPECT_EQ(requestedDataFormat, actualDataFormat);
-
- result = AAudioStreamBuilder_getSampleRate(0x0BADCAFE, &sampleRate); // ridiculous token
- EXPECT_EQ(AAUDIO_ERROR_INVALID_HANDLE, result);
-
- // Create a second builder and make sure they do not collide.
- ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder2));
- ASSERT_NE(aaudioBuilder1, aaudioBuilder2);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSampleRate(aaudioBuilder2, requestedSampleRate2));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getSampleRate(aaudioBuilder1, &sampleRate));
- EXPECT_EQ(requestedSampleRate1, sampleRate);
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getSampleRate(aaudioBuilder2, &sampleRate));
- EXPECT_EQ(requestedSampleRate2, sampleRate);
-
- // Delete the builder.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder1));
-
- // Now it should no longer be valid.
- // Note that test assumes we are using the HandleTracker. If we use plain pointers
- // then it will be difficult to detect this kind of error.
- result = AAudioStreamBuilder_getSampleRate(aaudioBuilder1, &sampleRate); // stale token
- EXPECT_EQ(AAUDIO_ERROR_INVALID_HANDLE, result);
-
- // Second builder should still be valid.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_getSampleRate(aaudioBuilder2, &sampleRate));
- EXPECT_EQ(requestedSampleRate2, sampleRate);
-
- // Delete the second builder.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder2));
-
- // Now it should no longer be valid. Assumes HandlerTracker used.
- EXPECT_EQ(AAUDIO_ERROR_INVALID_HANDLE, AAudioStreamBuilder_getSampleRate(aaudioBuilder2, &sampleRate));
-}
-
-// Test creating a default stream with everything unspecified.
-TEST(test_aaudio_api, aaudio_stream_unspecified) {
- AAudioStreamBuilder aaudioBuilder;
- AAudioStream aaudioStream;
- aaudio_result_t result = AAUDIO_OK;
-
- // Use an AAudioStreamBuilder to define the stream.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
- ASSERT_EQ(AAUDIO_OK, result);
-
- // Create an AAudioStream using the Builder.
- ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
-
- // Cleanup
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
- EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-}
-
-// Test Writing to an AAudioStream
-void runtest_aaudio_stream(aaudio_sharing_mode_t requestedSharingMode) {
- const aaudio_sample_rate_t requestedSampleRate = 48000;
- const aaudio_sample_rate_t requestedSamplesPerFrame = 2;
- const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM16;
-
- aaudio_sample_rate_t actualSampleRate = -1;
- int32_t actualSamplesPerFrame = -1;
- aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_INVALID;
- aaudio_sharing_mode_t actualSharingMode;
- aaudio_size_frames_t framesPerBurst = -1;
- int writeLoops = 0;
-
- aaudio_size_frames_t framesWritten = 0;
- aaudio_size_frames_t framesPrimed = 0;
- aaudio_position_frames_t framesTotal = 0;
- aaudio_position_frames_t aaudioFramesRead = 0;
- aaudio_position_frames_t aaudioFramesRead1 = 0;
- aaudio_position_frames_t aaudioFramesRead2 = 0;
- aaudio_position_frames_t aaudioFramesWritten = 0;
-
- aaudio_nanoseconds_t timeoutNanos;
-
- aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
- AAudioStreamBuilder aaudioBuilder;
- AAudioStream aaudioStream;
-
- aaudio_result_t result = AAUDIO_OK;
-
- // Use an AAudioStreamBuilder to define the stream.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
- ASSERT_EQ(AAUDIO_OK, result);
-
- // Request stream properties.
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSampleRate(aaudioBuilder, requestedSampleRate));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSamplesPerFrame(aaudioBuilder, requestedSamplesPerFrame));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setFormat(aaudioBuilder, requestedDataFormat));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_setSharingMode(aaudioBuilder, requestedSharingMode));
-
- // Create an AAudioStream using the Builder.
- ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getState(aaudioStream, &state));
- EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
-
- // Check to see what kind of stream we actually got.
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getSampleRate(aaudioStream, &actualSampleRate));
- ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000); // TODO what is range?
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getSamplesPerFrame(aaudioStream, &actualSamplesPerFrame));
- ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getSharingMode(aaudioStream, &actualSharingMode));
- ASSERT_TRUE(actualSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
- || actualSharingMode == AAUDIO_SHARING_MODE_LEGACY);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFormat(aaudioStream, &actualDataFormat));
- EXPECT_NE(AAUDIO_FORMAT_INVALID, actualDataFormat);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesPerBurst(aaudioStream, &framesPerBurst));
- ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
-
- // Allocate a buffer for the audio data.
- // TODO handle possibility of other data formats
- ASSERT_TRUE(actualDataFormat == AAUDIO_FORMAT_PCM16);
- size_t dataSizeSamples = framesPerBurst * actualSamplesPerFrame;
- int16_t *data = new int16_t[dataSizeSamples];
- ASSERT_TRUE(nullptr != data);
- memset(data, 0, sizeof(int16_t) * dataSizeSamples);
-
- // Prime the buffer.
- timeoutNanos = 0;
- do {
- framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
- // There should be some room for priming the buffer.
- framesTotal += framesWritten;
- ASSERT_GE(framesWritten, 0);
- ASSERT_LE(framesWritten, framesPerBurst);
- } while (framesWritten > 0);
- ASSERT_TRUE(framesTotal > 0);
-
- // Start/write/pause more than once to see if it fails after the first time.
- // Write some data and measure the rate to see if the timing is OK.
- for (int numLoops = 0; numLoops < 2; numLoops++) {
- // Start and wait for server to respond.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
- ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
- AAUDIO_STREAM_STATE_STARTING,
- &state,
- DEFAULT_STATE_TIMEOUT));
- EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
-
- // Write some data while we are running. Read counter should be advancing.
- writeLoops = 1 * actualSampleRate / framesPerBurst; // 1 second
- ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
- timeoutNanos = 10 * AAUDIO_NANOS_PER_SECOND * framesPerBurst / actualSampleRate; // bursts
- framesWritten = 1;
- ASSERT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead));
- aaudioFramesRead1 = aaudioFramesRead;
- aaudio_nanoseconds_t beginTime = AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC);
- do {
- framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
- ASSERT_GE(framesWritten, 0);
- ASSERT_LE(framesWritten, framesPerBurst);
-
- framesTotal += framesWritten;
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesWritten(aaudioStream, &aaudioFramesWritten));
- EXPECT_EQ(framesTotal, aaudioFramesWritten);
-
- // Try to get a more accurate measure of the sample rate.
- if (beginTime == 0) {
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead));
- if (aaudioFramesRead > aaudioFramesRead1) { // is read pointer advancing
- beginTime = AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC);
- aaudioFramesRead1 = aaudioFramesRead;
- }
- }
- } while (framesWritten > 0 && writeLoops-- > 0);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead2));
- aaudio_nanoseconds_t endTime = AAudio_getNanoseconds(AAUDIO_CLOCK_MONOTONIC);
- ASSERT_GT(aaudioFramesRead2, 0);
- ASSERT_GT(aaudioFramesRead2, aaudioFramesRead1);
- ASSERT_LE(aaudioFramesRead2, aaudioFramesWritten);
-
- // TODO why is legacy so inaccurate?
- const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
- if (requestedSharingMode != AAUDIO_SHARING_MODE_LEGACY) {
- // Calculate approximate sample rate and compare with stream rate.
- double seconds = (endTime - beginTime) / (double) AAUDIO_NANOS_PER_SECOND;
- double measuredRate = (aaudioFramesRead2 - aaudioFramesRead1) / seconds;
- ASSERT_NEAR(actualSampleRate, measuredRate, rateTolerance);
- }
-
- // Request async pause and wait for server to say that it has completed the pause.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
- EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
- AAUDIO_STREAM_STATE_PAUSING,
- &state,
- DEFAULT_STATE_TIMEOUT));
- EXPECT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
- }
-
- // Make sure the read counter is not advancing when we are paused.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead));
- ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
-
- // Use this to sleep by waiting for something that won't happen.
- AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state, timeoutNanos);
- ASSERT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead2));
- EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
-
- // ------------------- TEST FLUSH -----------------
- // Prime the buffer.
- timeoutNanos = 0;
- writeLoops = 100;
- do {
- framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
- framesTotal += framesWritten;
- } while (framesWritten > 0 && writeLoops-- > 0);
- EXPECT_EQ(0, framesWritten);
-
- // Flush and wait for server to respond.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_requestFlush(aaudioStream));
- EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
- AAUDIO_STREAM_STATE_FLUSHING,
- &state,
- DEFAULT_STATE_TIMEOUT));
- EXPECT_EQ(AAUDIO_STREAM_STATE_FLUSHED, state);
-
- // After a flush, the read counter should be caught up with the write counter.
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesWritten(aaudioStream, &aaudioFramesWritten));
- EXPECT_EQ(framesTotal, aaudioFramesWritten);
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getFramesRead(aaudioStream, &aaudioFramesRead));
- EXPECT_EQ(aaudioFramesRead, aaudioFramesWritten);
-
- // The buffer should be empty after a flush so we should be able to write.
- framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
- // There should be some room for priming the buffer.
- ASSERT_TRUE(framesWritten > 0 && framesWritten <= framesPerBurst);
-
- EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-}
-
-// Test Writing to an AAudioStream using LEGACY sharing mode.
-TEST(test_aaudio_api, aaudio_stream_legacy) {
- runtest_aaudio_stream(AAUDIO_SHARING_MODE_LEGACY);
-}
-
-// Test Writing to an AAudioStream using EXCLUSIVE sharing mode.
-TEST(test_aaudio_api, aaudio_stream_exclusive) {
- runtest_aaudio_stream(AAUDIO_SHARING_MODE_EXCLUSIVE);
-}
-
-#define AAUDIO_THREAD_ANSWER 1826375
-#define AAUDIO_THREAD_DURATION_MSEC 500
-
-static void *TestAAudioStreamThreadProc(void *arg) {
- AAudioStream aaudioStream = (AAudioStream) reinterpret_cast<size_t>(arg);
- aaudio_stream_state_t state;
-
- // Use this to sleep by waiting for something that won't happen.
- EXPECT_EQ(AAUDIO_OK, AAudioStream_getState(aaudioStream, &state));
- AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state,
- AAUDIO_THREAD_DURATION_MSEC * AAUDIO_NANOS_PER_MILLISECOND);
- return reinterpret_cast<void *>(AAUDIO_THREAD_ANSWER);
-}
-
-// Test creating a stream related thread.
-TEST(test_aaudio_api, aaudio_stream_thread_basic) {
- AAudioStreamBuilder aaudioBuilder;
- AAudioStream aaudioStream;
- aaudio_result_t result = AAUDIO_OK;
- void *threadResult;
-
- // Use an AAudioStreamBuilder to define the stream.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
- ASSERT_EQ(AAUDIO_OK, result);
-
- // Create an AAudioStream using the Builder.
- ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
-
- // Start a thread.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_createThread(aaudioStream,
- 10 * AAUDIO_NANOS_PER_MILLISECOND,
- TestAAudioStreamThreadProc,
- reinterpret_cast<void *>(aaudioStream)));
- // Thread already started.
- ASSERT_NE(AAUDIO_OK, AAudioStream_createThread(aaudioStream, // should fail!
- 10 * AAUDIO_NANOS_PER_MILLISECOND,
- TestAAudioStreamThreadProc,
- reinterpret_cast<void *>(aaudioStream)));
-
- // Wait for the thread to finish.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_joinThread(aaudioStream,
- &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * AAUDIO_NANOS_PER_MILLISECOND));
- // The thread returns a special answer.
- ASSERT_EQ(AAUDIO_THREAD_ANSWER, (int)reinterpret_cast<size_t>(threadResult));
-
- // Thread should already be joined.
- ASSERT_NE(AAUDIO_OK, AAudioStream_joinThread(aaudioStream, // should fail!
- &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * AAUDIO_NANOS_PER_MILLISECOND));
-
- // Cleanup
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
- EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-}