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

Commit a2f478ca authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: implement silenced capture for mmap

Implement silencing of audio capture for idle UIDs for
MMAP streams.

Use audio HAL setMicGain() API to silence the mmap buffer for
exclusive mode and when only one client is active in shared mode.

Add new MmapStreamCallback method onStreamSilenced() for AAudio
service to selectively silence streams from silenced UIDs in
shared mode.

Bug: 72134552
Test: manual
Change-Id: I7c92ba0002bc5ba003c1a3c887edddf9ae53b538
parent 9fc25229
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
+86 −14
Original line number Diff line number Diff line
@@ -7886,7 +7886,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();
@@ -7904,7 +7904,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.
@@ -7949,6 +7956,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)
{
@@ -7962,13 +7980,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;
@@ -8016,33 +8028,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) {
@@ -8072,6 +8094,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()) {
@@ -8085,6 +8109,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());
@@ -8092,6 +8117,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) {
@@ -8518,9 +8544,11 @@ void AudioFlinger::MmapThread::checkInvalidTracks_l()
        if (track->isInvalid()) {
            sp<MmapStreamCallback> callback = mCallback.promote();
            if (callback != 0) {
                callback->onTearDown();
                callback->onTearDown(track->portId());
            } else if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
                ALOGW("Could not notify MMAP stream tear down: no onTearDown callback!");
                mNoCallbackWarningCount++;
            }
            break;
        }
    }
}
@@ -8575,7 +8603,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);
@@ -8780,6 +8807,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);
@@ -8788,6 +8821,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 ||
@@ -8805,4 +8866,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