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

Commit 9350158d authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge "Update Soundpool callback interface" into tm-dev

parents 0a69364a 81fb57f5
Loading
Loading
Loading
Loading
+56 −38
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */


//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#include <utility>
#define LOG_TAG "SoundPool::Stream"
#define LOG_TAG "SoundPool::Stream"
#include <utils/Log.h>
#include <utils/Log.h>
#include <android/content/AttributionSourceState.h>
#include <android/content/AttributionSourceState.h>
@@ -309,13 +310,11 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
    }
    }
    if (mAudioTrack == nullptr) {
    if (mAudioTrack == nullptr) {
        // mToggle toggles each time a track is started on a given stream.
        // mToggle toggles each time a track is started on a given stream.
        // The toggle is concatenated with the Stream address and passed to AudioTrack
        // This enables the detection of callbacks received from the old
        // as callback user data. This enables the detection of callbacks received from the old
        // audio track while the new one is being started and avoids processing them with
        // audio track while the new one is being started and avoids processing them with
        // wrong audio audio buffer size  (mAudioBufferSize)
        // wrong audio audio buffer size  (mAudioBufferSize)
        auto toggle = mToggle ^ 1;
        auto toggle = mToggle ^ 1;
        // NOLINTNEXTLINE(performance-no-int-to-ptr)
        // NOLINTNEXTLINE(performance-no-int-to-ptr)
        void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle);
        audio_channel_mask_t soundChannelMask = sound->getChannelMask();
        audio_channel_mask_t soundChannelMask = sound->getChannelMask();
        // When sound contains a valid channel mask, use it as is.
        // When sound contains a valid channel mask, use it as is.
        // Otherwise, use stream count to calculate channel mask.
        // Otherwise, use stream count to calculate channel mask.
@@ -327,10 +326,11 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
        android::content::AttributionSourceState attributionSource;
        android::content::AttributionSourceState attributionSource;
        attributionSource.packageName = mStreamManager->getOpPackageName();
        attributionSource.packageName = mStreamManager->getOpPackageName();
        attributionSource.token = sp<BBinder>::make();
        attributionSource.token = sp<BBinder>::make();
        mCallback =  sp<StreamCallback>::make(this, toggle),
        // TODO b/182469354 make consistent with AudioRecord, add util for native source
        // TODO b/182469354 make consistent with AudioRecord, add util for native source
        mAudioTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
        mAudioTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
                channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
                channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
                staticCallback, userData,
                mCallback,
                0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
                0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
                AudioTrack::TRANSFER_DEFAULT,
                AudioTrack::TRANSFER_DEFAULT,
                nullptr /*offloadInfo*/, attributionSource,
                nullptr /*offloadInfo*/, attributionSource,
@@ -375,16 +375,55 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
    mStreamID = nextStreamID;  // prefer this to be the last, as it is an atomic sync point
    mStreamID = nextStreamID;  // prefer this to be the last, as it is an atomic sync point
}
}


/* static */
int Stream::getCorrespondingStreamID() {
void Stream::staticCallback(int event, void* user, void* info)
    std::lock_guard lock(mLock);
{
    return static_cast<int>(mAudioTrack ? mStreamID : getPairStream()->mStreamID);
    const auto userAsInt = (uintptr_t)user;
}
    // NOLINTNEXTLINE(performance-no-int-to-ptr)
size_t Stream::StreamCallback::onMoreData(const AudioTrack::Buffer&) {
    auto stream = reinterpret_cast<Stream*>(userAsInt & ~1);
    ALOGW("%s streamID %d Unexpected EVENT_MORE_DATA for static track",
    stream->callback(event, info, int(userAsInt & 1), 0 /* tries */);
            __func__, mStream->getCorrespondingStreamID());
    return 0;
}

void Stream::StreamCallback::onUnderrun() {
    ALOGW("%s streamID %d Unexpected EVENT_UNDERRUN for static track",
            __func__, mStream->getCorrespondingStreamID());
}
}


void Stream::callback(int event, void* info, int toggle, int tries)
void Stream::StreamCallback::onLoopEnd(int32_t) {
    ALOGV("%s streamID %d EVENT_LOOP_END", __func__, mStream->getCorrespondingStreamID());
}

void Stream::StreamCallback::onMarker(uint32_t) {
    ALOGW("%s streamID %d Unexpected EVENT_MARKER for static track",
            __func__, mStream->getCorrespondingStreamID());
}

void Stream::StreamCallback::onNewPos(uint32_t) {
    ALOGW("%s streamID %d Unexpected EVENT_NEW_POS for static track",
            __func__, mStream->getCorrespondingStreamID());
}

void Stream::StreamCallback::onBufferEnd() {
    mStream->onBufferEnd(mToggle, 0);
}

void Stream::StreamCallback::onNewIAudioTrack() {
    ALOGV("%s streamID %d NEW_IAUDIOTRACK", __func__, mStream->getCorrespondingStreamID());
}

void Stream::StreamCallback::onStreamEnd() {
    ALOGW("%s streamID %d Unexpected EVENT_STREAM_END for static track",
            __func__, mStream->getCorrespondingStreamID());
}

size_t Stream::StreamCallback::onCanWriteMoreData(const AudioTrack::Buffer&) {
    ALOGW("%s streamID %d Unexpected EVENT_CAN_WRITE_MORE_DATA for static track",
            __func__, mStream->getCorrespondingStreamID());
    return 0;
}

