Merge cherrypicks of [6072696, 6072074, 6072757, 6072120, 6072121, 6072122, 6072123, 6072575, 6072576, 6072577, 6072578, 6072579, 6072193, 6072131, 6072194, 6072076, 6072210, 6072759, 6072760, 6072698, 6072699, 6072700, 6072701, 6072702, 6072703, 6072704, 6072905, 6072906, 6072907, 6072761] into oc-m8-release
Change-Id: Ia2c2924ff42d1a800a482b1d492124ba45ad5368
diff --git a/media/libaaudio/src/fifo/FifoBuffer.cpp b/media/libaaudio/src/fifo/FifoBuffer.cpp
index a869886..c8ec150 100644
--- a/media/libaaudio/src/fifo/FifoBuffer.cpp
+++ b/media/libaaudio/src/fifo/FifoBuffer.cpp
@@ -22,6 +22,8 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <algorithm>
+
#include "FifoControllerBase.h"
#include "FifoController.h"
#include "FifoControllerIndirect.h"
@@ -85,15 +87,14 @@
wrappingBuffer->data[1] = nullptr;
wrappingBuffer->numFrames[1] = 0;
if (framesAvailable > 0) {
-
uint8_t *source = &mStorage[convertFramesToBytes(startIndex)];
// Does the available data cross the end of the FIFO?
if ((startIndex + framesAvailable) > mFrameCapacity) {
wrappingBuffer->data[0] = source;
- wrappingBuffer->numFrames[0] = mFrameCapacity - startIndex;
+ fifo_frames_t firstFrames = mFrameCapacity - startIndex;
+ wrappingBuffer->numFrames[0] = firstFrames;
wrappingBuffer->data[1] = &mStorage[0];
- wrappingBuffer->numFrames[1] = mFrameCapacity - startIndex;
-
+ wrappingBuffer->numFrames[1] = framesAvailable - firstFrames;
} else {
wrappingBuffer->data[0] = source;
wrappingBuffer->numFrames[0] = framesAvailable;
@@ -102,18 +103,19 @@
wrappingBuffer->data[0] = nullptr;
wrappingBuffer->numFrames[0] = 0;
}
-
}
fifo_frames_t FifoBuffer::getFullDataAvailable(WrappingBuffer *wrappingBuffer) {
- fifo_frames_t framesAvailable = mFifo->getFullFramesAvailable();
+ // The FIFO might be overfull so clip to capacity.
+ fifo_frames_t framesAvailable = std::min(mFifo->getFullFramesAvailable(), mFrameCapacity);
fifo_frames_t startIndex = mFifo->getReadIndex();
fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex);
return framesAvailable;
}
fifo_frames_t FifoBuffer::getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer) {
- fifo_frames_t framesAvailable = mFifo->getEmptyFramesAvailable();
+ // The FIFO might have underrun so clip to capacity.
+ fifo_frames_t framesAvailable = std::min(mFifo->getEmptyFramesAvailable(), mFrameCapacity);
fifo_frames_t startIndex = mFifo->getWriteIndex();
fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex);
return framesAvailable;
diff --git a/media/libaaudio/src/fifo/FifoControllerBase.cpp b/media/libaaudio/src/fifo/FifoControllerBase.cpp
index 14a2be1..51a8e34 100644
--- a/media/libaaudio/src/fifo/FifoControllerBase.cpp
+++ b/media/libaaudio/src/fifo/FifoControllerBase.cpp
@@ -38,7 +38,7 @@
fifo_frames_t FifoControllerBase::getReadIndex() {
// % works with non-power of two sizes
- return (fifo_frames_t) (getReadCounter() % mCapacity);
+ return (fifo_frames_t) ((uint64_t)getReadCounter() % mCapacity);
}
void FifoControllerBase::advanceReadIndex(fifo_frames_t numFrames) {
@@ -51,7 +51,7 @@
fifo_frames_t FifoControllerBase::getWriteIndex() {
// % works with non-power of two sizes
- return (fifo_frames_t) (getWriteCounter() % mCapacity);
+ return (fifo_frames_t) ((uint64_t)getWriteCounter() % mCapacity);
}
void FifoControllerBase::advanceWriteIndex(fifo_frames_t numFrames) {
diff --git a/media/libaaudio/tests/Android.mk b/media/libaaudio/tests/Android.mk
index 37b010d..8117181 100644
--- a/media/libaaudio/tests/Android.mk
+++ b/media/libaaudio/tests/Android.mk
@@ -80,3 +80,13 @@
LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
LOCAL_MODULE := test_n_streams
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
+LOCAL_SRC_FILES:= test_atomic_fifo.cpp
+LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
+LOCAL_MODULE := test_atomic_fifo
+include $(BUILD_NATIVE_TEST)
diff --git a/media/libaaudio/tests/test_atomic_fifo.cpp b/media/libaaudio/tests/test_atomic_fifo.cpp
new file mode 100644
index 0000000..0edfebe
--- /dev/null
+++ b/media/libaaudio/tests/test_atomic_fifo.cpp
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <iostream>
+
+#include <gtest/gtest.h>
+#include <stdlib.h>
+
+#include "fifo/FifoBuffer.h"
+#include "fifo/FifoController.h"
+
+using android::fifo_frames_t;
+using android::fifo_counter_t;
+using android::FifoController;
+using android::FifoBuffer;
+using android::WrappingBuffer;
+
+TEST(test_fifo_controller, fifo_indices) {
+ // Values are arbitrary primes designed to trigger edge cases.
+ constexpr int capacity = 83;
+ constexpr int threshold = 47;
+ FifoController fifoController(capacity, threshold);
+ ASSERT_EQ(capacity, fifoController.getCapacity());
+ ASSERT_EQ(threshold, fifoController.getThreshold());
+
+ ASSERT_EQ(0, fifoController.getReadCounter());
+ ASSERT_EQ(0, fifoController.getWriteCounter());
+ ASSERT_EQ(0, fifoController.getFullFramesAvailable());
+ ASSERT_EQ(threshold, fifoController.getEmptyFramesAvailable());
+
+ // Pretend to write some data.
+ constexpr int advance1 = 23;
+ fifoController.advanceWriteIndex(advance1);
+ int advanced = advance1;
+ ASSERT_EQ(0, fifoController.getReadCounter());
+ ASSERT_EQ(0, fifoController.getReadIndex());
+ ASSERT_EQ(advanced, fifoController.getWriteCounter());
+ ASSERT_EQ(advanced, fifoController.getWriteIndex());
+ ASSERT_EQ(advanced, fifoController.getFullFramesAvailable());
+ ASSERT_EQ(threshold - advanced, fifoController.getEmptyFramesAvailable());
+
+ // Pretend to read the data.
+ fifoController.advanceReadIndex(advance1);
+ ASSERT_EQ(advanced, fifoController.getReadCounter());
+ ASSERT_EQ(advanced, fifoController.getReadIndex());
+ ASSERT_EQ(advanced, fifoController.getWriteCounter());
+ ASSERT_EQ(advanced, fifoController.getWriteIndex());
+ ASSERT_EQ(0, fifoController.getFullFramesAvailable());
+ ASSERT_EQ(threshold, fifoController.getEmptyFramesAvailable());
+
+ // Write past end of buffer.
+ constexpr int advance2 = 13 + capacity - advance1;
+ fifoController.advanceWriteIndex(advance2);
+ advanced += advance2;
+ ASSERT_EQ(advance1, fifoController.getReadCounter());
+ ASSERT_EQ(advance1, fifoController.getReadIndex());
+ ASSERT_EQ(advanced, fifoController.getWriteCounter());
+ ASSERT_EQ(advanced - capacity, fifoController.getWriteIndex());
+ ASSERT_EQ(advance2, fifoController.getFullFramesAvailable());
+ ASSERT_EQ(threshold - advance2, fifoController.getEmptyFramesAvailable());
+}
+
+TEST(test_fifo_controller, fifo_wrap_around_zero) {
+ constexpr int capacity = 7; // arbitrary prime
+ constexpr int threshold = capacity;
+ FifoController fifoController(capacity, threshold);
+ ASSERT_EQ(capacity, fifoController.getCapacity());
+ ASSERT_EQ(threshold, fifoController.getThreshold());
+
+ fifoController.setReadCounter(-10); // a bit less than negative capacity
+ for (int i = 0; i < 20; i++) {
+ EXPECT_EQ(i - 10, fifoController.getReadCounter());
+ EXPECT_GE(fifoController.getReadIndex(), 0);
+ EXPECT_LT(fifoController.getReadIndex(), capacity);
+ fifoController.advanceReadIndex(1);
+ }
+
+ fifoController.setWriteCounter(-10);
+ for (int i = 0; i < 20; i++) {
+ EXPECT_EQ(i - 10, fifoController.getWriteCounter());
+ EXPECT_GE(fifoController.getWriteIndex(), 0);
+ EXPECT_LT(fifoController.getWriteIndex(), capacity);
+ fifoController.advanceWriteIndex(1);
+ }
+}
+
+
+// TODO consider using a template for other data types.
+
+// Create a big array and then use a region in the middle for the unit tests.
+// Then we can scan the rest of the array to see if it got clobbered.
+static constexpr fifo_frames_t kBigArraySize = 1024;
+static constexpr fifo_frames_t kFifoDataOffset = 128; // starting index of FIFO data
+static constexpr int16_t kSafeDataValue = 0x7654; // original value of BigArray
+
+class TestFifoBuffer {
+public:
+ explicit TestFifoBuffer(fifo_frames_t capacity, fifo_frames_t threshold = 0)
+ : mFifoBuffer(sizeof(int16_t), capacity,
+ &mReadIndex,
+ &mWriteIndex,
+ &mVeryBigArray[kFifoDataOffset]) // address of start of FIFO data
+ {
+
+ // Assume a frame is one int16_t.
+ // For reading and writing.
+ if (threshold <= 0) {
+ threshold = capacity;
+ }
+ mFifoBuffer.setThreshold(threshold);
+ mThreshold = threshold;
+
+ for (fifo_frames_t i = 0; i < kBigArraySize; i++) {
+ mVeryBigArray[i] = kSafeDataValue;
+ }
+ }
+
+ void checkMisc() {
+ ASSERT_EQ((int32_t)(2 * sizeof(int16_t)), mFifoBuffer.convertFramesToBytes(2));
+ ASSERT_EQ(mThreshold, mFifoBuffer.getThreshold());
+ }
+
+ void verifyAddressInRange(void *p, void *valid, size_t numBytes) {
+ uintptr_t p_int = (uintptr_t) p;
+ uintptr_t valid_int = (uintptr_t) valid;
+ EXPECT_GE(p_int, valid_int);
+ EXPECT_LT(p_int, (valid_int + numBytes));
+ }
+
+ void verifyStorageIntegrity() {
+ for (fifo_frames_t i = 0; i < kFifoDataOffset; i++) {
+ EXPECT_EQ(mVeryBigArray[i], kSafeDataValue);
+ }
+ fifo_frames_t firstFrameAfter = kFifoDataOffset + mFifoBuffer.getBufferCapacityInFrames();
+ for (fifo_frames_t i = firstFrameAfter; i < kBigArraySize; i++) {
+ EXPECT_EQ(mVeryBigArray[i], kSafeDataValue);
+ }
+ }
+
+ // Verify that the available frames in each part add up correctly.
+ void verifyWrappingBuffer() {
+ WrappingBuffer wrappingBuffer;
+
+
+ // Does the sum of the two parts match the available value returned?
+ // For EmptyRoom
+ fifo_frames_t framesAvailable =
+ mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable();
+ fifo_frames_t wrapAvailable = mFifoBuffer.getEmptyRoomAvailable(&wrappingBuffer);
+ EXPECT_EQ(framesAvailable, wrapAvailable);
+ fifo_frames_t bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1];
+ EXPECT_EQ(framesAvailable, bothAvailable);
+ // For FullData
+ framesAvailable =
+ mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable();
+ wrapAvailable = mFifoBuffer.getFullDataAvailable(&wrappingBuffer);
+ EXPECT_EQ(framesAvailable, wrapAvailable);
+ bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1];
+ EXPECT_EQ(framesAvailable, bothAvailable);
+
+ // Are frame counts in legal range?
+ fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames();
+ EXPECT_GE(wrappingBuffer.numFrames[0], 0);
+ EXPECT_LE(wrappingBuffer.numFrames[0], capacity);
+ EXPECT_GE(wrappingBuffer.numFrames[1], 0);
+ EXPECT_LE(wrappingBuffer.numFrames[1], capacity);
+
+ // Are addresses within the FIFO data area?
+ size_t validBytes = capacity * sizeof(int16_t);
+ if (wrappingBuffer.numFrames[0]) {
+ verifyAddressInRange(wrappingBuffer.data[0], mFifoStorage, validBytes);
+ uint8_t *last = ((uint8_t *)wrappingBuffer.data[0])
+ + mFifoBuffer.convertFramesToBytes(wrappingBuffer.numFrames[0]) - 1;
+ verifyAddressInRange(last, mFifoStorage, validBytes);
+ }
+ if (wrappingBuffer.numFrames[1]) {
+ verifyAddressInRange(wrappingBuffer.data[1], mFifoStorage, validBytes);
+ uint8_t *last = ((uint8_t *)wrappingBuffer.data[1])
+ + mFifoBuffer.convertFramesToBytes(wrappingBuffer.numFrames[1]) - 1;
+ verifyAddressInRange(last, mFifoStorage, validBytes);
+ }
+
+ }
+
+ // Write data but do not overflow.
+ void writeMultipleDataFrames(fifo_frames_t numFrames) {
+ fifo_frames_t framesAvailable =
+ mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable();
+ fifo_frames_t framesToWrite = std::min(framesAvailable, numFrames);
+ for (int i = 0; i < framesToWrite; i++) {
+ mData[i] = mNextWriteIndex++;
+ }
+ fifo_frames_t actual = mFifoBuffer.write(mData, framesToWrite);
+ ASSERT_EQ(framesToWrite, actual);
+ }
+
+ // Read whatever data is available, Do not underflow.
+ void verifyMultipleDataFrames(fifo_frames_t numFrames) {
+ fifo_frames_t framesAvailable =
+ mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable();
+ fifo_frames_t framesToRead = std::min(framesAvailable, numFrames);
+ fifo_frames_t actual = mFifoBuffer.read(mData, framesToRead);
+ ASSERT_EQ(framesToRead, actual);
+ for (int i = 0; i < framesToRead; i++) {
+ ASSERT_EQ(mNextVerifyIndex++, mData[i]);
+ }
+ }
+
+ // Read specified number of frames
+ void verifyRequestedData(fifo_frames_t numFrames) {
+ fifo_frames_t framesAvailable =
+ mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable();
+ ASSERT_LE(numFrames, framesAvailable);
+ fifo_frames_t framesToRead = std::min(framesAvailable, numFrames);
+ fifo_frames_t actual = mFifoBuffer.read(mData, framesToRead);
+ ASSERT_EQ(actual, numFrames);
+ for (int i = 0; i < actual; i++) {
+ ASSERT_EQ(mNextVerifyIndex++, mData[i]);
+ }
+ }
+
+ // Wrap around the end of the buffer.
+ void checkWrappingWriteRead() {
+ constexpr int frames1 = 43;
+ constexpr int frames2 = 15;
+
+ writeMultipleDataFrames(frames1);
+ verifyWrappingBuffer();
+ verifyRequestedData(frames1);
+ verifyWrappingBuffer();
+
+ writeMultipleDataFrames(frames2);
+ verifyWrappingBuffer();
+ verifyRequestedData(frames2);
+ verifyWrappingBuffer();
+
+ verifyStorageIntegrity();
+ }
+
+ // Write and Read a specific amount of data.
+ void checkWriteRead() {
+ const fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames();
+ // Wrap around with the smaller region in the second half.
+ const int frames1 = capacity - 4;
+ const int frames2 = 7; // arbitrary, small
+ writeMultipleDataFrames(frames1);
+ verifyRequestedData(frames1);
+ writeMultipleDataFrames(frames2);
+ verifyRequestedData(frames2);
+
+ verifyStorageIntegrity();
+ }
+
+ // Write and Read a specific amount of data.
+ void checkWriteReadSmallLarge() {
+ const fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames();
+ // Wrap around with the larger region in the second half.
+ const int frames1 = capacity - 4;
+ const int frames2 = capacity - 9; // arbitrary, large
+ writeMultipleDataFrames(frames1);
+ verifyRequestedData(frames1);
+ writeMultipleDataFrames(frames2);
+ verifyRequestedData(frames2);
+
+ verifyStorageIntegrity();
+ }
+
+ // Randomly read or write up to the maximum amount of data.
+ void checkRandomWriteRead() {
+ for (int i = 0; i < 20; i++) {
+ fifo_frames_t framesEmpty =
+ mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable();
+ fifo_frames_t numFrames = (fifo_frames_t)(drand48() * framesEmpty);
+ writeMultipleDataFrames(numFrames);
+
+ fifo_frames_t framesFull =
+ mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable();
+ numFrames = (fifo_frames_t)(drand48() * framesFull);
+ verifyMultipleDataFrames(numFrames);
+ }
+
+ verifyStorageIntegrity();
+ }
+
+ // Write and Read a specific amount of data.
+ void checkNegativeCounters() {
+ fifo_counter_t counter = -9876;
+ mFifoBuffer.setWriteCounter(counter);
+ mFifoBuffer.setReadCounter(counter);
+ checkWrappingWriteRead();
+ }
+
+ // Wrap over the boundary at 0x7FFFFFFFFFFFFFFF
+ // Note that the behavior of a signed overflow is technically undefined.
+ void checkHalfWrap() {
+ fifo_counter_t counter = INT64_MAX - 10;
+ mFifoBuffer.setWriteCounter(counter);
+ mFifoBuffer.setReadCounter(counter);
+ ASSERT_GT(mFifoBuffer.getWriteCounter(), 0);
+ checkWrappingWriteRead();
+ ASSERT_LT(mFifoBuffer.getWriteCounter(), 0); // did we wrap past INT64_MAX?
+ }
+
+ // Wrap over the boundary at 0xFFFFFFFFFFFFFFFF
+ void checkFullWrap() {
+ fifo_counter_t counter = -10;
+ mFifoBuffer.setWriteCounter(counter);
+ mFifoBuffer.setReadCounter(counter);
+ ASSERT_LT(mFifoBuffer.getWriteCounter(), 0);
+ writeMultipleDataFrames(20);
+ ASSERT_GT(mFifoBuffer.getWriteCounter(), 0); // did we wrap past zero?
+ verifyStorageIntegrity();
+ }
+
+ FifoBuffer mFifoBuffer;
+ fifo_frames_t mNextWriteIndex = 0;
+ fifo_frames_t mNextVerifyIndex = 0;
+ fifo_frames_t mThreshold;
+
+ fifo_counter_t mReadIndex = 0;
+ fifo_counter_t mWriteIndex = 0;
+ int16_t mVeryBigArray[kBigArraySize]; // Use the middle of this array for the FIFO.
+ int16_t *mFifoStorage = &mVeryBigArray[kFifoDataOffset]; // Start here for storage.
+ int16_t mData[kBigArraySize]{};
+};
+
+TEST(test_fifo_buffer, fifo_write_read) {
+ constexpr int capacity = 51; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkMisc();
+ tester.checkWriteRead();
+}
+
+TEST(test_fifo_buffer, fifo_wrapping_write_read) {
+ constexpr int capacity = 59; // arbitrary, a little bigger this time
+ TestFifoBuffer tester(capacity);
+ tester.checkWrappingWriteRead();
+}
+
+TEST(test_fifo_buffer, fifo_read_write_small_large) {
+ constexpr int capacity = 51; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkWriteReadSmallLarge();
+}
+
+TEST(test_fifo_buffer, fifo_random_read_write) {
+ constexpr int capacity = 51; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkRandomWriteRead();
+}
+
+TEST(test_fifo_buffer, fifo_random_threshold) {
+ constexpr int capacity = 67; // arbitrary
+ constexpr int threshold = 37; // arbitrary
+ TestFifoBuffer tester(capacity, threshold);
+ tester.checkRandomWriteRead();
+}
+
+TEST(test_fifo_buffer, fifo_negative_counters) {
+ constexpr int capacity = 49; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkNegativeCounters();
+}
+
+TEST(test_fifo_buffer, fifo_half_wrap) {
+ constexpr int capacity = 57; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkHalfWrap();
+}
+
+TEST(test_fifo_buffer, fifo_full_wrap) {
+ constexpr int capacity = 57; // arbitrary
+ TestFifoBuffer tester(capacity);
+ tester.checkFullWrap();
+}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 39f04fb..3b90073 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2887,6 +2887,8 @@
}
{
+ Mutex::Autolock _l(mLock);
+
if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
// if uuid is specified, request effect descriptor
lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
@@ -2942,6 +2944,8 @@
desc = d;
}
}
+ }
+ {
// Do not allow auxiliary effects on a session different from 0 (output mix)
if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&