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

Commit c3390881 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "aaudio: lock transport methods" into rvc-dev am: 3bd241dc am:...

Merge "aaudio: lock transport methods" into rvc-dev am: 3bd241dc am: 28ca11af am: eb53cd9c am: 096955e4

Change-Id: I530b8ff667af1d9f561db075f4b5a40540089abb
parents 19f9dde6 096955e4
Loading
Loading
Loading
Loading
+30 −83
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
#include <sstream>

#include <aaudio/AAudio.h>
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/ServiceUtilities.h>
#include <utils/String16.h>

@@ -162,28 +161,6 @@ aaudio_handle_t AAudioService::openStream(const aaudio::AAudioStreamRequest &req
    }
}

// If a close request is pending then close the stream
bool AAudioService::releaseStream(const sp<AAudioServiceStreamBase> &serviceStream) {
    bool closed = false;
    // decrementAndRemoveStreamByHandle() uses a lock so that if there are two simultaneous closes
    // then only one will get the pointer and do the close.
    sp<AAudioServiceStreamBase> foundStream = mStreamTracker.decrementAndRemoveStreamByHandle(
            serviceStream->getHandle());
    if (foundStream.get() != nullptr) {
        foundStream->close();
        pid_t pid = foundStream->getOwnerProcessId();
        AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
        closed = true;
    }
    return closed;
}

aaudio_result_t AAudioService::checkForPendingClose(
        const sp<AAudioServiceStreamBase> &serviceStream,
        aaudio_result_t defaultResult) {
    return releaseStream(serviceStream) ? AAUDIO_ERROR_INVALID_STATE : defaultResult;
}

aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
    // Check permission and ownership first.
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
@@ -195,17 +172,20 @@ aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
}

aaudio_result_t AAudioService::closeStream(sp<AAudioServiceStreamBase> serviceStream) {
    // This is protected by a lock in AAudioClientTracker.
    // It is safe to unregister the same stream twice.
    pid_t pid = serviceStream->getOwnerProcessId();
    AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
    // This is protected by a lock in mStreamTracker.
    // It is safe to remove the same stream twice.
    mStreamTracker.removeStreamByHandle(serviceStream->getHandle());

    serviceStream->markCloseNeeded();
    (void) releaseStream(serviceStream);
    return AAUDIO_OK;
    return serviceStream->close();
}

sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
        aaudio_handle_t streamHandle) {
    sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandleAndIncrement(
    sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(
            streamHandle);
    if (serviceStream.get() != nullptr) {
        // Only allow owner or the aaudio service to access the stream.
@@ -218,8 +198,6 @@ sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
        if (!allowed) {
            ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
                  callingUserId, streamHandle, ownerUserId);
            // We incremented the reference count so we must check if it needs to be closed.
            checkForPendingClose(serviceStream, AAUDIO_OK);
            serviceStream.clear();
        }
    }
@@ -234,96 +212,66 @@ aaudio_result_t AAudioService::getStreamDescription(
        ALOGE("getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }

    aaudio_result_t result = serviceStream->getDescription(parcelable);
    // parcelable.dump();
    return checkForPendingClose(serviceStream, result);
    return serviceStream->getDescription(parcelable);
}

aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("startStream(), illegal stream handle = 0x%0x", streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }

    aaudio_result_t result = serviceStream->start();
    return checkForPendingClose(serviceStream, result);
    return serviceStream->start();
}

aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("pauseStream(), illegal stream handle = 0x%0x", streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    aaudio_result_t result = serviceStream->pause();
    return checkForPendingClose(serviceStream, result);
    return serviceStream->pause();
}

aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("stopStream(), illegal stream handle = 0x%0x", streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    aaudio_result_t result = serviceStream->stop();
    return checkForPendingClose(serviceStream, result);
    return serviceStream->stop();
}

aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("flushStream(), illegal stream handle = 0x%0x", streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    aaudio_result_t result = serviceStream->flush();
    return checkForPendingClose(serviceStream, result);
    return serviceStream->flush();
}

aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
                                                   pid_t clientThreadId,
                                                   int64_t periodNanoseconds) {
    aaudio_result_t result = AAUDIO_OK;
                                                   int64_t /* periodNanoseconds */) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    if (serviceStream->getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
        ALOGE("AAudioService::registerAudioThread(), thread already registered");
        result = AAUDIO_ERROR_INVALID_STATE;
    } else {
        const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
    int32_t priority = isCallerInService()
        ? kRealTimeAudioPriorityService : kRealTimeAudioPriorityClient;
        serviceStream->setRegisteredThread(clientThreadId);
        int err = android::requestPriority(ownerPid, clientThreadId,
                                           priority, true /* isForApp */);
        if (err != 0) {
            ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
                  clientThreadId, errno, priority);
            result = AAUDIO_ERROR_INTERNAL;
        }
    }
    return checkForPendingClose(serviceStream, result);
    return serviceStream->registerAudioThread(clientThreadId, priority);
}

aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
                                                     pid_t clientThreadId) {
    aaudio_result_t result = AAUDIO_OK;
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    if (serviceStream->getRegisteredThread() != clientThreadId) {
        ALOGE("%s(), wrong thread", __func__);
        result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    } else {
        serviceStream->setRegisteredThread(0);
    }
    return checkForPendingClose(serviceStream, result);
    return serviceStream->unregisterAudioThread(clientThreadId);
}

aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
@@ -332,22 +280,20 @@ aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
                                           audio_port_handle_t *clientHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    aaudio_result_t result = serviceStream->startClient(client, attr, clientHandle);
    return checkForPendingClose(serviceStream, result);
    return serviceStream->startClient(client, attr, clientHandle);
}

aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
                                          audio_port_handle_t portHandle) {
    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    aaudio_result_t result = serviceStream->stopClient(portHandle);
    return checkForPendingClose(serviceStream, result);
    return serviceStream->stopClient(portHandle);
}

// This is only called internally when AudioFlinger wants to tear down a stream.
@@ -355,12 +301,13 @@ aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
    ALOGD("%s(%d) called", __func__, portHandle);
    sp<AAudioServiceStreamBase> serviceStream =
            mStreamTracker.findStreamByPortHandleAndIncrement(portHandle);
            mStreamTracker.findStreamByPortHandle(portHandle);
    if (serviceStream.get() == nullptr) {
        ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
        return AAUDIO_ERROR_INVALID_HANDLE;
    }
    // This is protected by a lock and will just return if already stopped.
    aaudio_result_t result = serviceStream->stop();
    serviceStream->disconnect();
    return checkForPendingClose(serviceStream, result);
    return result;
}
+0 −5
Original line number Diff line number Diff line
@@ -114,11 +114,6 @@ private:
    sp<aaudio::AAudioServiceStreamBase> convertHandleToServiceStream(
            aaudio::aaudio_handle_t streamHandle);

    bool releaseStream(const sp<aaudio::AAudioServiceStreamBase> &serviceStream);

    aaudio_result_t checkForPendingClose(const sp<aaudio::AAudioServiceStreamBase> &serviceStream,
                                         aaudio_result_t defaultResult);

    android::AudioClient            mAudioClient;

    aaudio::AAudioStreamTracker     mStreamTracker;
