audioflinger: limit max number of tracks per client

Limit max number of audio tracks for a given application to
limit the chance of denial of service by misbehaving apps
not releasing tracks.

Bug: 7007023
Change-Id: Id7ac37450aabdbeaa5f83cb6e4b2a2b0c749f99c
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a91fc26..c19cb6a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4588,10 +4588,25 @@
     return mixerStatus;
 }
 
+// trackCountForUid_l() must be called with ThreadBase::mLock held
+uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid)
+{
+    uint32_t trackCount = 0;
+    for (size_t i = 0; i < mTracks.size() ; i++) {
+        if (mTracks[i]->uid() == (int)uid) {
+            trackCount++;
+        }
+    }
+    return trackCount;
+}
+
 // getTrackName_l() must be called with ThreadBase::mLock held
 int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask,
-        audio_format_t format, audio_session_t sessionId)
+        audio_format_t format, audio_session_t sessionId, uid_t uid)
 {
+    if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
+        return -1;
+    }
     return mAudioMixer->getTrackName(channelMask, format, sessionId);
 }
 
@@ -4696,7 +4711,7 @@
             mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
             for (size_t i = 0; i < mTracks.size() ; i++) {
                 int name = getTrackName_l(mTracks[i]->mChannelMask,
-                        mTracks[i]->mFormat, mTracks[i]->mSessionId);
+                        mTracks[i]->mFormat, mTracks[i]->mSessionId, mTracks[i]->uid());
                 if (name < 0) {
                     break;
                 }
@@ -5141,8 +5156,11 @@
 
 // getTrackName_l() must be called with ThreadBase::mLock held
 int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask __unused,
-        audio_format_t format __unused, audio_session_t sessionId __unused)
+        audio_format_t format __unused, audio_session_t sessionId __unused, uid_t uid)
 {
+    if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
+        return -1;
+    }
     return 0;
 }