Loading include/media/MmapStreamCallback.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading services/audioflinger/AudioFlinger.cpp +4 −6 Original line number Diff line number Diff line Loading @@ -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); } } Loading services/audioflinger/MmapTracks.h +11 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -58,5 +67,7 @@ private: virtual void onTimestamp(const ExtendedTimestamp ×tamp); pid_t mPid; bool mSilenced; // protected by MMapThread::mLock bool mSilencedNotified; // protected by MMapThread::mLock }; // end of Track services/audioflinger/Threads.cpp +86 −14 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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()) { Loading @@ -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()); Loading @@ -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) { Loading Loading @@ -8530,9 +8556,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; } } } Loading Loading @@ -8587,7 +8615,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); Loading Loading @@ -8792,6 +8819,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); Loading @@ -8800,6 +8833,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 || Loading @@ -8817,4 +8878,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 services/audioflinger/Threads.h +11 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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); Loading @@ -1686,8 +1693,6 @@ protected: bool mMasterMute; bool mStreamMute; float mHalVolFloat; int32_t mNoCallbackWarningCount; static constexpr int32_t kMaxNoCallbackWarnings = 5; AudioStreamOut* mOutput; }; Loading @@ -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 Loading
include/media/MmapStreamCallback.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
services/audioflinger/AudioFlinger.cpp +4 −6 Original line number Diff line number Diff line Loading @@ -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); } } Loading
services/audioflinger/MmapTracks.h +11 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -58,5 +67,7 @@ private: virtual void onTimestamp(const ExtendedTimestamp ×tamp); pid_t mPid; bool mSilenced; // protected by MMapThread::mLock bool mSilencedNotified; // protected by MMapThread::mLock }; // end of Track
services/audioflinger/Threads.cpp +86 −14 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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()) { Loading @@ -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()); Loading @@ -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) { Loading Loading @@ -8530,9 +8556,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; } } } Loading Loading @@ -8587,7 +8615,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); Loading Loading @@ -8792,6 +8819,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); Loading @@ -8800,6 +8833,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 || Loading @@ -8817,4 +8878,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
services/audioflinger/Threads.h +11 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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); Loading @@ -1686,8 +1693,6 @@ protected: bool mMasterMute; bool mStreamMute; float mHalVolFloat; int32_t mNoCallbackWarningCount; static constexpr int32_t kMaxNoCallbackWarnings = 5; AudioStreamOut* mOutput; }; Loading @@ -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