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

Commit d0ffd62e authored by Phil Burk's avatar Phil Burk
Browse files

Oboe Tests: added test_marshalling.cpp



Bug: 33347409
Test: these are gtests

Change-Id: Ie79751464f4147744d25740da991a57fffa03c70
Signed-off-by: default avatarPhil Burk <philburk@google.com>
parent addae1cf
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -7,9 +7,8 @@ LOCAL_C_INCLUDES := \
    frameworks/av/media/liboboe/src/core \
    frameworks/av/media/liboboe/src/utility
LOCAL_SRC_FILES := test_oboe_api.cpp
LOCAL_SHARED_LIBRARIES := libaudioutils libmedia \
                          libbinder libcutils libutils \
                          libaudioclient liblog
LOCAL_SHARED_LIBRARIES := libaudioclient libaudioutils libbinder \
                          libcutils liblog libmedia libutils
LOCAL_STATIC_LIBRARIES := liboboe
LOCAL_MODULE := test_oboe_api
include $(BUILD_NATIVE_TEST)
@@ -21,7 +20,23 @@ LOCAL_C_INCLUDES := \
    frameworks/av/media/liboboe/src/core \
    frameworks/av/media/liboboe/src/utility
LOCAL_SRC_FILES:= test_handle_tracker.cpp
LOCAL_SHARED_LIBRARIES := libbinder libcutils libutils liblog
LOCAL_SHARED_LIBRARIES := libaudioclient libaudioutils libbinder \
                          libcutils liblog libmedia libutils
LOCAL_STATIC_LIBRARIES := liboboe
LOCAL_MODULE := test_handle_tracker
include $(BUILD_NATIVE_TEST)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
    $(call include-path-for, audio-utils) \
    frameworks/av/media/liboboe/include \
    frameworks/av/media/liboboe/src \
    frameworks/av/media/liboboe/src/core \
    frameworks/av/media/liboboe/src/fifo \
    frameworks/av/media/liboboe/src/utility
LOCAL_SRC_FILES:= test_marshalling.cpp
LOCAL_SHARED_LIBRARIES := libaudioclient libaudioutils libbinder \
                          libcutils liblog libmedia libutils
LOCAL_STATIC_LIBRARIES := liboboe
LOCAL_MODULE := test_marshalling
include $(BUILD_NATIVE_TEST)
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ TEST(test_handle_tracker, oboe_handle_tracker) {
        EXPECT_EQ(&data, found);
        // should fail the second time
        found = tracker.remove(type, dataHandle);
        EXPECT_EQ(NULL, found);
        EXPECT_EQ(nullptr, found);
    }
}

+166 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

// Unit tests for Oboe Marshalling of RingBuffer information.

#include <stdlib.h>
#include <math.h>

#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <sys/mman.h>

#include <oboe/OboeDefinitions.h>
#include <binding/AudioEndpointParcelable.h>

using namespace android;
using namespace oboe;

// Test adding one value.
TEST(test_marshalling, oboe_one_read_write) {
    Parcel parcel;
    size_t pos = parcel.dataPosition();
    const int arbitraryValue = 235;
    parcel.writeInt32(arbitraryValue);
    parcel.setDataPosition(pos);
    int32_t y;
    parcel.readInt32(&y);
    EXPECT_EQ(arbitraryValue, y);
}

// Test SharedMemoryParcel.
TEST(test_marshalling, oboe_shared_memory) {
    SharedMemoryParcelable sharedMemoryA;
    SharedMemoryParcelable sharedMemoryB;
    const size_t memSizeBytes = 840;
    int fd = ashmem_create_region("TestMarshalling", memSizeBytes);
    ASSERT_LE(0, fd);
    sharedMemoryA.setup(fd, memSizeBytes);
    void *region1;
    EXPECT_EQ(OBOE_OK, sharedMemoryA.resolve(0, 16, &region1)); // fits in region
    EXPECT_NE(OBOE_OK, sharedMemoryA.resolve(-2, 16, &region1)); // offset is negative
    EXPECT_NE(OBOE_OK, sharedMemoryA.resolve(0, memSizeBytes + 8, &region1)); // size too big
    EXPECT_NE(OBOE_OK, sharedMemoryA.resolve(memSizeBytes - 8, 16, &region1)); // goes past the end
    int32_t *buffer1 = (int32_t *)region1;
    buffer1[0] = 98735; // arbitrary value

    Parcel parcel;
    size_t pos = parcel.dataPosition();
    sharedMemoryA.writeToParcel(&parcel);

    parcel.setDataPosition(pos);
    sharedMemoryB.readFromParcel(&parcel);
    EXPECT_EQ(sharedMemoryA.getSizeInBytes(), sharedMemoryB.getSizeInBytes());

    // should see same value at two different addresses
    void *region2;
    EXPECT_EQ(OBOE_OK, sharedMemoryB.resolve(0, 16, &region2));
    int32_t *buffer2 = (int32_t *)region2;
    EXPECT_NE(buffer1, buffer2);
    EXPECT_EQ(buffer1[0], buffer2[0]);
}

