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""
gugelfrei
TreeHugger Robot 6 years ago committed by Android (Google) Code Review
commit f255369091

@ -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

@ -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);
}
}

@ -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

@ -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()
{
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 @@ 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

@ -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:

@ -1946,7 +1946,7 @@ AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
sessionId, uid, false /* isOut */,
ALLOC_NONE,
TYPE_DEFAULT, portId),
mPid(pid)
mPid(pid), mSilenced(false), mSilencedNotified(false)
{
}

@ -52,7 +52,7 @@ public:
void setGains(const AudioGainCollection &gains) { mGains = gains; }
const AudioGainCollection &getGains() const { return mGains; }
void setFlags(uint32_t flags)
virtual void setFlags(uint32_t flags)
{
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag

@ -43,6 +43,20 @@ public:
// For a Profile aka MixPort, tag name and name are equivalent.
virtual const String8 getTagName() const { return getName(); }
// FIXME: this is needed because shared MMAP stream clients use the same audio session.
// Once capture clients are tracked individually and not per session this can be removed
// MMAP no IRQ input streams do not have the default limitation of one active client
// max as they can be used in shared mode by the same application.
// NOTE: this works for explicit values set in audio_policy_configuration.xml because
// flags are parsed before maxActiveCount by the serializer.
void setFlags(uint32_t flags) override
{
AudioPort::setFlags(flags);
if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
maxActiveCount = 0;
}
}
// This method is used for input and direct output, and is not used for other output.
// If parameter updatedSamplingRate is non-NULL, it is assigned the actual sample rate.
// For input, flags is interpreted as audio_input_flags_t.

@ -1468,14 +1468,19 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
}
// 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;

@ -344,8 +344,9 @@ aaudio_result_t AAudioServiceEndpointMMAP::getTimestamp(int64_t *positionFrames,
}
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();
};

@ -68,7 +68,7 @@ public:
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;

Loading…
Cancel
Save