+5 −3
Original line number Diff line number Diff line
@@ -90,14 +90,16 @@ bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
std::vector<android::sp<AAudioServiceStreamBase>>
        AAudioServiceEndpoint::disconnectRegisteredStreams() {
    std::vector<android::sp<AAudioServiceStreamBase>> streamsDisconnected;
    {
        std::lock_guard<std::mutex> lock(mLockStreams);
        mRegisteredStreams.swap(streamsDisconnected);
    }
    mConnected.store(false);
    for (const auto &stream : mRegisteredStreams) {
    for (const auto &stream : streamsDisconnected) {
        ALOGD("%s() - stop and disconnect port %d", __func__, stream->getPortHandle());
        stream->stop();
        stream->disconnect();
    }
    mRegisteredStreams.swap(streamsDisconnected);
    return streamsDisconnected;
}

+1 −3
Original line number Diff line number Diff line
@@ -168,13 +168,11 @@ aaudio_result_t AAudioServiceEndpointShared::startStream(sp<AAudioServiceStreamB

aaudio_result_t AAudioServiceEndpointShared::stopStream(sp<AAudioServiceStreamBase> sharedStream,
                                                        audio_port_handle_t clientHandle) {
    // Don't lock here because the disconnectRegisteredStreams also uses the lock.

    // Ignore result.
    (void) getStreamInternal()->stopClient(clientHandle);

    if (--mRunningStreamCount == 0) { // atomic
        stopSharingThread();
        stopSharingThread(); // the sharing thread locks mLockStreams
        getStreamInternal()->requestStop();
    }
    return AAUDIO_OK;
+89 −12
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include <media/MediaMetricsItem.h>
#include <media/TypeConverter.h>
#include <mediautils/SchedulingPolicyService.h>

#include "binding/IAAudioService.h"
#include "binding/AAudioServiceMessage.h"
@@ -169,11 +170,16 @@ error:
}

aaudio_result_t AAudioServiceStreamBase::close() {
    std::lock_guard<std::mutex> lock(mLock);
    return close_l();
}

aaudio_result_t AAudioServiceStreamBase::close_l() {
    if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
        return AAUDIO_OK;
    }

    stop();
    stop_l();

    aaudio_result_t result = AAUDIO_OK;
    sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
@@ -185,7 +191,7 @@ aaudio_result_t AAudioServiceStreamBase::close() {
        endpointManager.closeEndpoint(endpoint);

        // AAudioService::closeStream() prevents two threads from closing at the same time.
        mServiceEndpoint.clear(); // endpoint will hold the pointer until this method returns.
        mServiceEndpoint.clear(); // endpoint will hold the pointer after this method returns.
    }

    {
@@ -219,9 +225,18 @@ aaudio_result_t AAudioServiceStreamBase::startDevice() {
 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
 */
aaudio_result_t AAudioServiceStreamBase::start() {
    std::lock_guard<std::mutex> lock(mLock);

    const int64_t beginNs = AudioClock::getNanoseconds();
    aaudio_result_t result = AAUDIO_OK;

    if (auto state = getState();
        state == AAUDIO_STREAM_STATE_CLOSED || state == AAUDIO_STREAM_STATE_DISCONNECTED) {
        ALOGW("%s() already CLOSED, returns INVALID_STATE, handle = %d",
                __func__, getHandle());
        return AAUDIO_ERROR_INVALID_STATE;
    }

    mediametrics::Defer defer([&] {
        mediametrics::LogItem(mMetricsId)
            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
@@ -231,7 +246,7 @@ aaudio_result_t AAudioServiceStreamBase::start() {
            .record(); });

    if (isRunning()) {
        return AAUDIO_OK;
        return result;
    }

    setFlowing(false);
@@ -254,16 +269,21 @@ aaudio_result_t AAudioServiceStreamBase::start() {
    return result;

error:
    disconnect();
    disconnect_l();
    return result;
}

aaudio_result_t AAudioServiceStreamBase::pause() {
    const int64_t beginNs = AudioClock::getNanoseconds();
    std::lock_guard<std::mutex> lock(mLock);
    return pause_l();
}

aaudio_result_t AAudioServiceStreamBase::pause_l() {
    aaudio_result_t result = AAUDIO_OK;
    if (!isRunning()) {
        return result;
    }
    const int64_t beginNs = AudioClock::getNanoseconds();

    mediametrics::Defer defer([&] {
        mediametrics::LogItem(mMetricsId)
@@ -279,7 +299,7 @@ aaudio_result_t AAudioServiceStreamBase::pause() {

    result = stopTimestampThread();
    if (result != AAUDIO_OK) {
        disconnect();
        disconnect_l();
        return result;
    }

@@ -292,7 +312,7 @@ aaudio_result_t AAudioServiceStreamBase::pause() {
    result = endpoint->stopStream(this, mClientHandle);
    if (result != AAUDIO_OK) {
        ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText());
        disconnect(); // TODO should we return or pause Base first?
        disconnect_l(); // TODO should we return or pause Base first?
    }

    sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
@@ -301,11 +321,16 @@ aaudio_result_t AAudioServiceStreamBase::pause() {
}

aaudio_result_t AAudioServiceStreamBase::stop() {
    const int64_t beginNs = AudioClock::getNanoseconds();
    std::lock_guard<std::mutex> lock(mLock);
    return stop_l();
}

aaudio_result_t AAudioServiceStreamBase::stop_l() {
    aaudio_result_t result = AAUDIO_OK;
    if (!isRunning()) {
        return result;
    }
    const int64_t beginNs = AudioClock::getNanoseconds();

    mediametrics::Defer defer([&] {
        mediametrics::LogItem(mMetricsId)
@@ -322,7 +347,7 @@ aaudio_result_t AAudioServiceStreamBase::stop() {
    sendCurrentTimestamp(); // warning - this calls a virtual function
    result = stopTimestampThread();
    if (result != AAUDIO_OK) {
        disconnect();
        disconnect_l();
        return result;
    }

@@ -336,7 +361,7 @@ aaudio_result_t AAudioServiceStreamBase::stop() {
    result = endpoint->stopStream(this, mClientHandle);
    if (result != AAUDIO_OK) {
        ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText());
        disconnect();
        disconnect_l();
        // TODO what to do with result here?
    }

@@ -355,11 +380,12 @@ aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() {
}

aaudio_result_t AAudioServiceStreamBase::flush() {
    const int64_t beginNs = AudioClock::getNanoseconds();
    std::lock_guard<std::mutex> lock(mLock);
    aaudio_result_t result = AAudio_isFlushAllowed(getState());
    if (result != AAUDIO_OK) {
        return result;
    }
    const int64_t beginNs = AudioClock::getNanoseconds();

    mediametrics::Defer defer([&] {
        mediametrics::LogItem(mMetricsId)
@@ -404,16 +430,66 @@ void AAudioServiceStreamBase::run() {
}

void AAudioServiceStreamBase::disconnect() {
    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
    std::lock_guard<std::mutex> lock(mLock);
    disconnect_l();
}

void AAudioServiceStreamBase::disconnect_l() {
    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED
        && getState() != AAUDIO_STREAM_STATE_CLOSED) {

        mediametrics::LogItem(mMetricsId)
            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
            .record();

        sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
    }
}

aaudio_result_t AAudioServiceStreamBase::registerAudioThread(pid_t clientThreadId,
        int priority) {
    std::lock_guard<std::mutex> lock(mLock);
    aaudio_result_t result = AAUDIO_OK;
    if (getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
        ALOGE("AAudioService::registerAudioThread(), thread already registered");
        result = AAUDIO_ERROR_INVALID_STATE;
    } else {
        const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
        setRegisteredThread(clientThreadId);
        int err = android::requestPriority(ownerPid, clientThreadId,
                                           priority, true /* isForApp */);
        if (err != 0) {
            ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
                  clientThreadId, errno, priority);
            result = AAUDIO_ERROR_INTERNAL;
        }
    }
    return result;
}

aaudio_result_t AAudioServiceStreamBase::unregisterAudioThread(pid_t clientThreadId) {
    std::lock_guard<std::mutex> lock(mLock);
    aaudio_result_t result = AAUDIO_OK;
    if (getRegisteredThread() != clientThreadId) {
        ALOGE("%s(), wrong thread", __func__);
        result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    } else {
        setRegisteredThread(0);
    }
    return result;
}

void AAudioServiceStreamBase::setState(aaudio_stream_state_t state) {
    // CLOSED is a final state.
    if (mState != AAUDIO_STREAM_STATE_CLOSED) {
        mState = state;
    } else {
        ALOGW_IF(mState != state, "%s(%d) when already CLOSED", __func__, state);
    }
}

aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
                                                          double  dataDouble) {
    AAudioServiceMessage command;
@@ -511,6 +587,7 @@ aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
 * used to communicate with the underlying HAL or Service.
 */
aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
    std::lock_guard<std::mutex> lock(mLock);
    {
        std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
        if (mUpMessageQueue == nullptr) {
Loading