Revert "Revert "audioflinger: implement silenced capture for mmap""
This reverts commit 611ebb95e76c230214780b7b583b8a3c5277ac7a.
Bug: 78118584
bug: 72134552
Test: 'adb shell write_sine_callback -m3 -pl -s100 -x' and Plug headphones in and out.
Test: AAudio CTS tests
Change-Id: I7558ad7b9c6c2d352ebce105382fe914c26fd35e
diff --git a/include/media/MmapStreamCallback.h b/include/media/MmapStreamCallback.h
index 8098e79..31b8eb5 100644
--- a/include/media/MmapStreamCallback.h
+++ b/include/media/MmapStreamCallback.h
@@ -31,8 +31,9 @@
* 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
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b38d37f..54121cd 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1000,14 +1000,12 @@
{
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);
}
}
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index a210a1b..6f546c3 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -43,6 +43,15 @@
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 @@
virtual void onTimestamp(const ExtendedTimestamp ×tamp);
pid_t mPid;
+ bool mSilenced; // protected by MMapThread::mLock
+ bool mSilencedNotified; // protected by MMapThread::mLock
}; // end of Track
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ab65601..1517d11 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7898,7 +7898,7 @@
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::disconnect()
{
- for (const sp<MmapTrack> &t : mActiveTracks) {
+ 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 @@
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 @@
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 @@
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 @@
return NO_ERROR;
}
+ Mutex::Autolock _l(mLock);
+
sp<MmapTrack> track;
for (const sp<MmapTrack> &t : mActiveTracks) {
if (handle == t->portId()) {
@@ -8097,6 +8121,7 @@
mActiveTracks.remove(track);
+ mLock.unlock();
if (isOutput()) {
AudioSystem::stopOutput(mId, streamType(), track->sessionId());
AudioSystem::releaseOutput(mId, streamType(), track->sessionId());
@@ -8104,6 +8129,7 @@
AudioSystem::stopInput(track->portId());
AudioSystem::releaseInput(track->portId());
}
+ mLock.lock();
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
@@ -8530,9 +8556,11 @@
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;
}
}
}
@@ -8587,7 +8615,6 @@
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);
@@ -8792,6 +8819,12 @@
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 +8833,34 @@
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 +8878,15 @@
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
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 5a5961a..bc4a534 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1589,6 +1589,7 @@
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 @@
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 @@
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 @@
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 @@
bool mMasterMute;
bool mStreamMute;
float mHalVolFloat;
- int32_t mNoCallbackWarningCount;
- static constexpr int32_t kMaxNoCallbackWarnings = 5;
AudioStreamOut* mOutput;
};
@@ -1702,9 +1707,12 @@
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:
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3fe41d8..aff1239 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1946,7 +1946,7 @@
sessionId, uid, false /* isOut */,
ALLOC_NONE,
TYPE_DEFAULT, portId),
- mPid(pid)
+ mPid(pid), mSilenced(false), mSilencedNotified(false)
{
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 947529e..0d36266 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1468,14 +1468,19 @@
}
// For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
// The second call is for the first active client and sets the UID. Any further call
- // corresponds to a new client and is only permitted from the same UId.
+ // corresponds to a new client and is only permitted from the same UID.
+ // If the first UID is silenced, allow a new UID connection and replace with new UID
if (audioSession->openCount() == 1) {
audioSession->setUid(uid);
} else if (audioSession->uid() != uid) {
- ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
- uid, session, audioSession->uid());
- status = INVALID_OPERATION;
- goto error;
+ if (!audioSession->isSilenced()) {
+ ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
+ uid, session, audioSession->uid());
+ status = INVALID_OPERATION;
+ goto error;
+ }
+ audioSession->setUid(uid);
+ audioSession->setSilenced(false);
}
audioSession->changeOpenCount(1);
*inputType = API_INPUT_LEGACY;
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index ea30c6d..5f1de76 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -344,8 +344,9 @@
}
-void AAudioServiceEndpointMMAP::onTearDown() {
+void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t handle __unused) {
ALOGD("%s(%p) called", __func__, this);
+ //TODO: disconnect only stream corresponding to handle received
disconnectRegisteredStreams();
};
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 16b6269..c4c943d 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -68,7 +68,7 @@
aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
// -------------- Callback functions for MmapStreamCallback ---------------------
- void onTearDown() override;
+ void onTearDown(audio_port_handle_t handle) override;
void onVolumeChanged(audio_channel_mask_t channels,
android::Vector<float> values) override;