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

Commit fe0fcdc1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "fix-b-373872271-drain-notif-3" into main

* changes:
  libaudiohal@aidl: Support clip transition reporting
  Add OWNERS for the audioparameterparser service
parents d03ff96e 026c2a54
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,5 +33,6 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
               media/libaudioclient/tests/
               media/libaudiohal/tests/
               media/libmediatranscoding/
               services/audioparameterparser/
               services/camera/virtualcamera/
               services/mediatranscoding/
+8 −0
Original line number Diff line number Diff line
@@ -258,6 +258,14 @@ status_t AudioPlayback::onProcess(bool testSeek) {
        return INVALID_OPERATION;
}

void AudioPlayback::pause() {
    mTrack->pause();
}

void AudioPlayback::resume() {
    mTrack->start();
}

void AudioPlayback::stop() {
    {
        std::lock_guard lock(mMutex);
+2 −0
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ class AudioPlayback : public AudioTrack::IAudioTrackCallback {
    status_t waitForConsumption(bool testSeek = false) EXCLUDES(mMutex);
    status_t fillBuffer();
    status_t onProcess(bool testSeek = false);
    void pause();
    void resume();
    void stop() EXCLUDES(mMutex);
    bool waitForStreamEnd();

+79 −13
Original line number Diff line number Diff line
@@ -180,7 +180,29 @@ TEST(AudioTrackTest, TestAudioCbNotifier) {
    ap->stop();
}

TEST(AudioTrackTest, OffloadCompletion) {
class AudioTrackOffloadTest : public ::testing::Test {
  protected:
    void TearDown() override {
        if (!IsSkipped()) {
            // Let the offload AF stream to exit to avoid interfering with other tests.
            std::this_thread::sleep_for(std::chrono::milliseconds(750));
        }
    }
    bool halSupportsClipTransition() const;
    void testPlayback(bool testDrainPause, sp<AudioPlayback>* outPlayback = nullptr);
};

bool AudioTrackOffloadTest::halSupportsClipTransition() const {
    // TODO: Check for the HAL type (HIDL/AIDL) and version. HIDL and AIDL V4 should also
    //       support this.
    AudioParameter param;
    param.addKey(String8(AudioParameter::keyClipTransitionSupport));
    String8 values = AudioSystem::getParameters(AUDIO_IO_HANDLE_NONE, param.keysToString());
    LOG(DEBUG) << __func__ << ": values \"" << values << "\"";
    return !values.empty();
}

void AudioTrackOffloadTest::testPlayback(bool testDrainPause, sp<AudioPlayback>* outPlayback) {
    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
    info.sample_rate = 48000;
    info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
@@ -189,14 +211,6 @@ TEST(AudioTrackTest, OffloadCompletion) {
    info.bit_rate = 236256;
    info.duration_us = 120 * 1000000;  // 120 sec to ensure the offloading choice

    audio_config_base_t config = {/* .sample_rate = */ info.sample_rate,
                                  /* .channel_mask = */ info.channel_mask,
                                  /* .format = */ AUDIO_FORMAT_PCM_16_BIT};
    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
    attributes.usage = AUDIO_USAGE_MEDIA;
    attributes.flags = AUDIO_FLAG_NONE;

    if (AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
        GTEST_SKIP() << "offload playback is not supported for "
                     << audio_format_to_string(info.format);
@@ -207,13 +221,65 @@ TEST(AudioTrackTest, OffloadCompletion) {
    ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/sine960hz_48000_3s.ape"))
            << "unable to open the media file";
    ASSERT_EQ(OK, ap->create()) << "track creation failed";
    EXPECT_EQ(OK, ap->start()) << "audio track start failed";
    ASSERT_EQ(OK, ap->start()) << "audio track start failed";
    LOG(INFO) << __func__ << ": Started track";
    EXPECT_EQ(OK, ap->onProcess());
    LOG(INFO) << __func__ << ": onProcess done";
    if (!outPlayback) {
        ap->stop();
    LOG(INFO) << __func__ << ": Stopped track, waiting for stream end";
        LOG(INFO) << __func__ << ": Stopped track";
    }
    if (testDrainPause) {
        // Wait for draining to start, no event for this.
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        LOG(INFO) << __func__ << ": Pausing drain";
        ap->pause();
        LOG(INFO) << __func__ << ": Resuming drain";
        ap->resume();
    }
    if (!outPlayback) {
        LOG(INFO) << __func__ << ": Waiting for stream end";
        EXPECT_TRUE(ap->waitForStreamEnd()) << "Did not receive onStreamEnd";
    } else {
        *outPlayback = std::move(ap);
    }
}

TEST_F(AudioTrackOffloadTest, Completion) {
    testPlayback(false /*testDrainPause*/);
}

TEST_F(AudioTrackOffloadTest, DrainPause) {
    if (!halSupportsClipTransition()) {
        // TODO: In theory, this should also work w/o having the proper clip transition
        //       support, but as a fact it was not. Need to figure out why.
        GTEST_SKIP() << "Proper indication of clip transition is not supported";
    }
    testPlayback(true /*testDrainPause*/);
}

// Similar to AudioTrackOffloadTest.testMultipleAudioTrackOffloadPreemption
TEST_F(AudioTrackOffloadTest, ClipPreemption) {
    if (!halSupportsClipTransition()) {
        GTEST_SKIP() << "Proper indication of clip transition is not supported";
    }
    sp<AudioPlayback> trackOne, trackTwo;
    {
        SCOPED_TRACE("track 1");
        LOG(INFO) << __func__ << ": Creating and starting track 1";
        ASSERT_NO_FATAL_FAILURE(testPlayback(false /*testDrainPause*/, &trackOne));
    }
    {
        SCOPED_TRACE("track 2");
        // Wait for track 1 to start playing, no event for this.
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        LOG(INFO) << __func__ << ": Creating and starting track 2";
        ASSERT_NO_FATAL_FAILURE(testPlayback(false /*testDrainPause*/, &trackTwo));
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        trackTwo->stop();
    }
    LOG(INFO) << __func__ << ": Waiting for stream end on track 2";
    EXPECT_TRUE(trackTwo->waitForStreamEnd()) << "Did not receive onStreamEnd on track 2";
}

class AudioTrackCreateTest
+18 −2
Original line number Diff line number Diff line
@@ -94,6 +94,10 @@ namespace android {

namespace {

static constexpr int32_t kAidlVersion1 = 1;
static constexpr int32_t kAidlVersion2 = 2;
static constexpr int32_t kAidlVersion3 = 3;

// Note: these converters are for types defined in different AIDL files. Although these
// AIDL files are copies of each other, however formally these are different types
// thus we don't use a conversion via a parcelable.
@@ -175,6 +179,17 @@ status_t DeviceHalAidl::initCheck() {
    TIME_CHECK();
    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
    std::lock_guard l(mLock);
    int32_t aidlVersion = 0;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getInterfaceVersion(&aidlVersion)));
    if (aidlVersion > kAidlVersion3) {
        mHasClipTransitionSupport = true;
    } else {
        AudioParameter parameterKeys;
        parameterKeys.addKey(String8(AudioParameter::keyClipTransitionSupport));
        String8 values;
        auto status = parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, &values);
        mHasClipTransitionSupport = status == OK && !values.empty();
    }
    return mMapper.initialize();
}

@@ -545,7 +560,7 @@ status_t DeviceHalAidl::openOutputStream(
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
    }
    StreamContextAidl context(ret.desc, isOffload, aidlHandle);
    StreamContextAidl context(ret.desc, isOffload, aidlHandle, mHasClipTransitionSupport);
    if (!context.isValid()) {
        AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
                    ret.desc.toString().c_str());
@@ -627,7 +642,8 @@ status_t DeviceHalAidl::openInputStream(
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
    }
    StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
    StreamContextAidl context(
            ret.desc, false /*isAsynchronous*/, aidlHandle, mHasClipTransitionSupport);
    if (!context.isValid()) {
        AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
                    ret.desc.toString().c_str());
Loading