aaudio test: improve test_timestamps.cpp
Test for timestamps returned when STOPPED.
Test for no valid timestamps.
Bug: 122043542
Test: adb shell test_timestamps
Change-Id: I3f9ea636c7a469ffd6aa721776127dfeac94bc1e
diff --git a/media/libaaudio/tests/test_timestamps.cpp b/media/libaaudio/tests/test_timestamps.cpp
index dfa7815..7b1dfd3 100644
--- a/media/libaaudio/tests/test_timestamps.cpp
+++ b/media/libaaudio/tests/test_timestamps.cpp
@@ -35,6 +35,7 @@
#define NUM_SECONDS 1
#define NUM_LOOPS 4
+#define MAX_TESTS 20
typedef struct TimestampInfo {
int64_t framesTotal;
@@ -53,6 +54,49 @@
bool forceUnderruns = false;
} TimestampCallbackData_t;
+struct TimeStampTestLog {
+ aaudio_policy_t isMmap;
+ aaudio_sharing_mode_t sharingMode;
+ aaudio_performance_mode_t performanceMode;
+ aaudio_direction_t direction;
+ aaudio_result_t result;
+};
+
+static int s_numTests = 0;
+// Use a plain old array because we reference this from the callback and do not want any
+// automatic memory allocation.
+static TimeStampTestLog s_testLogs[MAX_TESTS]{};
+
+static void logTestResult(bool isMmap,
+ aaudio_sharing_mode_t sharingMode,
+ aaudio_performance_mode_t performanceMode,
+ aaudio_direction_t direction,
+ aaudio_result_t result) {
+ if(s_numTests >= MAX_TESTS) {
+ printf("ERROR - MAX_TESTS too small = %d\n", MAX_TESTS);
+ return;
+ }
+ s_testLogs[s_numTests].isMmap = isMmap;
+ s_testLogs[s_numTests].sharingMode = sharingMode;
+ s_testLogs[s_numTests].performanceMode = performanceMode;
+ s_testLogs[s_numTests].direction = direction;
+ s_testLogs[s_numTests].result = result;
+ s_numTests++;
+}
+
+static void printTestResults() {
+ for (int i = 0; i < s_numTests; i++) {
+ TimeStampTestLog *log = &s_testLogs[i];
+ printf("%2d: mmap = %3s, sharing = %9s, perf = %11s, dir = %6s ---- %4s\n",
+ i,
+ log->isMmap ? "yes" : "no",
+ getSharingModeText(log->sharingMode),
+ getPerformanceModeText(log->performanceMode),
+ getDirectionText(log->direction),
+ log->result ? "FAIL" : "pass");
+ }
+}
+
// Callback function that fills the audio output buffer.
aaudio_data_callback_result_t timestampDataCallbackProc(
AAudioStream *stream,
@@ -115,6 +159,7 @@
int32_t originalBufferSize = 0;
int32_t requestedBufferSize = 0;
int32_t finalBufferSize = 0;
+ bool isMmap = false;
aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
aaudio_sharing_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
@@ -124,7 +169,8 @@
memset(&sTimestampData, 0, sizeof(sTimestampData));
- printf("------------ testTimeStamps(policy = %d, sharing = %s, perf = %s, dir = %s) -----------\n",
+ printf("\n=================================================================================\n");
+ printf("--------- testTimeStamps(policy = %d, sharing = %s, perf = %s, dir = %s) --------\n",
mmapPolicy,
getSharingModeText(sharingMode),
getPerformanceModeText(performanceMode),
@@ -177,8 +223,8 @@
printf(" chans = %3d, rate = %6d format = %d\n",
actualChannelCount, actualSampleRate, actualDataFormat);
- printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(aaudioStream)
- ? "yes" : "no");
+ isMmap = AAudioStream_isMMapUsed(aaudioStream);
+ printf(" Is MMAP used? %s\n", isMmap ? "yes" : "no");
// This is the number of frames that are read in one chunk by a DMA controller
// or a DSP or a mixer.
@@ -218,7 +264,7 @@
for (int second = 0; second < NUM_SECONDS; second++) {
// Give AAudio callback time to run in the background.
- sleep(1);
+ usleep(200 * 1000);
// Periodically print the progress so we know it hasn't died.
printf("framesWritten = %d, XRuns = %d\n",
@@ -234,18 +280,25 @@
}
printf("timestampCount = %d\n", sTimestampData.timestampCount);
- int printed = 0;
- for (int i = 0; i < sTimestampData.timestampCount; i++) {
+ int printedGood = 0;
+ int printedBad = 0;
+ for (int i = 1; i < sTimestampData.timestampCount; i++) {
TimestampInfo *timestamp = &sTimestampData.timestamps[i];
- bool posChanged = (timestamp->timestampPosition != (timestamp - 1)->timestampPosition);
- bool timeChanged = (timestamp->timestampNanos != (timestamp - 1)->timestampNanos);
- if ((printed < 20) && ((i < 10) || posChanged || timeChanged)) {
- printf(" %3d : frames %8lld, xferd %8lld", i,
- (long long) timestamp->framesTotal,
- (long long) timestamp->appPosition);
- if (timestamp->result != AAUDIO_OK) {
- printf(", result = %s\n", AAudio_convertResultToText(timestamp->result));
- } else {
+ if (timestamp->result != AAUDIO_OK) {
+ if (printedBad < 5) {
+ printf(" %3d : frames %8lld, xferd %8lld, result = %s\n",
+ i,
+ (long long) timestamp->framesTotal,
+ (long long) timestamp->appPosition,
+ AAudio_convertResultToText(timestamp->result));
+ printedBad++;
+ }
+ } else {
+ const bool posChanged = (timestamp->timestampPosition !=
+ (timestamp - 1)->timestampPosition);
+ const bool timeChanged = (timestamp->timestampNanos
+ != (timestamp - 1)->timestampNanos);
+ if ((printedGood < 20) && (posChanged || timeChanged)) {
bool negative = timestamp->timestampPosition < 0;
bool retro = (i > 0 && (timestamp->timestampPosition <
(timestamp - 1)->timestampPosition));
@@ -253,17 +306,39 @@
: (retro ? " <= RETROGRADE!" : "");
double latency = calculateLatencyMillis(timestamp->timestampPosition,
- timestamp->timestampNanos,
- timestamp->appPosition,
- timestamp->appNanoseconds,
- actualSampleRate);
- printf(", STAMP: pos = %8lld, nanos = %8lld, lat = %7.1f msec %s\n",
+ timestamp->timestampNanos,
+ timestamp->appPosition,
+ timestamp->appNanoseconds,
+ actualSampleRate);
+ printf(" %3d : frames %8lld, xferd %8lld",
+ i,
+ (long long) timestamp->framesTotal,
+ (long long) timestamp->appPosition);
+ printf(" STAMP: pos = %8lld, nanos = %8lld, lat = %7.1f msec %s\n",
(long long) timestamp->timestampPosition,
(long long) timestamp->timestampNanos,
latency,
message);
+ printedGood++;
}
- printed++;
+ }
+ }
+
+ if (printedGood == 0) {
+ printf("ERROR - AAudioStream_getTimestamp() never gave us a valid timestamp\n");
+ result = AAUDIO_ERROR_INTERNAL;
+ } else {
+ // Make sure we do not get timestamps when stopped.
+ int64_t position;
+ int64_t time;
+ aaudio_result_t tempResult = AAudioStream_getTimestamp(aaudioStream,
+ CLOCK_MONOTONIC,
+ &position, &time);
+ if (tempResult != AAUDIO_ERROR_INVALID_STATE) {
+ printf("ERROR - AAudioStream_getTimestamp() should return"
+ " INVALID_STATE when stopped! %s\n",
+ AAudio_convertResultToText(tempResult));
+ result = AAUDIO_ERROR_INTERNAL;
}
}
@@ -273,12 +348,14 @@
}
finish:
+
+ logTestResult(isMmap, sharingMode, performanceMode, direction, result);
+
if (aaudioStream != nullptr) {
AAudioStream_close(aaudioStream);
}
AAudioStreamBuilder_delete(aaudioBuilder);
printf("result = %d = %s\n", result, AAudio_convertResultToText(result));
-
return result;
}
@@ -292,7 +369,7 @@
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("Test Timestamps V0.1.3\n");
+ printf("Test Timestamps V0.1.4\n");
// Legacy
aaudio_policy_t policy = AAUDIO_POLICY_NEVER;
@@ -332,5 +409,7 @@
AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
AAUDIO_DIRECTION_OUTPUT);
+ printTestResults();
+
return (result == AAUDIO_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}