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

Commit f2553690 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "silence_mmap_capture_fix" into pi-dev

* changes:
  audiopolicy: fix shared mmap capture
  audioflinger: fix mmap interface callback lock
  Revert "Revert "audioflinger: implement silenced capture for mmap""
parents 85d2e91d 03893876
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ class MmapStreamCallback : public virtual RefBase {
     * The mmap stream should be torn down because conditions that permitted its creation with
     * the requested parameters have changed and do not allow it to operate with the requested
     * constraints any more.
     * \param[in] handle handle for the client stream to tear down.
     */
    virtual void onTearDown() = 0;
    virtual void onTearDown(audio_port_handle_t handle) = 0;

    /**
     * The volume to be applied to the use case specified when opening the stream has changed
+4 −6
Original line number Diff line number Diff line
@@ -1000,14 +1000,12 @@ void AudioFlinger::setRecordSilenced(uid_t uid, bool silenced)
{
    ALOGV("AudioFlinger::setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);

    // TODO: Notify MmapThreads

    AutoMutex lock(mLock);
    for (size_t i = 0; i < mRecordThreads.size(); i++) {
        sp<RecordThread> thread = mRecordThreads.valueAt(i);
        if (thread != 0) {
            thread->setRecordSilenced(uid, silenced);
        mRecordThreads[i]->setRecordSilenced(uid, silenced);
    }
    for (size_t i = 0; i < mMmapThreads.size(); i++) {
        mMmapThreads[i]->setRecordSilenced(uid, silenced);
    }
}

+11 −0
Original line number Diff line number Diff line
@@ -43,6 +43,15 @@ public:
     static void        appendDumpHeader(String8& result);
            void        appendDump(String8& result, bool active);

                        // protected by MMapThread::mLock
            void        setSilenced_l(bool silenced) { mSilenced = silenced;
                                                       mSilencedNotified = false;}
                        // protected by MMapThread::mLock
            bool        isSilenced_l() const { return mSilenced; }
                        // protected by MMapThread::mLock
            bool        getAndSetSilencedNotified_l() { bool silencedNotified = mSilencedNotified;
                                                        mSilencedNotified = true;
                                                        return silencedNotified; }
private:
    friend class MmapThread;

@@ -58,5 +67,7 @@ private:
    virtual void onTimestamp(const ExtendedTimestamp &timestamp);

    pid_t mPid;
    bool  mSilenced;            // protected by MMapThread::mLock
    bool  mSilencedNotified;    // protected by MMapThread::mLock
};  // end of Track
+95 −15
Original line number Diff line number Diff line
@@ -7898,7 +7898,7 @@ AudioFlinger::MmapThread::MmapThread(
      mSessionId(AUDIO_SESSION_NONE),
      mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
      mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
      mActiveTracks(&this->mLocalLog)
      mActiveTracks(&this->mLocalLog), mNoCallbackWarningCount(0)
{
    mStandby = true;
    readHalParameters_l();
@@ -7916,7 +7916,14 @@ void AudioFlinger::MmapThread::onFirstRef()

void AudioFlinger::MmapThread::disconnect()
{
    ActiveTracks<MmapTrack> activeTracks;
    {
        Mutex::Autolock _l(mLock);
        for (const sp<MmapTrack> &t : mActiveTracks) {
            activeTracks.add(t);
        }
    }
    for (const sp<MmapTrack> &t : activeTracks) {
        stop(t->portId());
    }
    // This will decrement references and may cause the destruction of this thread.
@@ -7961,6 +7968,17 @@ status_t AudioFlinger::MmapThread::getMmapPosition(struct audio_mmap_position *p
    return mHalStream->getMmapPosition(position);
}

status_t AudioFlinger::MmapThread::exitStandby()
{
    status_t ret = mHalStream->start();
    if (ret != NO_ERROR) {
        ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
        return ret;
    }
    mStandby = false;
    return NO_ERROR;
}

status_t AudioFlinger::MmapThread::start(const AudioClient& client,
                                         audio_port_handle_t *handle)
{
@@ -7974,13 +7992,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,

    if (*handle == mPortId) {
        // for the first track, reuse portId and session allocated when the stream was opened
        ret = mHalStream->start();
        if (ret != NO_ERROR) {
            ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
            return ret;
        }
        mStandby = false;
        return NO_ERROR;
        return exitStandby();
    }

    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
@@ -8028,33 +8040,43 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
        return BAD_VALUE;
    }

    bool silenced = false;
    if (isOutput()) {
        ret = AudioSystem::startOutput(mId, streamType(), mSessionId);
    } else {
        // TODO: Block recording for idle UIDs (b/72134552)
        bool silenced;
        ret = AudioSystem::startInput(portId, &silenced);
    }

    Mutex::Autolock _l(mLock);
    // abort if start is rejected by audio policy manager
    if (ret != NO_ERROR) {
        ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret);
        if (mActiveTracks.size() != 0) {
            mLock.unlock();
            if (isOutput()) {
                AudioSystem::releaseOutput(mId, streamType(), mSessionId);
            } else {
                AudioSystem::releaseInput(portId);
            }
            mLock.lock();
        } else {
            mHalStream->stop();
        }
        return PERMISSION_DENIED;
    }

    if (!isOutput() && !silenced) {
        for (const sp<MmapTrack> &track : mActiveTracks) {
            if (track->isSilenced_l() && track->uid() != client.clientUid)
                track->invalidate();
        }
    }

    // Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
    sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
                                        client.clientUid, client.clientPid, portId);

    track->setSilenced_l(silenced);
    mActiveTracks.add(track);
    sp<EffectChain> chain = getEffectChain_l(mSessionId);
    if (chain != 0) {
@@ -8084,6 +8106,8 @@ status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
        return NO_ERROR;
    }

    Mutex::Autolock _l(mLock);

    sp<MmapTrack> track;
    for (const sp<MmapTrack> &t : mActiveTracks) {
        if (handle == t->portId()) {
@@ -8097,6 +8121,7 @@ status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)

    mActiveTracks.remove(track);

    mLock.unlock();
    if (isOutput()) {
        AudioSystem::stopOutput(mId, streamType(), track->sessionId());
        AudioSystem::releaseOutput(mId, streamType(), track->sessionId());
@@ -8104,6 +8129,7 @@ status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
        AudioSystem::stopInput(track->portId());
        AudioSystem::releaseInput(track->portId());
    }
    mLock.lock();

    sp<EffectChain> chain = getEffectChain_l(track->sessionId());
    if (chain != 0) {
@@ -8355,7 +8381,9 @@ status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *
        sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
        sp<MmapStreamCallback> callback = mCallback.promote();
        if (mDeviceId != deviceId && callback != 0) {
            mLock.unlock();
            callback->onRoutingChanged(deviceId);
            mLock.lock();
        }
        mDeviceId = deviceId;
    }
@@ -8364,7 +8392,9 @@ status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *
        sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
        sp<MmapStreamCallback> callback = mCallback.promote();
        if (mDeviceId != deviceId && callback != 0) {
            mLock.unlock();
            callback->onRoutingChanged(deviceId);
            mLock.lock();
        }
        mDeviceId = deviceId;
    }
@@ -8530,9 +8560,13 @@ void AudioFlinger::MmapThread::checkInvalidTracks_l()
        if (track->isInvalid()) {
            sp<MmapStreamCallback> callback = mCallback.promote();
            if (callback != 0) {
                callback->onTearDown();
                mLock.unlock();
                callback->onTearDown(track->portId());
                mLock.lock();
            } else if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
                ALOGW("Could not notify MMAP stream tear down: no onTearDown callback!");
                mNoCallbackWarningCount++;
            }
            break;
        }
    }
}
@@ -8587,7 +8621,6 @@ AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
      mStreamVolume(1.0),
      mStreamMute(false),
      mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
      mNoCallbackWarningCount(0),
      mOutput(output)
{
    snprintf(mThreadName, kThreadNameLength, "AudioMmapOut_%X", id);
@@ -8724,9 +8757,11 @@ void AudioFlinger::MmapPlaybackThread::processVolume_l()
                for (int i = 0; i < channelCount; i++) {
                    values.add(volume);
                }
                callback->onVolumeChanged(mChannelMask, values);
                mHalVolFloat = volume; // SW volume control worked, so update value.
                mNoCallbackWarningCount = 0;
                mLock.unlock();
                callback->onVolumeChanged(mChannelMask, values);
                mLock.lock();
            } else {
                if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
                    ALOGW("Could not set MMAP stream volume: no volume callback!");
@@ -8792,6 +8827,12 @@ AudioFlinger::MmapCaptureThread::MmapCaptureThread(
    mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
}

status_t AudioFlinger::MmapCaptureThread::exitStandby()
{
    mInput->stream->setGain(1.0f);
    return MmapThread::exitStandby();
}

AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
{
    Mutex::Autolock _l(mLock);
@@ -8800,6 +8841,34 @@ AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
    return input;
}


void AudioFlinger::MmapCaptureThread::processVolume_l()
{
    bool changed = false;
    bool silenced = false;

    sp<MmapStreamCallback> callback = mCallback.promote();
    if (callback == 0) {
        if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
            ALOGW("Could not set MMAP stream silenced: no onStreamSilenced callback!");
            mNoCallbackWarningCount++;
        }
    }

    // After a change occurred in track silenced state, mute capture in audio DSP if at least one
    // track is silenced and unmute otherwise
    for (size_t i = 0; i < mActiveTracks.size() && !silenced; i++) {
        if (!mActiveTracks[i]->getAndSetSilencedNotified_l()) {
            changed = true;
            silenced = mActiveTracks[i]->isSilenced_l();
        }
    }

    if (changed) {
        mInput->stream->setGain(silenced ? 0.0f: 1.0f);
    }
}

void AudioFlinger::MmapCaptureThread::updateMetadata_l()
{
    if (mInput == nullptr || mInput->stream == nullptr ||
@@ -8817,4 +8886,15 @@ void AudioFlinger::MmapCaptureThread::updateMetadata_l()
    mInput->stream->updateSinkMetadata(metadata);
}

void AudioFlinger::MmapCaptureThread::setRecordSilenced(uid_t uid, bool silenced)
{
    Mutex::Autolock _l(mLock);
    for (size_t i = 0; i < mActiveTracks.size() ; i++) {
        if (mActiveTracks[i]->uid() == uid) {
            mActiveTracks[i]->setSilenced_l(silenced);
            broadcast_l();
        }
    }
}

} // namespace android
+11 −3
Original line number Diff line number Diff line
@@ -1589,6 +1589,7 @@ class MmapThread : public ThreadBase
    virtual     void        threadLoop_exit();
    virtual     void        threadLoop_standby();
    virtual     bool        shouldStandby_l() { return false; }
    virtual     status_t    exitStandby();

    virtual     status_t    initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
    virtual     size_t      frameCount() const { return mFrameCount; }
@@ -1621,6 +1622,9 @@ class MmapThread : public ThreadBase

    virtual     void        invalidateTracks(audio_stream_type_t streamType __unused) {}

                // Sets the UID records silence
    virtual     void        setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}

                void        dump(int fd, const Vector<String16>& args);
    virtual     void        dumpInternals(int fd, const Vector<String16>& args);
                void        dumpTracks(int fd, const Vector<String16>& args);
@@ -1637,6 +1641,9 @@ class MmapThread : public ThreadBase
                sp<DeviceHalInterface>  mHalDevice;
                AudioHwDevice* const    mAudioHwDev;
                ActiveTracks<MmapTrack> mActiveTracks;

                int32_t                 mNoCallbackWarningCount;
     static     constexpr int32_t       kMaxNoCallbackWarnings = 5;
};

class MmapPlaybackThread : public MmapThread, public VolumeInterface
@@ -1670,7 +1677,7 @@ public:

    virtual     audio_stream_type_t streamType() { return mStreamType; }
    virtual     void        checkSilentMode_l();
    virtual     void        processVolume_l();
                void        processVolume_l() override;

    virtual     void        dumpInternals(int fd, const Vector<String16>& args);

@@ -1686,8 +1693,6 @@ protected:
                bool                        mMasterMute;
                bool                        mStreamMute;
                float                       mHalVolFloat;
                int32_t                     mNoCallbackWarningCount;
     static     constexpr int32_t           kMaxNoCallbackWarnings = 5;
                AudioStreamOut*             mOutput;
};

@@ -1702,9 +1707,12 @@ public:

                AudioStreamIn* clearInput();

                status_t       exitStandby() override;
    virtual     bool           isOutput() const override { return false; }

                void           updateMetadata_l() override;
                void           processVolume_l() override;
                void           setRecordSilenced(uid_t uid, bool silenced) override;

protected:

Loading