Track: Check buffer size

Test: Native POC
Bug: 38340117
Change-Id: Ia7edd9a802905214a27961dbcec6352f6ef98f73
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9cab4c7..37c5764 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -71,6 +71,7 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             audio_session_t sessionId,
             uid_t clientUid,
             bool isOut,
@@ -81,7 +82,7 @@
         mThread(thread),
         mClient(client),
         mCblk(NULL),
-        // mBuffer
+        // mBuffer, mBufferSize
         mState(IDLE),
         mSampleRate(sampleRate),
         mFormat(format),
@@ -113,15 +114,22 @@
 
     // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
 
-    size_t bufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
+    size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
     // check overflow when computing bufferSize due to multiplication by mFrameSize.
-    if (bufferSize < frameCount  // roundup rounds down for values above UINT_MAX / 2
+    if (minBufferSize < frameCount  // roundup rounds down for values above UINT_MAX / 2
             || mFrameSize == 0   // format needs to be correct
-            || bufferSize > SIZE_MAX / mFrameSize) {
+            || minBufferSize > SIZE_MAX / mFrameSize) {
         android_errorWriteLog(0x534e4554, "34749571");
         return;
     }
-    bufferSize *= mFrameSize;
+    minBufferSize *= mFrameSize;
+
+    if (buffer == nullptr) {
+        bufferSize = minBufferSize; // allocated here.
+    } else if (minBufferSize > bufferSize) {
+        android_errorWriteLog(0x534e4554, "38340117");
+        return;
+    }
 
     size_t size = sizeof(audio_track_cblk_t);
     if (buffer == NULL && alloc == ALLOC_CBLK) {
@@ -177,6 +185,7 @@
             // It should references the buffer via the pipe.
             // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
             mBuffer = NULL;
+            bufferSize = 0;
             break;
         case ALLOC_CBLK:
             // clear all buffers
@@ -196,7 +205,10 @@
         case ALLOC_NONE:
             mBuffer = buffer;
             break;
+        default:
+            LOG_ALWAYS_FATAL("invalid allocation type: %d", (int)alloc);
         }
+        mBufferSize = bufferSize;
 
 #ifdef TEE_SINK
         if (mTeeSinkTrackEnabled) {
@@ -368,6 +380,7 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             const sp<IMemory>& sharedBuffer,
             audio_session_t sessionId,
             uid_t uid,
@@ -376,6 +389,7 @@
             audio_port_handle_t portId)
     :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
                   (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
+                  (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
                   sessionId, uid, true /*isOut*/,
                   (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
                   type, portId),
@@ -1220,7 +1234,8 @@
             uid_t uid)
     :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
               sampleRate, format, channelMask, frameCount,
-              NULL, 0, AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
+              nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
+              AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
               TYPE_OUTPUT),
     mActive(false), mSourceThread(sourceThread)
 {
@@ -1417,10 +1432,12 @@
                                                      audio_format_t format,
                                                      size_t frameCount,
                                                      void *buffer,
+                                                     size_t bufferSize,
                                                      audio_output_flags_t flags)
     :   Track(playbackThread, NULL, streamType,
               sampleRate, format, channelMask, frameCount,
-              buffer, 0, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
+              buffer, bufferSize, nullptr /* sharedBuffer */,
+              AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
               mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
 {
     uint64_t mixBufferNs = ((uint64_t)2 * playbackThread->frameCount() * 1000000000) /
@@ -1554,13 +1571,14 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             audio_session_t sessionId,
             uid_t uid,
             audio_input_flags_t flags,
             track_type type,
             audio_port_handle_t portId)
     :   TrackBase(thread, client, sampleRate, format,
-                  channelMask, frameCount, buffer, sessionId, uid, false /*isOut*/,
+                  channelMask, frameCount, buffer, bufferSize, sessionId, uid, false /*isOut*/,
                   (type == TYPE_DEFAULT) ?
                           ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
                           ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
@@ -1754,9 +1772,10 @@
                                                      audio_format_t format,
                                                      size_t frameCount,
                                                      void *buffer,
+                                                     size_t bufferSize,
                                                      audio_input_flags_t flags)
     :   RecordTrack(recordThread, NULL, sampleRate, format, channelMask, frameCount,
-                buffer, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
+                buffer, bufferSize, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
                 mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
 {
     uint64_t mixBufferNs = ((uint64_t)2 * recordThread->frameCount() * 1000000000) /
@@ -1823,7 +1842,9 @@
         uid_t uid,
         audio_port_handle_t portId)
     :   TrackBase(thread, NULL, sampleRate, format,
-                  channelMask, 0, NULL, sessionId, uid, false,
+                  channelMask, (size_t)0 /* frameCount */,
+                  nullptr /* buffer */, (size_t)0 /* bufferSize */,
+                  sessionId, uid, false /* isOut */,
                   ALLOC_NONE,
                   TYPE_DEFAULT, portId)
 {