IMediaSource: add readMultiple API to speed up inter-process reading.

GenericSource: use readMultiple for audio track.
Bug: 28545177
Bug: 22775369
Change-Id: If26b80e75eba4212105d51140c4bfce85ec664f8
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 84f1181..7e40e4f 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -37,6 +37,7 @@
     PAUSE,
     GETFORMAT,
     READ,
+    READMULTIPLE,
     RELEASE_BUFFER
 };
 
@@ -189,6 +190,37 @@
         return ret;
     }
 
+    virtual status_t readMultiple(Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers) {
+        ALOGV("readMultiple");
+        if (buffers == NULL || !buffers->isEmpty()) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        data.writeUint32(maxNumBuffers);
+        status_t ret = remote()->transact(READMULTIPLE, data, &reply);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+        // wrap the returned data in a vector of MediaBuffers
+        int32_t bufCount = 0;
+        while (1) {
+            if (reply.readInt32() == 0) {
+                break;
+            }
+            int32_t len = reply.readInt32();
+            ALOGV("got len %d", len);
+            MediaBuffer *buf = new MediaBuffer(len);
+            reply.read(buf->data(), len);
+            buf->meta_data()->updateFromParcel(reply);
+            buffers->push_back(buf);
+            ++bufCount;
+        }
+        ret = reply.readInt32();
+        ALOGV("got status %d, bufCount %d", ret, bufCount);
+        return ret;
+    }
+
     virtual status_t pause() {
         ALOGV("pause");
         Parcel data, reply;
@@ -340,6 +372,37 @@
             }
             return NO_ERROR;
         }
+        case READMULTIPLE: {
+            ALOGV("readmultiple");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            uint32_t maxNumBuffers;
+            data.readUint32(&maxNumBuffers);
+            status_t ret = NO_ERROR;
+            uint32_t bufferCount = 0;
+            if (maxNumBuffers > kMaxNumReadMultiple) {
+                maxNumBuffers = kMaxNumReadMultiple;
+            }
+            while (bufferCount < maxNumBuffers) {
+                if (reply->dataSize() >= MediaBuffer::kSharedMemThreshold) {
+                    break;
+                }
+
+                MediaBuffer *buf = NULL;
+                ret = read(&buf, NULL);
+                if (ret != NO_ERROR || buf == NULL) {
+                    break;
+                }
+                ++bufferCount;
+                reply->writeInt32(1);  // indicate one more MediaBuffer.
+                reply->writeByteArray(
+                        buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
+                buf->meta_data()->writeToParcel(*reply);
+                buf->release();
+            }
+            reply->writeInt32(0);  // indicate no more MediaBuffer.
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }