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

Commit 8dff4ae2 authored by Phil Burk's avatar Phil Burk Committed by Android (Google) Code Review
Browse files

Merge changes Ic24aca3e,If8f6f6f1

* changes:
  aaudio: prevent onAudioDeviceUpdate past close
  aaudio: fix crash from callbacks during close
parents f1a36052 58f5ce14
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1037,6 +1037,11 @@ AAUDIO_API aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* buil
 * but still allow queries to the stream to occur from other threads. This often
 * happens if you are monitoring stream progress from a UI thread.
 *
 * NOTE: This function is only fully implemented for MMAP streams,
 * which are low latency streams supported by some devices.
 * On other "Legacy" streams some audio resources will still be in use
 * and some callbacks may still be in process after this call.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return {@link #AAUDIO_OK} or a negative error.
 */
+8 −2
Original line number Diff line number Diff line
@@ -14,8 +14,6 @@
 * limitations under the License.
 */

#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
                          : "AudioStreamInternalCapture_Client")
//#define LOG_NDEBUG 0
#include <utils/Log.h>

@@ -29,6 +27,14 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <utils/Trace.h>

// We do this after the #includes because if a header uses ALOG.
// it would fail on the reference to mInService.
#undef LOG_TAG
// This file is used in both client and server processes.
// This is needed to make sense of the logs more easily.
#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
                          : "AudioStreamInternalCapture_Client")

using android::WrappingBuffer;

using namespace aaudio;
+8 −2
Original line number Diff line number Diff line
@@ -14,8 +14,6 @@
 * limitations under the License.
 */

#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
                          : "AudioStreamInternalPlay_Client")
//#define LOG_NDEBUG 0
#include <utils/Log.h>

@@ -26,6 +24,14 @@
#include "client/AudioStreamInternalPlay.h"
#include "utility/AudioClock.h"

// We do this after the #includes because if a header uses ALOG.
// it would fail on the reference to mInService.
#undef LOG_TAG
// This file is used in both client and server processes.
// This is needed to make sense of the logs more easily.
#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
                            : "AudioStreamInternalPlay_Client")

using android::WrappingBuffer;

using namespace aaudio;
+4 −5
Original line number Diff line number Diff line
@@ -255,17 +255,16 @@ AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream) {
    if (audioStream != nullptr) {
        aaudio_stream_id_t id = audioStream->getId();
        ALOGD("%s(s#%u) called ---------------", __func__, id);
        result = audioStream->safeRelease();
        // safeRelease will only fail if called illegally, for example, from a callback.
        result = audioStream->safeReleaseClose();
        // safeReleaseClose will only fail if called illegally, for example, from a callback.
        // That would result in deleting an active stream, which would cause a crash.
        if (result != AAUDIO_OK) {
            ALOGW("%s(s#%u) failed. Close it from another thread.",
                  __func__, id);
        } else {
            audioStream->unregisterPlayerBase();
             // Mark CLOSED to keep destructors from asserting.
            audioStream->closeFinal();
            delete audioStream;
            // Allow the stream to be deleted.
            AudioStreamBuilder::stopUsingStream(audioStream);
        }
        ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
    }
+48 −18
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ static aaudio_stream_id_t AAudio_getNextStreamId() {
}

AudioStream::AudioStream()
        : mPlayerBase(new MyPlayerBase(this))
        : mPlayerBase(new MyPlayerBase())
        , mStreamId(AAudio_getNextStreamId())
        {
    // mThread is a pthread_t of unknown size so we need memset.
@@ -48,6 +48,10 @@ AudioStream::AudioStream()
}

AudioStream::~AudioStream() {
    // Please preserve this log because there have been several bugs related to
    // AudioStream deletion and late callbacks.
    ALOGD("%s(s#%u) mPlayerBase strongCount = %d",
            __func__, getId(), mPlayerBase->getStrongCount());
    // If the stream is deleted when OPEN or in use then audio resources will leak.
    // This would indicate an internal error. So we want to find this ASAP.
    LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
@@ -55,8 +59,6 @@ AudioStream::~AudioStream() {
                          || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
                        "~AudioStream() - still in use, state = %s",
                        AudioGlobal_convertStreamStateToText(getState()));

    mPlayerBase->clearParentReference(); // remove reference to this AudioStream
}

aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
@@ -301,18 +303,29 @@ aaudio_result_t AudioStream::safeStop() {
}

aaudio_result_t AudioStream::safeRelease() {
    // This get temporarily unlocked in the release() when joining callback threads.
    // This get temporarily unlocked in the MMAP release() when joining callback threads.
    std::lock_guard<std::mutex> lock(mStreamLock);
    if (collidesWithCallback()) {
        ALOGE("%s cannot be called from a callback!", __func__);
        return AAUDIO_ERROR_INVALID_STATE;
    }
    if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
    if (getState() == AAUDIO_STREAM_STATE_CLOSING) { // already released?
        return AAUDIO_OK;
    }
    return release_l();
}

aaudio_result_t AudioStream::safeReleaseClose() {
    // This get temporarily unlocked in the MMAP release() when joining callback threads.
    std::lock_guard<std::mutex> lock(mStreamLock);
    if (collidesWithCallback()) {
        ALOGE("%s cannot be called from a callback!", __func__);
        return AAUDIO_ERROR_INVALID_STATE;
    }
    releaseCloseFinal();
    return AAUDIO_OK;
}

void AudioStream::setState(aaudio_stream_state_t state) {
    ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
    if (state == mState) {
@@ -523,11 +536,18 @@ bool AudioStream::collidesWithCallback() const {
}

#if AAUDIO_USE_VOLUME_SHAPER
android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
        const android::media::VolumeShaper::Configuration& configuration __unused,
        const android::media::VolumeShaper::Operation& operation __unused) {
    ALOGW("applyVolumeShaper() is not supported");
    return android::media::VolumeShaper::Status::ok();
::android::binder::Status AudioStream::MyPlayerBase::applyVolumeShaper(
        const ::android::media::VolumeShaper::Configuration& configuration,
        const ::android::media::VolumeShaper::Operation& operation) {
    android::sp<AudioStream> audioStream;
    {
        std::lock_guard<std::mutex> lock(mParentLock);
        audioStream = mParent.promote();
    }
    if (audioStream) {
        return audioStream->applyVolumeShaper(configuration, operation);
    }
    return android::NO_ERROR;
}
#endif

@@ -537,26 +557,36 @@ void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
    doSetVolume(); // apply this change
}

AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
}

AudioStream::MyPlayerBase::~MyPlayerBase() {
}

void AudioStream::MyPlayerBase::registerWithAudioManager() {
void AudioStream::MyPlayerBase::registerWithAudioManager(const android::sp<AudioStream>& parent) {
    std::lock_guard<std::mutex> lock(mParentLock);
    mParent = parent;
    if (!mRegistered) {
        init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(mParent->getUsage()));
        init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(parent->getUsage()));
        mRegistered = true;
    }
}

void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
    std::lock_guard<std::mutex> lock(mParentLock);
    if (mRegistered) {
        baseDestroy();
        mRegistered = false;
    }
}

android::status_t AudioStream::MyPlayerBase::playerSetVolume() {
    android::sp<AudioStream> audioStream;
    {
        std::lock_guard<std::mutex> lock(mParentLock);
        audioStream = mParent.promote();
    }
    if (audioStream) {
        // No pan and only left volume is taken into account from IPLayer interface
        audioStream->setDuckAndMuteVolume(mVolumeMultiplierL  /* * mPanMultiplierL */);
    }
    return android::NO_ERROR;
}

void AudioStream::MyPlayerBase::destroy() {
    unregisterWithAudioManager();
}
Loading