Don't record audio if UID is idle - media framework
To protect user's privacy if a UID is in an idle state we allow
recording but report silence (all zeros in the byte array) and once
the process goes in an active state we report the real mic data.
This avoids the race between the app being notified aboout its
lifecycle and the audio system being notified about the state
of a UID.
Test: Added - AudioRecordTest#testRecordNoDataForIdleUids
Passing - cts-tradefed run cts-dev -m CtsMediaTestCases
-t android.media.cts.AudioRecordTest
bug:63938985
Change-Id: I1442a9dda1553e9ea7a4a654c50555ac1ec06aa0
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d5def48..7308c41 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6528,6 +6528,7 @@
rear = mRsmpInRear += framesRead;
size = activeTracks.size();
+
// loop over each active track
for (size_t i = 0; i < size; i++) {
activeTrack = activeTracks[i];
@@ -6584,6 +6585,11 @@
if (activeTrack->mFramesToDrop == 0) {
if (framesOut > 0) {
activeTrack->mSink.frameCount = framesOut;
+ // Sanitize before releasing if the track has no access to the source data
+ // An idle UID receives silence from non virtual devices until active
+ if (activeTrack->isSilenced()) {
+ memset(activeTrack->mSink.raw, 0, framesOut * mFrameSize);
+ }
activeTrack->releaseBuffer(&activeTrack->mSink);
}
} else {
@@ -6923,7 +6929,9 @@
status_t status = NO_ERROR;
if (recordTrack->isExternalTrack()) {
mLock.unlock();
- status = AudioSystem::startInput(mId, recordTrack->sessionId());
+ bool silenced;
+ status = AudioSystem::startInput(mId, recordTrack->sessionId(),
+ mInDevice, recordTrack->uid(), &silenced);
mLock.lock();
// FIXME should verify that recordTrack is still in mActiveTracks
if (status != NO_ERROR) {
@@ -6932,6 +6940,7 @@
ALOGV("RecordThread::start error %d", status);
return status;
}
+ recordTrack->setSilenced(silenced);
}
// Catch up with current buffer indices if thread is already running.
// This is what makes a new client discard all buffered data. If the track's mRsmpInFront
@@ -7135,6 +7144,16 @@
write(fd, result.string(), result.size());
}
+void AudioFlinger::RecordThread::setRecordSilenced(uid_t uid, bool silenced)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mTracks.size() ; i++) {
+ sp<RecordTrack> track = mTracks[i];
+ if (track != 0 && track->uid() == uid) {
+ track->setSilenced(silenced);
+ }
+ }
+}
void AudioFlinger::RecordThread::ResamplerBufferProvider::reset()
{
@@ -7827,7 +7846,9 @@
if (isOutput()) {
ret = AudioSystem::startOutput(mId, streamType(), mSessionId);
} else {
- ret = AudioSystem::startInput(mId, mSessionId);
+ // TODO: Block recording for idle UIDs (b/72134552)
+ bool silenced;
+ ret = AudioSystem::startInput(mId, mSessionId, mInDevice, client.clientUid, &silenced);
}
// abort if start is rejected by audio policy manager