Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 628286b6 authored by Xin Li's avatar Xin Li
Browse files

DO NOT MERGE - Merge PPRL.190305.001 into master

Bug: 127812889
Change-Id: I96d8fdd0e8a40a783a2f4ee91a01dbad44a22956
parents fe610f0f a31eb276
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ fifo_frames_t FifoControllerBase::getFullFramesAvailable() {

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::getEmptyFramesAvailable() {

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) {
+189 −30
Original line number Diff line number Diff line
@@ -23,12 +23,12 @@
#include "fifo/FifoController.h"

using android::fifo_frames_t;
using android::fifo_counter_t;
using android::FifoController;
using android::FifoBuffer;
using android::WrappingBuffer;

//void foo() {
TEST(test_fifi_controller, fifo_indices) {
TEST(test_fifo_controller, fifo_indices) {
    // Values are arbitrary primes designed to trigger edge cases.
    constexpr int capacity = 83;
    constexpr int threshold = 47;
@@ -73,18 +73,59 @@ TEST(test_fifi_controller, fifo_indices) {
    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) {
        : 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.
        mData = new int16_t[capacity];
        if (threshold <= 0) {
            threshold = capacity;
        }
        mFifoBuffer.setThreshold(threshold);
        mThreshold = threshold;

        for (fifo_frames_t i = 0; i < kBigArraySize; i++) {
            mVeryBigArray[i] = kSafeDataValue;
        }
    }

    void checkMisc() {
@@ -92,26 +133,70 @@ public:
        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 checkWrappingBuffer() {
    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 writeData(fifo_frames_t numFrames) {
    void writeMultipleDataFrames(fifo_frames_t numFrames) {
        fifo_frames_t framesAvailable =
                mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable();
        fifo_frames_t framesToWrite = std::min(framesAvailable, numFrames);
@@ -122,8 +207,8 @@ public:
        ASSERT_EQ(framesToWrite, actual);
    }

    // Read data but do not underflow.
    void verifyData(fifo_frames_t numFrames) {
    // 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);
@@ -134,20 +219,35 @@ public:
        }
    }

    // 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;

        writeData(frames1);
        checkWrappingBuffer();
        verifyData(frames1);
        checkWrappingBuffer();
        writeMultipleDataFrames(frames1);
        verifyWrappingBuffer();
        verifyRequestedData(frames1);
        verifyWrappingBuffer();

        writeMultipleDataFrames(frames2);
        verifyWrappingBuffer();
        verifyRequestedData(frames2);
        verifyWrappingBuffer();

        writeData(frames2);
        checkWrappingBuffer();
        verifyData(frames2);
        checkWrappingBuffer();
        verifyStorageIntegrity();
    }

    // Write and Read a specific amount of data.
@@ -156,10 +256,12 @@ public:
        // Wrap around with the smaller region in the second half.
        const int frames1 = capacity - 4;
        const int frames2 = 7; // arbitrary, small
        writeData(frames1);
        verifyData(frames1);
        writeData(frames2);
        verifyData(frames2);
        writeMultipleDataFrames(frames1);
        verifyRequestedData(frames1);
        writeMultipleDataFrames(frames2);
        verifyRequestedData(frames2);

        verifyStorageIntegrity();
    }

    // Write and Read a specific amount of data.
@@ -168,10 +270,12 @@ public:
        // Wrap around with the larger region in the second half.
        const int frames1 = capacity - 4;
        const int frames2 = capacity - 9; // arbitrary, large
        writeData(frames1);
        verifyData(frames1);
        writeData(frames2);
        verifyData(frames2);
        writeMultipleDataFrames(frames1);
        verifyRequestedData(frames1);
        writeMultipleDataFrames(frames2);
        verifyRequestedData(frames2);

        verifyStorageIntegrity();
    }

    // Randomly read or write up to the maximum amount of data.
@@ -180,30 +284,67 @@ public:
            fifo_frames_t framesEmpty =
                    mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable();
            fifo_frames_t numFrames = (fifo_frames_t)(drand48() * framesEmpty);
            writeData(numFrames);
            writeMultipleDataFrames(numFrames);

            fifo_frames_t framesFull =
                    mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable();
            numFrames = (fifo_frames_t)(drand48() * framesFull);
            verifyData(numFrames);
            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;
    int16_t       *mData;
    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_read_write) {
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_read_write) {
TEST(test_fifo_buffer, fifo_wrapping_write_read) {
    constexpr int capacity = 59; // arbitrary, a little bigger this time
    TestFifoBuffer tester(capacity);
    tester.checkWrappingWriteRead();
@@ -227,3 +368,21 @@ TEST(test_fifo_buffer, fifo_random_threshold) {
    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();
}
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ void HalDeathHandler::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/)
        handler.second();
    }
    ALOGE("HAL server crashed, audio server is restarting");
    exit(1);
    _exit(1);  // Avoid calling atexit handlers, as this code runs on a thread from RPC threadpool.
}

} // namespace android
+4 −0
Original line number Diff line number Diff line
@@ -3001,6 +3001,8 @@ sp<IEffect> AudioFlinger::createEffect(
    }

    {
        Mutex::Autolock _l(mLock);

        if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
            // if uuid is specified, request effect descriptor
            lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
@@ -3056,6 +3058,8 @@ sp<IEffect> AudioFlinger::createEffect(
                desc = d;
            }
        }
    }
    {

        // Do not allow auxiliary effects on a session different from 0 (output mix)
        if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&