// Test SharedRegionParcel.
TEST(test_marshalling, oboe_shared_region) {
    SharedMemoryParcelable sharedMemories[2];
    SharedRegionParcelable sharedRegionA;
    SharedRegionParcelable sharedRegionB;
    const size_t memSizeBytes = 840;
    int fd = ashmem_create_region("TestMarshalling", memSizeBytes);
    ASSERT_LE(0, fd);
    sharedMemories[0].setup(fd, memSizeBytes);
    int32_t regionOffset1 = 32;
    int32_t regionSize1 = 16;
    sharedRegionA.setup(0, regionOffset1, regionSize1);

    void *region1;
    EXPECT_EQ(OBOE_OK, sharedRegionA.resolve(sharedMemories, &region1));
    int32_t *buffer1 = (int32_t *)region1;
    buffer1[0] = 336677; // arbitrary value

    Parcel parcel;
    size_t pos = parcel.dataPosition();
    sharedRegionA.writeToParcel(&parcel);

    parcel.setDataPosition(pos);
    sharedRegionB.readFromParcel(&parcel);

    // should see same value
    void *region2;
    EXPECT_EQ(OBOE_OK, sharedRegionB.resolve(sharedMemories, &region2));
    int32_t *buffer2 = (int32_t *)region2;
    EXPECT_EQ(buffer1[0], buffer2[0]);
}

