1 /*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_NDEBUG 0
18 #define LOG_TAG "AAudioTest"
19
20 #include <atomic>
21 #include <tuple>
22
23 #include <aaudio/AAudio.h>
24 #include <android/log.h>
25 #include <gtest/gtest.h>
26
27 #include "test_aaudio.h"
28 #include "utils.h"
29
30 constexpr int kExtremelyHighCallbackPeriodMillis = 200;
31 constexpr int kExpectedCallbackCount = 5;
32 constexpr int kPollTimeMillis = 5;
33
measureLatency(AAudioStream * stream)34 static int32_t measureLatency(AAudioStream *stream) {
35 int64_t presentationTime = 0;
36 int64_t presentationPosition = 0;
37 int64_t now = getNanoseconds();
38 int32_t sampleRate = AAudioStream_getSampleRate(stream);
39 int64_t framesWritten = AAudioStream_getFramesWritten(stream);
40 aaudio_result_t result = AAudioStream_getTimestamp(stream,
41 CLOCK_MONOTONIC,
42 &presentationPosition,
43 &presentationTime);
44 if (result < 0) {
45 return result;
46 }
47 // Calculate when the last frame written would be played.
48 int64_t deltaFrames = framesWritten - presentationPosition;
49 if (deltaFrames < 0) {
50 __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Underrun detected: %lld frames",
51 (long long)(-deltaFrames));
52 return 0;
53 }
54 int64_t calculatedDeltaNanos = deltaFrames * NANOS_PER_SECOND / sampleRate;
55 int64_t calculatedTimeNanos = presentationTime + calculatedDeltaNanos;
56 int64_t latencyNanos = calculatedTimeNanos - now;
57 int32_t latencyMillis = (int32_t) ((latencyNanos + NANOS_PER_MILLISECOND - 1)
58 / NANOS_PER_MILLISECOND);
59 return latencyMillis;
60 }
61
62 using CbTestParams = std::tuple<aaudio_sharing_mode_t, int32_t,
63 aaudio_performance_mode_t, int32_t, aaudio_format_t, int32_t>;
64 enum {
65 PARAM_SHARING_MODE = 0,
66 PARAM_FRAMES_PER_CB,
67 PARAM_PERF_MODE,
68 PARAM_ALLOW_MMAP,
69 PARAM_AUDIO_FORMAT,
70 PARAM_SAMPLE_RATE
71 };
72
73 enum {
74 MMAP_NOT_ALLOWED,
75 MMAP_ALLOWED,
76 };
77
allowMMapToString(int allow)78 static const char* allowMMapToString(int allow) {
79 switch (allow) {
80 case MMAP_NOT_ALLOWED: return "NOTMMAP";
81 case MMAP_ALLOWED:
82 default:
83 return "MMAPOK";
84 }
85 }
86
audioFormatToString(aaudio_format_t format)87 static const char* audioFormatToString(aaudio_format_t format) {
88 switch (format) {
89 case AAUDIO_FORMAT_UNSPECIFIED: return "UNSP";
90 case AAUDIO_FORMAT_PCM_I16: return "I16";
91 case AAUDIO_FORMAT_PCM_FLOAT: return "FLT";
92 default:
93 return "BAD";
94 }
95 }
96
getTestName(const::testing::TestParamInfo<CbTestParams> & info)97 static std::string getTestName(const ::testing::TestParamInfo<CbTestParams>& info) {
98 return std::string()
99 + sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param))
100 + "__" + std::to_string(std::get<PARAM_FRAMES_PER_CB>(info.param))
101 + "__" + performanceModeToString(std::get<PARAM_PERF_MODE>(info.param))
102 + "__" + allowMMapToString(std::get<PARAM_ALLOW_MMAP>(info.param))
103 + "__" + audioFormatToString(std::get<PARAM_AUDIO_FORMAT>(info.param))
104 + "__" + std::to_string(std::get<PARAM_SAMPLE_RATE>(info.param))
105 ;
106 }
107
108 template<typename T>
109 class AAudioStreamCallbackTest : public AAudioCtsBase,
110 public ::testing::WithParamInterface<CbTestParams> {
111 protected:
112 struct AAudioCallbackTestData {
113 int32_t expectedFramesPerCallback;
114 int32_t actualFramesPerCallback;
115 int32_t minLatency;
116 int32_t maxLatency;
117 std::atomic<aaudio_result_t> callbackError;
118 std::atomic<int32_t> callbackCount;
119 std::atomic<bool> returnStop;
120
AAudioCallbackTestDataAAudioStreamCallbackTest::AAudioCallbackTestData121 AAudioCallbackTestData() {
122 reset(0);
123 }
resetAAudioStreamCallbackTest::AAudioCallbackTestData124 void reset(int32_t expectedFramesPerCb) {
125 expectedFramesPerCallback = expectedFramesPerCb;
126 actualFramesPerCallback = 0;
127 minLatency = INT32_MAX;
128 maxLatency = 0;
129 callbackError = AAUDIO_OK;
130 callbackCount = 0;
131 returnStop = false;
132 }
updateFrameCountAAudioStreamCallbackTest::AAudioCallbackTestData133 void updateFrameCount(int32_t numFrames) {
134 if (numFrames != expectedFramesPerCallback) {
135 // record unexpected framecounts
136 actualFramesPerCallback = numFrames;
137 } else if (actualFramesPerCallback == 0) {
138 // record at least one frame count
139 actualFramesPerCallback = numFrames;
140 }
141 }
updateLatencyAAudioStreamCallbackTest::AAudioCallbackTestData142 void updateLatency(int32_t latency) {
143 if (latency <= 0) return;
144 minLatency = std::min(minLatency, latency);
145 maxLatency = std::max(maxLatency, latency);
146 }
waitForNCallbacksAAudioStreamCallbackTest::AAudioCallbackTestData147 bool waitForNCallbacks(int32_t n) {
148 int32_t timeTakenMillis = 0;
149 // Expect each callback to take less than kExtremelyHighCallbackPeriodMillis
150 while (timeTakenMillis < kExtremelyHighCallbackPeriodMillis * n) {
151 if (callbackCount >= n) {
152 return true;
153 }
154 usleep(kPollTimeMillis * MICROS_PER_MILLISECOND);
155 timeTakenMillis += kPollTimeMillis;
156 }
157 return false;
158 }
159 };
160
createAndVerifyHonoringMMap()161 void createAndVerifyHonoringMMap() {
162 aaudio_policy_t originalPolicy = AAUDIO_POLICY_AUTO;
163
164 // Turn off MMap if requested.
165 bool allowMMap = std::get<PARAM_ALLOW_MMAP>(GetParam()) == MMAP_ALLOWED;
166 if (AAudioExtensions::getInstance().isMMapSupported()) {
167 originalPolicy = AAudioExtensions::getInstance().getMMapPolicy();
168 AAudioExtensions::getInstance().setMMapEnabled(allowMMap);
169 }
170
171 mHelper->createAndVerifyStream(&mSetupSuccessful);
172
173 // Restore policy for next test.
174 if (AAudioExtensions::getInstance().isMMapSupported()) {
175 AAudioExtensions::getInstance().setMMapPolicy(originalPolicy);
176 }
177 // Make sure we do not get MMAP when we disable it.
178 if (mSetupSuccessful && !allowMMap) {
179 ASSERT_FALSE(AAudioExtensions::getInstance().isMMapUsed(mHelper->stream()));
180 }
181 }
182
183 static void MyErrorCallbackProc(AAudioStream *stream, void *userData, aaudio_result_t error);
184
builder() const185 AAudioStreamBuilder* builder() const { return mHelper->builder(); }
stream() const186 AAudioStream* stream() const { return mHelper->stream(); }
actual() const187 const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
188
189 std::unique_ptr<T> mHelper;
190 bool mSetupSuccessful = false;
191 std::unique_ptr<AAudioCallbackTestData> mCbData;
192 };
193
194 template<typename T>
MyErrorCallbackProc(AAudioStream *,void * userData,aaudio_result_t error)195 void AAudioStreamCallbackTest<T>::MyErrorCallbackProc(
196 AAudioStream* /*stream*/, void *userData, aaudio_result_t error) {
197 AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
198 myData->callbackError = error;
199 }
200
201
202 class AAudioInputStreamCallbackTest : public AAudioStreamCallbackTest<InputStreamBuilderHelper> {
203 protected:
204 void SetUp() override;
205
206 static aaudio_data_callback_result_t MyDataCallbackProc(
207 AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
208 };
209
MyDataCallbackProc(AAudioStream *,void * userData,void *,int32_t numFrames)210 aaudio_data_callback_result_t AAudioInputStreamCallbackTest::MyDataCallbackProc(
211 AAudioStream* /*stream*/, void *userData, void* /*audioData*/, int32_t numFrames) {
212 AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
213 myData->updateFrameCount(numFrames);
214 // No latency measurement as there is no API for querying capture position.
215 myData->callbackCount++;
216 return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
217 }
218
SetUp()219 void AAudioInputStreamCallbackTest::SetUp() {
220 AAudioCtsBase::SetUp();
221
222 mSetupSuccessful = false;
223 if (!deviceSupportsFeature(FEATURE_RECORDING)) return;
224 mHelper.reset(new InputStreamBuilderHelper(
225 std::get<PARAM_SHARING_MODE>(GetParam()),
226 std::get<PARAM_PERF_MODE>(GetParam()),
227 std::get<PARAM_AUDIO_FORMAT>(GetParam()),
228 std::get<PARAM_SAMPLE_RATE>(GetParam()))
229 );
230 mHelper->initBuilder();
231
232 int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
233 mCbData.reset(new AAudioCallbackTestData());
234 AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
235 AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
236 if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
237 AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
238 }
239
240 createAndVerifyHonoringMMap();
241 }
242
243 // Test starting and stopping an INPUT AAudioStream that uses a Callback
TEST_P(AAudioInputStreamCallbackTest,testRecording)244 TEST_P(AAudioInputStreamCallbackTest, testRecording) {
245 if (!mSetupSuccessful) return;
246
247 const int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
248 const int32_t streamFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
249 if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
250 ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
251 }
252 const int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream());
253 const int32_t callbackCountsPerBurst = streamFramesPerDataCallback == AAUDIO_UNSPECIFIED ? 1
254 : (framesPerBurst + streamFramesPerDataCallback - 1) / streamFramesPerDataCallback;
255
256 // Try both methods of stopping a stream.
257 const int kNumMethods = 2;
258
259 constexpr int kMaxXRunCount = 0;
260
261 // Start/stop more than once to see if it fails after the first time.
262 // Also check to make sure we do not get callbacks after the stop.
263 for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
264 mCbData->reset(streamFramesPerDataCallback);
265
266 mHelper->startStream();
267 // See b/62090113. For legacy path, the device is only known after
268 // the stream has been started.
269 EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
270 EXPECT_TRUE(mCbData->waitForNCallbacks(kExpectedCallbackCount));
271
272 ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
273 ASSERT_GE(mCbData->callbackCount, kExpectedCallbackCount);
274
275 ASSERT_LE(AAudioStream_getXRunCount(stream()), kMaxXRunCount);
276
277 switch (loopIndex % kNumMethods) {
278 case 0:
279 mCbData->returnStop = true; // callback return
280 mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
281 break;
282 case 1:
283 mHelper->stopStream();
284 break;
285 }
286
287 int32_t oldCallbackCount = mCbData->callbackCount;
288 EXPECT_GE(oldCallbackCount, kExpectedCallbackCount);
289 usleep(kExtremelyHighCallbackPeriodMillis * MICROS_PER_MILLISECOND);
290 if ((AAudioExtensions::getInstance().isMMapUsed(mHelper->stream()))) {
291 EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
292 } else {
293 // Allow requesting at most one burst size data from callback after stopping
294 EXPECT_GE(mCbData->callbackCount, oldCallbackCount);
295 EXPECT_LE(mCbData->callbackCount, oldCallbackCount + callbackCountsPerBurst);
296 }
297
298 if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
299 ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
300 }
301
302 ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
303 }
304 }
305
306 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamCallbackTest,
307 ::testing::Values(
308 std::make_tuple(
309 AAUDIO_SHARING_MODE_SHARED,
310 AAUDIO_UNSPECIFIED,
311 AAUDIO_PERFORMANCE_MODE_NONE,
312 MMAP_ALLOWED,
313 AAUDIO_FORMAT_UNSPECIFIED,
314 48000),
315 // cb buffer size: arbitrary prime number < 96
316 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
317 AAUDIO_FORMAT_UNSPECIFIED, 48000),
318 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
319 AAUDIO_FORMAT_UNSPECIFIED, 48000),
320 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
321 AAUDIO_FORMAT_UNSPECIFIED, 48000),
322 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
323 AAUDIO_FORMAT_PCM_I16, 48000),
324 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
325 AAUDIO_FORMAT_PCM_FLOAT, 48000),
326 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
327 AAUDIO_FORMAT_UNSPECIFIED, 44100),
328 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
329 AAUDIO_FORMAT_UNSPECIFIED, 44100),
330 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
331 AAUDIO_FORMAT_UNSPECIFIED, 44100),
332 // cb buffer size: arbitrary prime number > 192
333 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
334 AAUDIO_FORMAT_UNSPECIFIED, 48000),
335 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
336 AAUDIO_FORMAT_UNSPECIFIED, 48000),
337 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
338 AAUDIO_FORMAT_UNSPECIFIED, 11025),
339 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
340 AAUDIO_FORMAT_UNSPECIFIED, 11025),
341 // Recording in POWER_SAVING mode isn't supported, b/62291775.
342 std::make_tuple(
343 AAUDIO_SHARING_MODE_SHARED,
344 AAUDIO_UNSPECIFIED,
345 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
346 MMAP_ALLOWED,
347 AAUDIO_FORMAT_UNSPECIFIED,
348 48000),
349 std::make_tuple(
350 AAUDIO_SHARING_MODE_EXCLUSIVE,
351 AAUDIO_UNSPECIFIED,
352 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
353 MMAP_ALLOWED,
354 AAUDIO_FORMAT_UNSPECIFIED,
355 48000),
356 std::make_tuple(
357 AAUDIO_SHARING_MODE_EXCLUSIVE,
358 AAUDIO_UNSPECIFIED,
359 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
360 MMAP_ALLOWED,
361 AAUDIO_FORMAT_UNSPECIFIED,
362 88200)),
363 &getTestName);
364
365
366 class AAudioOutputStreamCallbackTest : public AAudioStreamCallbackTest<OutputStreamBuilderHelper> {
367 protected:
368 void SetUp() override;
369
370 static aaudio_data_callback_result_t MyDataCallbackProc(
371 AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
372 };
373
374 // Callback function that fills the audio output buffer.
MyDataCallbackProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)375 aaudio_data_callback_result_t AAudioOutputStreamCallbackTest::MyDataCallbackProc(
376 AAudioStream *stream,
377 void *userData,
378 void *audioData,
379 int32_t numFrames) {
380 int32_t channelCount = AAudioStream_getChannelCount(stream);
381 int32_t numSamples = channelCount * numFrames;
382 if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
383 int16_t *shortData = (int16_t *) audioData;
384 for (int i = 0; i < numSamples; i++) *shortData++ = 0;
385 } else if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_FLOAT) {
386 float *floatData = (float *) audioData;
387 for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
388 }
389
390 AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
391 myData->updateFrameCount(numFrames);
392 myData->updateLatency(measureLatency(stream));
393 myData->callbackCount++;
394 return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
395 }
396
SetUp()397 void AAudioOutputStreamCallbackTest::SetUp() {
398 AAudioCtsBase::SetUp();
399
400 mSetupSuccessful = false;
401 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
402 mHelper.reset(new OutputStreamBuilderHelper(
403 std::get<PARAM_SHARING_MODE>(GetParam()),
404 std::get<PARAM_PERF_MODE>(GetParam()),
405 std::get<PARAM_AUDIO_FORMAT>(GetParam()),
406 std::get<PARAM_SAMPLE_RATE>(GetParam()))
407 );
408 mHelper->initBuilder();
409
410 int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
411 mCbData.reset(new AAudioCallbackTestData());
412 AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
413 AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
414 if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
415 AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
416 }
417
418 createAndVerifyHonoringMMap();
419
420 }
421
422 // Test starting and stopping an OUTPUT AAudioStream that uses a Callback
TEST_P(AAudioOutputStreamCallbackTest,testPlayback)423 TEST_P(AAudioOutputStreamCallbackTest, testPlayback) {
424 if (!mSetupSuccessful) return;
425
426 const int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
427 const int32_t streamFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
428 if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
429 ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
430 }
431 const int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream());
432 const int32_t callbackCountsPerBurst = streamFramesPerDataCallback == AAUDIO_UNSPECIFIED ? 1
433 : (framesPerBurst + streamFramesPerDataCallback - 1) / streamFramesPerDataCallback;
434
435 // Try all 3 methods of stopping/pausing a stream.
436 constexpr int kNumMethods = 3;
437
438 // Pausing or stopping an output stream without setting returnStop sometimes results in a xRun.
439 constexpr int kMaxXRunCount = 1;
440
441 // Start/stop more than once to see if it fails after the first time.
442 // Also check to make sure we do not get callbacks after the stop.
443 for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
444 mCbData->reset(streamFramesPerDataCallback);
445
446 mHelper->startStream();
447 // See b/62090113. For legacy path, the device is only known after
448 // the stream has been started.
449 EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
450 EXPECT_TRUE(mCbData->waitForNCallbacks(kExpectedCallbackCount));
451
452 ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
453 ASSERT_GE(mCbData->callbackCount, kExpectedCallbackCount);
454
455 ASSERT_LE(AAudioStream_getXRunCount(stream()), kMaxXRunCount);
456
457 switch (loopIndex % kNumMethods) {
458 case 0:
459 mCbData->returnStop = true; // callback return
460 mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
461 break;
462 case 1:
463 mHelper->pauseStream();
464 break;
465 case 2:
466 mHelper->stopStream();
467 break;
468 }
469
470 int32_t oldCallbackCount = mCbData->callbackCount;
471 EXPECT_GE(oldCallbackCount, kExpectedCallbackCount);
472 usleep(kExtremelyHighCallbackPeriodMillis * MICROS_PER_MILLISECOND);
473 if (AAudioExtensions::getInstance().isMMapUsed(mHelper->stream())) {
474 EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
475 } else {
476 // Allow requesting at most one burst size data from callback after stopping
477 EXPECT_GE(mCbData->callbackCount, oldCallbackCount);
478 EXPECT_LE(mCbData->callbackCount, oldCallbackCount + callbackCountsPerBurst);
479 }
480
481 if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
482 ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
483 }
484
485 EXPECT_GE(mCbData->minLatency, 1); // Absurdly low
486 // We only issue a warning here because the CDD does not mandate a specific minimum latency
487 if (mCbData->maxLatency > 300) {
488 __android_log_print(ANDROID_LOG_WARN, LOG_TAG,
489 "Suspiciously high callback latency: %d", mCbData->maxLatency);
490 }
491 //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
492
493 ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
494 }
495 }
496
497 INSTANTIATE_TEST_CASE_P(SPM, AAudioOutputStreamCallbackTest,
498 ::testing::Values(
499 std::make_tuple(
500 AAUDIO_SHARING_MODE_SHARED,
501 AAUDIO_UNSPECIFIED,
502 AAUDIO_PERFORMANCE_MODE_NONE,
503 MMAP_ALLOWED,
504 AAUDIO_FORMAT_UNSPECIFIED,
505 48000),
506 // cb buffer size: arbitrary prime number < 96
507 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
508 AAUDIO_FORMAT_UNSPECIFIED, 48000),
509 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
510 AAUDIO_FORMAT_UNSPECIFIED, 48000),
511 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
512 AAUDIO_FORMAT_UNSPECIFIED, 48000),
513 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
514 AAUDIO_FORMAT_PCM_I16, 48000),
515 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
516 AAUDIO_FORMAT_PCM_FLOAT, 48000),
517 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
518 AAUDIO_FORMAT_UNSPECIFIED, 44100),
519 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
520 AAUDIO_FORMAT_UNSPECIFIED, 44100),
521 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
522 AAUDIO_FORMAT_UNSPECIFIED, 44100),
523 // cb buffer size: arbitrary prime number > 192
524 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
525 AAUDIO_FORMAT_UNSPECIFIED, 48000),
526 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
527 AAUDIO_FORMAT_UNSPECIFIED, 48000),
528 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
529 AAUDIO_FORMAT_UNSPECIFIED, 11025),
530 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
531 AAUDIO_FORMAT_UNSPECIFIED, 11025),
532 std::make_tuple(
533 AAUDIO_SHARING_MODE_SHARED,
534 AAUDIO_UNSPECIFIED,
535 AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
536 MMAP_ALLOWED,
537 AAUDIO_FORMAT_UNSPECIFIED,
538 48000),
539 std::make_tuple(
540 AAUDIO_SHARING_MODE_SHARED,
541 AAUDIO_UNSPECIFIED,
542 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
543 MMAP_ALLOWED,
544 AAUDIO_FORMAT_UNSPECIFIED,
545 48000),
546 std::make_tuple(
547 AAUDIO_SHARING_MODE_EXCLUSIVE,
548 AAUDIO_UNSPECIFIED,
549 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
550 MMAP_ALLOWED,
551 AAUDIO_FORMAT_UNSPECIFIED,
552 48000),
553 std::make_tuple(
554 AAUDIO_SHARING_MODE_EXCLUSIVE,
555 AAUDIO_UNSPECIFIED,
556 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
557 MMAP_ALLOWED,
558 AAUDIO_FORMAT_UNSPECIFIED,
559 88200)),
560 &getTestName);
561