AudioRecordTest: Release AudioRecord on failure
Reduces the collateral test failures as AudioRecord
is a system-wide resource.
Bug: 22173057
Change-Id: I30ed19b967417eeba8149e0e0fe45ec4187ec015
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 6ba1aeb..36f2a2b 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -678,174 +678,192 @@
listener = new MockOnRecordPositionUpdateListener(record);
}
- if (markerPeriodsPerSecond != 0) {
- mMarkerPeriodInFrames = TEST_SR / markerPeriodsPerSecond;
- mMarkerPosition = mMarkerPeriodInFrames;
- assertEquals(AudioRecord.SUCCESS,
- record.setNotificationMarkerPosition(mMarkerPosition));
- } else {
- mMarkerPeriodInFrames = 0;
- }
final int updatePeriodInFrames = (periodsPerSecond == 0)
? 0 : TEST_SR / periodsPerSecond;
- assertEquals(AudioRecord.SUCCESS,
- record.setPositionNotificationPeriod(updatePeriodInFrames));
-
- listener.start(TEST_SR);
- record.startRecording();
- assertEquals(AudioRecord.RECORDSTATE_RECORDING, record.getRecordingState());
- long startTime = System.currentTimeMillis();
-
- // For our tests, we could set test duration by timed sleep or by # frames received.
- // Since we don't know *exactly* when AudioRecord actually begins recording,
- // we end the test by # frames read.
- final int numChannels = AudioFormat.channelCountFromInChannelMask(TEST_CONF);
- final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT);
- final int bytesPerFrame = numChannels * bytesPerSample;
- // careful about integer overflow in the formula below:
- final int targetSamples = (int)((long)TEST_TIME_MS * TEST_SR * numChannels / 1000);
- final int BUFFER_FRAMES = 512;
- final int BUFFER_SAMPLES = BUFFER_FRAMES * numChannels;
- // TODO: verify behavior when buffer size is not a multiple of frame size.
-
// After starting, there is no guarantee when the first frame of data is read.
long firstSampleTime = 0;
- int samplesRead = 0;
- if (useByteBuffer) {
- ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SAMPLES * bytesPerSample);
- while (samplesRead < targetSamples) {
- // the first time through, we read a single frame.
- // this sets the recording anchor position.
- int amount = samplesRead == 0 ? numChannels :
- Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
- amount *= bytesPerSample; // in bytes
- // read always places data at the start of the byte buffer with
- // position and limit are ignored. test this by setting
- // position and limit to arbitrary values here.
- final int lastPosition = 7;
- final int lastLimit = 13;
- byteBuffer.position(lastPosition);
- byteBuffer.limit(lastLimit);
- int ret = blocking ? record.read(byteBuffer, amount) :
- record.read(byteBuffer, amount, AudioRecord.READ_NON_BLOCKING);
- // so long as amount requested in bytes is a multiple of the frame size
- // we expect the byte buffer request to be filled. Caution: the
- // byte buffer data will be in native endian order, not Java order.
- if (blocking) {
- assertEquals(amount, ret);
- } else {
- assertTrue("0 <= " + ret + " <= " + amount, 0 <= ret && ret <= amount);
- }
- // position, limit are not changed by read().
- assertEquals(lastPosition, byteBuffer.position());
- assertEquals(lastLimit, byteBuffer.limit());
- if (samplesRead == 0 && ret > 0) {
- firstSampleTime = System.currentTimeMillis();
- }
- samplesRead += ret / bytesPerSample;
+
+ // blank final variables: all successful paths will initialize the times.
+ final long endTime;
+ final long startTime;
+ final long stopTime;
+
+ try {
+ if (markerPeriodsPerSecond != 0) {
+ mMarkerPeriodInFrames = TEST_SR / markerPeriodsPerSecond;
+ mMarkerPosition = mMarkerPeriodInFrames;
+ assertEquals(AudioRecord.SUCCESS,
+ record.setNotificationMarkerPosition(mMarkerPosition));
+ } else {
+ mMarkerPeriodInFrames = 0;
}
- } else {
- switch (TEST_FORMAT) {
- case AudioFormat.ENCODING_PCM_8BIT: {
- // For 8 bit data, use bytes
- byte[] byteData = new byte[BUFFER_SAMPLES];
+
+ assertEquals(AudioRecord.SUCCESS,
+ record.setPositionNotificationPeriod(updatePeriodInFrames));
+
+ listener.start(TEST_SR);
+ record.startRecording();
+ assertEquals(AudioRecord.RECORDSTATE_RECORDING, record.getRecordingState());
+ startTime = System.currentTimeMillis();
+
+ // For our tests, we could set test duration by timed sleep or by # frames received.
+ // Since we don't know *exactly* when AudioRecord actually begins recording,
+ // we end the test by # frames read.
+ final int numChannels = AudioFormat.channelCountFromInChannelMask(TEST_CONF);
+ final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT);
+ final int bytesPerFrame = numChannels * bytesPerSample;
+ // careful about integer overflow in the formula below:
+ final int targetSamples = (int)((long)TEST_TIME_MS * TEST_SR * numChannels / 1000);
+ final int BUFFER_FRAMES = 512;
+ final int BUFFER_SAMPLES = BUFFER_FRAMES * numChannels;
+ // TODO: verify behavior when buffer size is not a multiple of frame size.
+
+ int samplesRead = 0;
+ if (useByteBuffer) {
+ ByteBuffer byteBuffer =
+ ByteBuffer.allocateDirect(BUFFER_SAMPLES * bytesPerSample);
while (samplesRead < targetSamples) {
// the first time through, we read a single frame.
// this sets the recording anchor position.
int amount = samplesRead == 0 ? numChannels :
Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
- int ret = blocking ? record.read(byteData, 0, amount) :
- record.read(byteData, 0, amount, AudioRecord.READ_NON_BLOCKING);
+ amount *= bytesPerSample; // in bytes
+ // read always places data at the start of the byte buffer with
+ // position and limit are ignored. test this by setting
+ // position and limit to arbitrary values here.
+ final int lastPosition = 7;
+ final int lastLimit = 13;
+ byteBuffer.position(lastPosition);
+ byteBuffer.limit(lastLimit);
+ int ret = blocking ? record.read(byteBuffer, amount) :
+ record.read(byteBuffer, amount, AudioRecord.READ_NON_BLOCKING);
+ // so long as amount requested in bytes is a multiple of the frame size
+ // we expect the byte buffer request to be filled. Caution: the
+ // byte buffer data will be in native endian order, not Java order.
if (blocking) {
assertEquals(amount, ret);
} else {
- assertTrue("0 <= " + ret + " <= " + amount, 0 <= ret && ret <= amount);
+ assertTrue("0 <= " + ret + " <= " + amount,
+ 0 <= ret && ret <= amount);
}
+ // position, limit are not changed by read().
+ assertEquals(lastPosition, byteBuffer.position());
+ assertEquals(lastLimit, byteBuffer.limit());
if (samplesRead == 0 && ret > 0) {
firstSampleTime = System.currentTimeMillis();
}
- samplesRead += ret;
+ samplesRead += ret / bytesPerSample;
}
- } break;
- case AudioFormat.ENCODING_PCM_16BIT: {
- // For 16 bit data, use shorts
- short[] shortData = new short[BUFFER_SAMPLES];
- while (samplesRead < targetSamples) {
- // the first time through, we read a single frame.
- // this sets the recording anchor position.
- int amount = samplesRead == 0 ? numChannels :
- Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
- int ret = blocking ? record.read(shortData, 0, amount) :
- record.read(shortData, 0, amount, AudioRecord.READ_NON_BLOCKING);
- if (blocking) {
- assertEquals(amount, ret);
- } else {
- assertTrue("0 <= " + ret + " <= " + amount, 0 <= ret && ret <= amount);
+ } else {
+ switch (TEST_FORMAT) {
+ case AudioFormat.ENCODING_PCM_8BIT: {
+ // For 8 bit data, use bytes
+ byte[] byteData = new byte[BUFFER_SAMPLES];
+ while (samplesRead < targetSamples) {
+ // the first time through, we read a single frame.
+ // this sets the recording anchor position.
+ int amount = samplesRead == 0 ? numChannels :
+ Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
+ int ret = blocking ? record.read(byteData, 0, amount) :
+ record.read(byteData, 0, amount, AudioRecord.READ_NON_BLOCKING);
+ if (blocking) {
+ assertEquals(amount, ret);
+ } else {
+ assertTrue("0 <= " + ret + " <= " + amount,
+ 0 <= ret && ret <= amount);
+ }
+ if (samplesRead == 0 && ret > 0) {
+ firstSampleTime = System.currentTimeMillis();
+ }
+ samplesRead += ret;
}
- if (samplesRead == 0 && ret > 0) {
- firstSampleTime = System.currentTimeMillis();
+ } break;
+ case AudioFormat.ENCODING_PCM_16BIT: {
+ // For 16 bit data, use shorts
+ short[] shortData = new short[BUFFER_SAMPLES];
+ while (samplesRead < targetSamples) {
+ // the first time through, we read a single frame.
+ // this sets the recording anchor position.
+ int amount = samplesRead == 0 ? numChannels :
+ Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
+ int ret = blocking ? record.read(shortData, 0, amount) :
+ record.read(shortData, 0, amount, AudioRecord.READ_NON_BLOCKING);
+ if (blocking) {
+ assertEquals(amount, ret);
+ } else {
+ assertTrue("0 <= " + ret + " <= " + amount,
+ 0 <= ret && ret <= amount);
+ }
+ if (samplesRead == 0 && ret > 0) {
+ firstSampleTime = System.currentTimeMillis();
+ }
+ samplesRead += ret;
}
- samplesRead += ret;
+ } break;
+ case AudioFormat.ENCODING_PCM_FLOAT: {
+ float[] floatData = new float[BUFFER_SAMPLES];
+ while (samplesRead < targetSamples) {
+ // the first time through, we read a single frame.
+ // this sets the recording anchor position.
+ int amount = samplesRead == 0 ? numChannels :
+ Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
+ int ret = record.read(floatData, 0, amount, blocking ?
+ AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
+ if (blocking) {
+ assertEquals(amount, ret);
+ } else {
+ assertTrue("0 <= " + ret + " <= " + amount,
+ 0 <= ret && ret <= amount);
+ }
+ if (samplesRead == 0 && ret > 0) {
+ firstSampleTime = System.currentTimeMillis();
+ }
+ samplesRead += ret;
+ }
+ } break;
}
- } break;
- case AudioFormat.ENCODING_PCM_FLOAT: {
- float[] floatData = new float[BUFFER_SAMPLES];
- while (samplesRead < targetSamples) {
- // the first time through, we read a single frame.
- // this sets the recording anchor position.
- int amount = samplesRead == 0 ? numChannels :
- Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
- int ret = record.read(floatData, 0, amount, blocking ?
- AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
- if (blocking) {
- assertEquals(amount, ret);
- } else {
- assertTrue("0 <= " + ret + " <= " + amount, 0 <= ret && ret <= amount);
- }
- if (samplesRead == 0 && ret > 0) {
- firstSampleTime = System.currentTimeMillis();
- }
- samplesRead += ret;
- }
- } break;
}
+
+ // We've read all the frames, now check the record timing.
+ endTime = System.currentTimeMillis();
+ //Log.d(TAG, "first sample time " + (firstSampleTime - startTime)
+ // + " test time " + (endTime - firstSampleTime));
+ // Verify recording starts within 200 ms of record.startRecording() (typical 100ms)
+ // Verify recording completes within 50 ms of expected test time (typical 20ms)
+ assertEquals(0, firstSampleTime - startTime, 200);
+ assertEquals(TEST_TIME_MS, endTime - firstSampleTime, auditRecording ? 1000 : 50);
+
+ // Even though we've read all the frames we want, the events may not be sent to
+ // the listeners (events are handled through a separate internal callback thread).
+ // One must sleep to make sure the last event(s) come in.
+ Thread.sleep(30);
+
+ record.stop();
+ assertEquals(AudioRecord.RECORDSTATE_STOPPED, record.getRecordingState());
+
+ stopTime = System.currentTimeMillis();
+
+ // stop listening - we should be done.
+ // Caution M behavior and likely much earlier:
+ // we assume no events can happen after stop(), but this may not
+ // always be true as stop can take 100ms to complete (as it may disable
+ // input recording on the hal); thus the event handler may be block with
+ // valid events, issuing right after stop completes. Except for those events,
+ // no other events should show up after stop.
+ // This behavior may change in the future but we account for it here in testing.
+ listener.stop();
+
+ // clean up
+ if (makeSomething != null) {
+ makeSomething.join();
+ }
+
+ } finally {
+ listener.release();
+ // we must release the record immediately as it is a system-wide
+ // resource needed for other tests.
+ record.release();
}
-
- // We've read all the frames, now check the record timing.
- final long endTime = System.currentTimeMillis();
- //Log.d(TAG, "first sample time " + (firstSampleTime - startTime)
- // + " test time " + (endTime - firstSampleTime));
- // Verify recording starts within 200 ms of record.startRecording() (typical 100ms)
- // Verify recording completes within 50 ms of expected test time (typical 20ms)
- assertEquals(0, firstSampleTime - startTime, 200);
- assertEquals(TEST_TIME_MS, endTime - firstSampleTime, auditRecording ? 1000 : 50);
-
- // Even though we've read all the frames we want, the events may not be sent to
- // the listeners (events are handled through a separate internal callback thread).
- // One must sleep to make sure the last event(s) come in.
- Thread.sleep(30);
-
- record.stop();
- assertEquals(AudioRecord.RECORDSTATE_STOPPED, record.getRecordingState());
-
- final long stopTime = System.currentTimeMillis();
-
- // stop listening - we should be done.
- // Caution M behavior and likely much earlier:
- // we assume no events can happen after stop(), but this may not
- // always be true as stop can take 100ms to complete (as it may disable
- // input recording on the hal); thus the event handler may be block with
- // valid events, issuing right after stop completes. Except for those events,
- // no other events should show up after stop.
- // This behavior may change in the future but we account for it here in testing.
- listener.stop();
-
- // clean up
- if (makeSomething != null) {
- makeSomething.join();
- }
- listener.release();
- record.release();
if (auditRecording) { // don't check timing if auditing (messes up timing)
return;
}
@@ -993,6 +1011,7 @@
}
public synchronized void release() {
+ stop();
mAudioRecord.setRecordPositionUpdateListener(null);
mAudioRecord = null;
}