// Test RingBufferParcelable.
TEST(test_marshalling, oboe_ring_buffer_parcelable) {
    SharedMemoryParcelable sharedMemories[2];
    RingBufferParcelable ringBufferA;
    RingBufferParcelable ringBufferB;

    const size_t bytesPerFrame = 8;
    const size_t framesPerBurst = 32;
    const size_t dataSizeBytes = 2048;
    const int32_t counterSizeBytes = sizeof(int64_t);
    const size_t memSizeBytes = dataSizeBytes + (2 * counterSizeBytes);

    int fd = ashmem_create_region("TestMarshalling", memSizeBytes);
    ASSERT_LE(0, fd);
    sharedMemories[0].setup(fd, memSizeBytes);

    int32_t sharedMemoryIndex = 0;
    // arrange indices and data in the shared memory
    int32_t readOffset = 0;
    int32_t writeOffset = readOffset + counterSizeBytes;
    int32_t dataOffset = writeOffset + counterSizeBytes;
    ringBufferA.setupMemory(sharedMemoryIndex, dataOffset, dataSizeBytes,
        readOffset, writeOffset, counterSizeBytes);
    ringBufferA.setFramesPerBurst(framesPerBurst);
    ringBufferA.setBytesPerFrame(bytesPerFrame);
    ringBufferA.setCapacityInFrames(dataSizeBytes / bytesPerFrame);

    // setup A
    RingBufferDescriptor descriptorA;
    EXPECT_EQ(OBOE_OK, ringBufferA.resolve(sharedMemories, &descriptorA));
    descriptorA.dataAddress[0] = 95;
    descriptorA.dataAddress[1] = 57;
    descriptorA.readCounterAddress[0] = 17;
    descriptorA.writeCounterAddress[0] = 39;

    // write A to parcel
    Parcel parcel;
    size_t pos = parcel.dataPosition();
    ringBufferA.writeToParcel(&parcel);

    // read B from parcel
    parcel.setDataPosition(pos);
    ringBufferB.readFromParcel(&parcel);

    RingBufferDescriptor descriptorB;
    EXPECT_EQ(OBOE_OK, ringBufferB.resolve(sharedMemories, &descriptorB));

    // A and B should match
    EXPECT_EQ(descriptorA.dataAddress[0], descriptorB.dataAddress[0]);
    EXPECT_EQ(descriptorA.dataAddress[1], descriptorB.dataAddress[1]);
    EXPECT_EQ(descriptorA.readCounterAddress[0], descriptorB.readCounterAddress[0]);
    EXPECT_EQ(descriptorA.writeCounterAddress[0], descriptorB.writeCounterAddress[0]);

    EXPECT_EQ(ringBufferA.getFramesPerBurst(), ringBufferB.getFramesPerBurst());
    EXPECT_EQ(ringBufferA.getBytesPerFrame(), ringBufferB.getBytesPerFrame());
    EXPECT_EQ(ringBufferA.getCapacityInFrames(), ringBufferB.getCapacityInFrames());
}
+94 −73
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ TEST(test_oboe_api, oboe_stream_builder) {
    const oboe_sample_rate_t requestedSampleRate1 = 48000;
    const oboe_sample_rate_t requestedSampleRate2 = 44100;
    const int32_t requestedSamplesPerFrame = 2;
    const oboe_audio_format_t requestedDataFormat = OBOE_AUDIO_DATATYPE_INT16;
    const oboe_audio_format_t requestedDataFormat = OBOE_AUDIO_FORMAT_PCM16;

    oboe_sample_rate_t sampleRate = 0;
    int32_t samplesPerFrame = 0;
@@ -94,7 +94,6 @@ TEST(test_oboe_api, oboe_stream_builder) {
    EXPECT_EQ(OBOE_ERROR_INVALID_HANDLE, OboeStreamBuilder_getSampleRate(oboeBuilder2, &sampleRate));
}


// Test creating a default stream with everything unspecified.
TEST(test_oboe_api, oboe_stream_unspecified) {
    OboeStreamBuilder oboeBuilder;
@@ -114,18 +113,17 @@ TEST(test_oboe_api, oboe_stream_unspecified) {
}

// Test Writing to an OboeStream
TEST(test_oboe_api, oboe_stream) {
void runtest_oboe_stream(oboe_sharing_mode_t requestedSharingMode) {
    const oboe_sample_rate_t requestedSampleRate = 48000;
    const oboe_sample_rate_t requestedSamplesPerFrame = 2;
    const oboe_audio_format_t requestedDataFormat = OBOE_AUDIO_DATATYPE_INT16;
    //const oboe_sharing_mode_t requestedSharingMode = OBOE_SHARING_MODE_EXCLUSIVE; // MMAP NOIRQ
    const oboe_sharing_mode_t requestedSharingMode = OBOE_SHARING_MODE_LEGACY; // AudioTrack
    const oboe_audio_format_t requestedDataFormat = OBOE_AUDIO_FORMAT_PCM16;

    oboe_sample_rate_t actualSampleRate = -1;
    int32_t actualSamplesPerFrame = -1;
    oboe_audio_format_t actualDataFormat = OBOE_AUDIO_FORMAT_PCM824;
    oboe_audio_format_t actualDataFormat = OBOE_AUDIO_FORMAT_INVALID;
    oboe_sharing_mode_t actualSharingMode;
    oboe_size_frames_t framesPerBurst = -1;
    int writeLoops = 0;

    oboe_size_frames_t framesWritten = 0;
    oboe_size_frames_t framesPrimed = 0;
@@ -162,22 +160,30 @@ TEST(test_oboe_api, oboe_stream) {

    // Check to see what kind of stream we actually got.
    EXPECT_EQ(OBOE_OK, OboeStream_getSampleRate(oboeStream, &actualSampleRate));
    EXPECT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000);  // TODO what is range?
    ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000);  // TODO what is range?

    EXPECT_EQ(OBOE_OK, OboeStream_getSamplesPerFrame(oboeStream, &actualSamplesPerFrame));
    EXPECT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
    ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?

    EXPECT_EQ(OBOE_OK, OboeStream_getSharingMode(oboeStream, &actualSharingMode));
    EXPECT_TRUE(actualSharingMode == OBOE_SHARING_MODE_EXCLUSIVE
    ASSERT_TRUE(actualSharingMode == OBOE_SHARING_MODE_EXCLUSIVE
                || actualSharingMode == OBOE_SHARING_MODE_LEGACY);

    EXPECT_EQ(OBOE_OK, OboeStream_getFormat(oboeStream, &actualDataFormat));
    EXPECT_NE(OBOE_AUDIO_FORMAT_INVALID, actualDataFormat);

    EXPECT_EQ(OBOE_OK, OboeStream_getFramesPerBurst(oboeStream, &framesPerBurst));
    EXPECT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
    ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?

    // Allocate a buffer for the audio data.
    int16_t *data = new int16_t[framesPerBurst * actualSamplesPerFrame];
    ASSERT_TRUE(NULL != data);

    // TODO handle possibility of other data formats
    ASSERT_TRUE(actualDataFormat == OBOE_AUDIO_FORMAT_PCM16);
    size_t dataSizeSamples = framesPerBurst * actualSamplesPerFrame;
    int16_t *data = new int16_t[dataSizeSamples];
    ASSERT_TRUE(nullptr != data);
    memset(data, 0, sizeof(int16_t) * dataSizeSamples);

    // Prime the buffer.
    timeoutNanos = 0;
    do {
        framesWritten = OboeStream_write(oboeStream, data, framesPerBurst, timeoutNanos);
@@ -188,6 +194,9 @@ TEST(test_oboe_api, oboe_stream) {
    } while (framesWritten > 0);
    ASSERT_TRUE(framesTotal > 0);

    // Start/write/pause more than once to see if it fails after the first time.
    // Write some data and measure the rate to see if the timing is OK.
    for (int numLoops = 0; numLoops < 2; numLoops++) {
        // Start and wait for server to respond.
        ASSERT_EQ(OBOE_OK, OboeStream_requestStart(oboeStream));
        ASSERT_EQ(OBOE_OK, OboeStream_waitForStateChange(oboeStream,
@@ -197,8 +206,8 @@ TEST(test_oboe_api, oboe_stream) {
        EXPECT_EQ(OBOE_STREAM_STATE_STARTED, state);

        // Write some data while we are running. Read counter should be advancing.
    int loops = 1 * actualSampleRate / framesPerBurst; // 1 second
    ASSERT_LT(2, loops); // detect absurdly high framesPerBurst
        writeLoops = 1 * actualSampleRate / framesPerBurst; // 1 second
        ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
        timeoutNanos = 10 * OBOE_NANOS_PER_SECOND * framesPerBurst / actualSampleRate; // bursts
        framesWritten = 1;
        ASSERT_EQ(OBOE_OK, OboeStream_getFramesRead(oboeStream, &oboeFramesRead));
@@ -221,7 +230,7 @@ TEST(test_oboe_api, oboe_stream) {
                    oboeFramesRead1 = oboeFramesRead;
                }
            }
    } while (framesWritten > 0 && loops-- > 0);
        } while (framesWritten > 0 && writeLoops-- > 0);

        EXPECT_EQ(OBOE_OK, OboeStream_getFramesRead(oboeStream, &oboeFramesRead2));
        oboe_nanoseconds_t endTime = Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC);
@@ -245,6 +254,7 @@ TEST(test_oboe_api, oboe_stream) {
                                                &state,
                                                DEFAULT_STATE_TIMEOUT));
        EXPECT_EQ(OBOE_STREAM_STATE_PAUSED, state);
    }

    // Make sure the read counter is not advancing when we are paused.
    ASSERT_EQ(OBOE_OK, OboeStream_getFramesRead(oboeStream, &oboeFramesRead));
@@ -255,13 +265,14 @@ TEST(test_oboe_api, oboe_stream) {
    ASSERT_EQ(OBOE_OK, OboeStream_getFramesRead(oboeStream, &oboeFramesRead2));
    EXPECT_EQ(oboeFramesRead, oboeFramesRead2);

    // Fill up the buffer.
    // ------------------- TEST FLUSH -----------------
    // Prime the buffer.
    timeoutNanos = 0;
    loops = 100;
    writeLoops = 100;
    do {
        framesWritten = OboeStream_write(oboeStream, data, framesPerBurst, timeoutNanos);
        framesTotal += framesWritten;
    } while (framesWritten > 0 && loops-- > 0);
    } while (framesWritten > 0 && writeLoops-- > 0);
    EXPECT_EQ(0, framesWritten);

    // Flush and wait for server to respond.
@@ -286,6 +297,16 @@ TEST(test_oboe_api, oboe_stream) {
    EXPECT_EQ(OBOE_OK, OboeStream_close(oboeStream));
}

// Test Writing to an OboeStream using LEGACY sharing mode.
TEST(test_oboe_api, oboe_stream_legacy) {
    runtest_oboe_stream(OBOE_SHARING_MODE_LEGACY);
}

// Test Writing to an OboeStream using EXCLUSIVE sharing mode.
TEST(test_oboe_api, oboe_stream_exclusive) {
    runtest_oboe_stream(OBOE_SHARING_MODE_EXCLUSIVE);
}

#define OBOE_THREAD_ANSWER          1826375
#define OBOE_THREAD_DURATION_MSEC       500