void Stream::onBufferEnd(int toggle, int tries)
{
{
    int32_t activeStreamIDToRestart = 0;
    int32_t activeStreamIDToRestart = 0;
    {
    {
@@ -400,7 +439,7 @@ void Stream::callback(int event, void* info, int toggle, int tries)
            if (tries < 3) {
            if (tries < 3) {
                lock.unlock();
                lock.unlock();
                ALOGV("%s streamID %d going to pair stream", __func__, (int)mStreamID);
                ALOGV("%s streamID %d going to pair stream", __func__, (int)mStreamID);
                getPairStream()->callback(event, info, toggle, tries + 1);
                getPairStream()->onBufferEnd(toggle, tries + 1);
            } else {
            } else {
                ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID);
                ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID);
            }
            }
@@ -410,32 +449,11 @@ void Stream::callback(int event, void* info, int toggle, int tries)
            ALOGD("%s streamID %d wrong toggle", __func__, (int)mStreamID);
            ALOGD("%s streamID %d wrong toggle", __func__, (int)mStreamID);
            return;
            return;
        }
        }
        switch (event) {
        case AudioTrack::EVENT_MORE_DATA:
            ALOGW("%s streamID %d Invalid EVENT_MORE_DATA for static track",
                    __func__, (int)mStreamID);
            break;
        case AudioTrack::EVENT_UNDERRUN:
            ALOGW("%s streamID %d Invalid EVENT_UNDERRUN for static track",
                    __func__, (int)mStreamID);
            break;
        case AudioTrack::EVENT_BUFFER_END:
        ALOGV("%s streamID %d EVENT_BUFFER_END", __func__, (int)mStreamID);
        ALOGV("%s streamID %d EVENT_BUFFER_END", __func__, (int)mStreamID);
        if (mState != IDLE) {
        if (mState != IDLE) {
            activeStreamIDToRestart = mStreamID;
            activeStreamIDToRestart = mStreamID;
            mStopTimeNs = systemTime();
            mStopTimeNs = systemTime();
        }
        }
            break;
        case AudioTrack::EVENT_LOOP_END:
            ALOGV("%s streamID %d EVENT_LOOP_END", __func__, (int)mStreamID);
            break;
        case AudioTrack::EVENT_NEW_IAUDIOTRACK:
            ALOGV("%s streamID %d NEW_IAUDIOTRACK", __func__, (int)mStreamID);
            break;
        default:
            ALOGW("%s streamID %d Invalid event %d", __func__, (int)mStreamID, event);
            break;
        }
    } // lock ends here.  This is on the callback thread, no need to be precise.
    } // lock ends here.  This is on the callback thread, no need to be precise.
    if (activeStreamIDToRestart > 0) {
    if (activeStreamIDToRestart > 0) {
        // Restart only if a particular streamID is still current and active.
        // Restart only if a particular streamID is still current and active.
+30 −3
Original line number Original line Diff line number Diff line
@@ -124,6 +124,35 @@ public:
    // This never changes.  See top of header.
    // This never changes.  See top of header.
    Stream* getPairStream() const;
    Stream* getPairStream() const;


    // Stream ID of ourselves, or the pair depending on who holds the AudioTrack
    int getCorrespondingStreamID();

protected:
    // AudioTrack callback interface implementation
    class StreamCallback : public AudioTrack::IAudioTrackCallback {
      public:
        StreamCallback(Stream * stream, bool toggle) : mStream(stream), mToggle(toggle) {}
        size_t onMoreData(const AudioTrack::Buffer& buffer) override;
        void onUnderrun() override;
        void onLoopEnd(int32_t loopsRemaining) override;
        void onMarker(uint32_t markerPosition) override;
        void onNewPos(uint32_t newPos) override;
        void onBufferEnd() override;
        void onNewIAudioTrack() override;
        void onStreamEnd() override;
        size_t onCanWriteMoreData(const AudioTrack::Buffer& buffer) override;

        // Holding a raw ptr is technically unsafe, but, Stream objects persist
        // through the lifetime of the StreamManager through the use of a
        // unique_ptr<Stream[]>. Ensuring lifetime will cause us to give up
        // locality as well as pay RefBase/sp performance cost, which we are
        // unwilling to do. Non-owning refs to unique_ptrs are idiomatically raw
        // ptrs, as below.
        Stream * const mStream;
        const bool mToggle;
    };

    sp<StreamCallback> mCallback;
private:
private:
    // garbage is used to release tracks and data outside of any lock.
    // garbage is used to release tracks and data outside of any lock.
    void play_l(const std::shared_ptr<Sound>& sound, int streamID,
    void play_l(const std::shared_ptr<Sound>& sound, int streamID,
@@ -133,9 +162,7 @@ private:
    void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
    void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);


    // For use with AudioTrack callback.
    // For use with AudioTrack callback.
    static void staticCallback(int event, void* user, void* info);
    void onBufferEnd(int toggle, int tries) NO_THREAD_SAFETY_ANALYSIS;
    void callback(int event, void* info, int toggle, int tries)
            NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock


    // StreamManager should be set on construction and not changed.
    // StreamManager should be set on construction and not changed.
    // release mLock before calling into StreamManager
    // release mLock before calling into StreamManager