Cache MMAP client silenced state.

When starting MMAP input stream, APM will check if the client is allowed
to capture at that moment or not and call setRecordSilenced if the
client is not allowed. However, the client is not active when starting
the MMAP input stream. In that case, the client silenced state will be
lost and the client will be able to capture even though it is not
allowed. In this CL, when setRecordSilenced is called, it will cache
the client silenced state so that it can apply when the client is
active.

Test: atest AAudioTests
Test: repo steps from the bug
Bug: 235850634
Change-Id: I49b5a0f08d1747053f868db6e88c0f677256fc3c
Merged-In: I49b5a0f08d1747053f868db6e88c0f677256fc3c
(cherry picked from commit 0960903b2fee5d1d449ffcd598e0b5d3a945d99a)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8732273..1e33057 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8646,6 +8646,12 @@
     if (isOutput()) {
         ret = AudioSystem::startOutput(portId);
     } else {
+        {
+            // Add the track record before starting input so that the silent status for the
+            // client can be cached.
+            Mutex::Autolock _l(mLock);
+            setClientSilencedStateIfNotExist_l(client.clientUid, false /*silenced*/);
+        }
         ret = AudioSystem::startInput(portId);
     }
 
@@ -8664,6 +8670,7 @@
         } else {
             mHalStream->stop();
         }
+        eraseClientSilenceStateIfNoActiveClient_l(client.clientUid);
         return PERMISSION_DENIED;
     }
 
@@ -8671,6 +8678,9 @@
     sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
                                         isOutput(), client.clientUid, client.clientPid,
                                         IPCThreadState::self()->getCallingPid(), portId);
+    if (!isOutput()) {
+        track->setSilenced_l(isClientSilenced_l(client.clientUid));
+    }
 
     if (isOutput()) {
         // force volume update when a new track is added
@@ -8726,6 +8736,7 @@
     }
 
     mActiveTracks.remove(track);
+    eraseClientSilenceStateIfNoActiveClient_l(track->uid());
 
     mLock.unlock();
     if (isOutput()) {
@@ -9488,6 +9499,7 @@
             broadcast_l();
         }
     }
+    setClientSilencedIfExists_l(uid, silenced);
 }
 
 void AudioFlinger::MmapCaptureThread::toAudioPortConfig(struct audio_port_config *config)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index c6a8201..30063b2 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1786,6 +1786,35 @@
                 // Sets the UID records silence
     virtual     void        setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}
 
+                void        setClientSilencedStateIfNotExist_l(uid_t uid, bool silenced) {
+                                if (mClientSilencedStates.count(uid) == 0) {
+                                    mClientSilencedStates[uid] = silenced;
+                                }
+                            }
+
+                size_t      eraseClientSilenceStateIfNoActiveClient_l(uid_t uid) {
+                                bool found = false;
+                                for (const auto& t : mActiveTracks) {
+                                    if (t->uid() == uid) {
+                                        found = true;
+                                    }
+                                }
+                                // Only erase when there is no active client for the given uid.
+                                return found ? 0 : mClientSilencedStates.erase(uid);
+                            }
+
+                bool        isClientSilenced_l(uid_t uid) const {
+                                const auto it = mClientSilencedStates.find(uid);
+                                return it != mClientSilencedStates.end() ? it->second : false;
+                            }
+
+                void        setClientSilencedIfExists_l(uid_t uid, bool silenced) {
+                                const auto it = mClientSilencedStates.find(uid);
+                                if (it != mClientSilencedStates.end()) {
+                                    it->second = silenced;
+                                }
+                            }
+
  protected:
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
                 void        dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1800,6 +1829,7 @@
                 AudioHwDevice* const    mAudioHwDev;
                 ActiveTracks<MmapTrack> mActiveTracks;
                 float                   mHalVolFloat;
+                std::map<uid_t, bool>   mClientSilencedStates;
 
                 int32_t                 mNoCallbackWarningCount;
      static     constexpr int32_t       kMaxNoCallbackWarnings = 5;