Merge "Move 'sniff' functionality from DataSource to MediaExtractor"
diff --git a/include/media/BufferingSettings.h b/include/media/BufferingSettings.h
new file mode 100644
index 0000000..7dd9d40
--- /dev/null
+++ b/include/media/BufferingSettings.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BUFFERING_SETTINGS_H
+#define ANDROID_BUFFERING_SETTINGS_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+enum BufferingMode : int {
+    // Do not support buffering.
+    BUFFERING_MODE_NONE             = 0,
+    // Support only time based buffering.
+    BUFFERING_MODE_TIME_ONLY        = 1,
+    // Support only size based buffering.
+    BUFFERING_MODE_SIZE_ONLY        = 2,
+    // Support both time and size based buffering, time based calculation precedes size based.
+    // Size based calculation will be used only when time information is not available for
+    // the stream.
+    BUFFERING_MODE_TIME_THEN_SIZE   = 3,
+    // Number of modes.
+    BUFFERING_MODE_COUNT            = 4,
+};
+
+struct BufferingSettings : public Parcelable {
+    static const int kNoWatermark = -1;
+
+    static bool IsValidBufferingMode(int mode);
+
+    BufferingMode mInitialBufferingMode;  // for prepare
+    BufferingMode mRebufferingMode;  // for playback
+
+    int mInitialWatermarkMs;  // time based
+    int mInitialWatermarkKB;  // size based
+
+    // When cached data is below this mark, playback will be paused for buffering
+    // till data reach |mRebufferingWatermarkHighMs| or end of stream.
+    int mRebufferingWatermarkLowMs;
+    // When cached data is above this mark, buffering will be paused.
+    int mRebufferingWatermarkHighMs;
+
+    // When cached data is below this mark, playback will be paused for buffering
+    // till data reach |mRebufferingWatermarkHighKB| or end of stream.
+    int mRebufferingWatermarkLowKB;
+    // When cached data is above this mark, buffering will be paused.
+    int mRebufferingWatermarkHighKB;
+
+    BufferingSettings();
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+};
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BUFFERING_SETTINGS_H
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 99ef59f..f642373 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -39,6 +39,7 @@
 struct IMediaHTTPService;
 struct AudioPlaybackRate;
 struct AVSyncSettings;
+struct BufferingSettings;
 
 typedef IMediaSource::ReadOptions::SeekMode MediaPlayerSeekMode;
 
@@ -59,6 +60,9 @@
     virtual status_t        setDataSource(const sp<IDataSource>& source) = 0;
     virtual status_t        setVideoSurfaceTexture(
                                     const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+    virtual status_t        getDefaultBufferingSettings(
+                                    BufferingSettings* buffering /* nonnull */) = 0;
+    virtual status_t        setBufferingSettings(const BufferingSettings& buffering) = 0;
     virtual status_t        prepareAsync() = 0;
     virtual status_t        start() = 0;
     virtual status_t        stop() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 4e4878a..0e815cb 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -30,6 +30,7 @@
 #include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
 #include <media/AVSyncSettings.h>
+#include <media/BufferingSettings.h>
 #include <media/Metadata.h>
 
 // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
@@ -174,6 +175,15 @@
     virtual status_t    setVideoSurfaceTexture(
                                 const sp<IGraphicBufferProducer>& bufferProducer) = 0;
 
+    virtual status_t    getDefaultBufferingSettings(
+                                BufferingSettings* buffering /* nonnull */) {
+        *buffering = BufferingSettings();
+        return OK;
+    }
+    virtual status_t    setBufferingSettings(const BufferingSettings& /* buffering */) {
+        return OK;
+    }
+
     virtual status_t    prepare() = 0;
     virtual status_t    prepareAsync() = 0;
     virtual status_t    start() = 0;
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 2e4cf7d..f4d8bc0 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_SRC_FILES += \
     IDataSource.cpp \
     IHDCP.cpp \
+    BufferingSettings.cpp \
     mediaplayer.cpp \
     IMediaCodecList.cpp \
     IMediaCodecService.cpp \
diff --git a/media/libmedia/BufferingSettings.cpp b/media/libmedia/BufferingSettings.cpp
new file mode 100644
index 0000000..6dc4a53
--- /dev/null
+++ b/media/libmedia/BufferingSettings.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BufferingSettings"
+//#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+
+#include <media/BufferingSettings.h>
+
+namespace android {
+
+// static
+bool BufferingSettings::IsValidBufferingMode(int mode) {
+    return (mode >= BUFFERING_MODE_NONE && mode < BUFFERING_MODE_COUNT);
+}
+
+BufferingSettings::BufferingSettings()
+        : mInitialBufferingMode(BUFFERING_MODE_NONE),
+          mRebufferingMode(BUFFERING_MODE_NONE),
+          mInitialWatermarkMs(kNoWatermark),
+          mInitialWatermarkKB(kNoWatermark),
+          mRebufferingWatermarkLowMs(kNoWatermark),
+          mRebufferingWatermarkHighMs(kNoWatermark),
+          mRebufferingWatermarkLowKB(kNoWatermark),
+          mRebufferingWatermarkHighKB(kNoWatermark) { }
+
+status_t BufferingSettings::readFromParcel(const Parcel* parcel) {
+    if (parcel == nullptr) {
+        return BAD_VALUE;
+    }
+    mInitialBufferingMode = (BufferingMode)parcel->readInt32();
+    mRebufferingMode = (BufferingMode)parcel->readInt32();
+    mInitialWatermarkMs = parcel->readInt32();
+    mInitialWatermarkKB = parcel->readInt32();
+    mRebufferingWatermarkLowMs = parcel->readInt32();
+    mRebufferingWatermarkHighMs = parcel->readInt32();
+    mRebufferingWatermarkLowKB = parcel->readInt32();
+    mRebufferingWatermarkHighKB = parcel->readInt32();
+
+    return OK;
+}
+
+status_t BufferingSettings::writeToParcel(Parcel* parcel) const {
+    if (parcel == nullptr) {
+        return BAD_VALUE;
+    }
+    parcel->writeInt32(mInitialBufferingMode);
+    parcel->writeInt32(mRebufferingMode);
+    parcel->writeInt32(mInitialWatermarkMs);
+    parcel->writeInt32(mInitialWatermarkKB);
+    parcel->writeInt32(mRebufferingWatermarkLowMs);
+    parcel->writeInt32(mRebufferingWatermarkHighMs);
+    parcel->writeInt32(mRebufferingWatermarkLowKB);
+    parcel->writeInt32(mRebufferingWatermarkHighKB);
+
+    return OK;
+}
+
+} // namespace android
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index dda2570..9ffde4e 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -23,6 +23,7 @@
 
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
+#include <media/BufferingSettings.h>
 
 #include <media/IDataSource.h>
 #include <media/IMediaHTTPService.h>
@@ -40,6 +41,8 @@
     SET_DATA_SOURCE_FD,
     SET_DATA_SOURCE_STREAM,
     SET_DATA_SOURCE_CALLBACK,
+    SET_BUFFERING_SETTINGS,
+    GET_DEFAULT_BUFFERING_SETTINGS,
     PREPARE_ASYNC,
     START,
     STOP,
@@ -148,6 +151,30 @@
         return reply.readInt32();
     }
 
+    status_t setBufferingSettings(const BufferingSettings& buffering)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        buffering.writeToParcel(&data);
+        remote()->transact(SET_BUFFERING_SETTINGS, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */)
+    {
+        if (buffering == nullptr) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(GET_DEFAULT_BUFFERING_SETTINGS, data, &reply);
+        status_t err = reply.readInt32();
+        if (err == OK) {
+            err = buffering->readFromParcel(&reply);
+        }
+        return err;
+    }
+
     status_t prepareAsync()
     {
         Parcel data, reply;
@@ -497,6 +524,23 @@
             reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
             return NO_ERROR;
         } break;
+        case SET_BUFFERING_SETTINGS: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            BufferingSettings buffering;
+            buffering.readFromParcel(&data);
+            reply->writeInt32(setBufferingSettings(buffering));
+            return NO_ERROR;
+        } break;
+        case GET_DEFAULT_BUFFERING_SETTINGS: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            BufferingSettings buffering;
+            status_t err = getDefaultBufferingSettings(&buffering);
+            reply->writeInt32(err);
+            if (err == OK) {
+                buffering.writeToParcel(reply);
+            }
+            return NO_ERROR;
+        } break;
         case PREPARE_ASYNC: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             reply->writeInt32(prepareAsync());
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index c1fe87f..3d466b1 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -590,7 +590,7 @@
                     params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
                             MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
                 }
-                if (params != MAP_FAILED) {
+                if (params != MAP_FAILED && params != NULL) {
                     err = data.read(params, size);
                     if (err != OK) {
                         android_errorWriteLog(0x534e4554, "26914474");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6e163d9..3ad461c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -972,6 +972,42 @@
     return OK;
 }
 
+status_t MediaPlayerService::Client::setBufferingSettings(
+        const BufferingSettings& buffering)
+{
+    ALOGV("[%d] setBufferingSettings(%d, %d, %d, %d, %d, %d, %d, %d)",
+            mConnId, buffering.mInitialBufferingMode, buffering.mRebufferingMode,
+            buffering.mInitialWatermarkMs, buffering.mInitialWatermarkKB,
+            buffering.mRebufferingWatermarkLowMs,
+            buffering.mRebufferingWatermarkHighMs,
+            buffering.mRebufferingWatermarkLowKB,
+            buffering.mRebufferingWatermarkHighKB);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->setBufferingSettings(buffering);
+}
+
+status_t MediaPlayerService::Client::getDefaultBufferingSettings(
+        BufferingSettings* buffering /* nonnull */)
+{
+    sp<MediaPlayerBase> p = getPlayer();
+    // TODO: create mPlayer on demand.
+    if (p == 0) return UNKNOWN_ERROR;
+    status_t ret = p->getDefaultBufferingSettings(buffering);
+    if (ret == NO_ERROR) {
+        ALOGV("[%d] getDefaultBufferingSettings(%d, %d, %d, %d, %d, %d, %d, %d)",
+                mConnId, buffering->mInitialBufferingMode, buffering->mRebufferingMode,
+                buffering->mInitialWatermarkMs, buffering->mInitialWatermarkKB,
+                buffering->mRebufferingWatermarkLowMs,
+                buffering->mRebufferingWatermarkHighMs,
+                buffering->mRebufferingWatermarkLowKB,
+                buffering->mRebufferingWatermarkHighKB);
+    } else {
+        ALOGV("[%d] getDefaultBufferingSettings returned %d", mConnId, ret);
+    }
+    return ret;
+}
+
 status_t MediaPlayerService::Client::prepareAsync()
 {
     ALOGV("[%d] prepareAsync", mConnId);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index a4ea37f..8a6ada0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -288,6 +288,9 @@
         virtual void            disconnect();
         virtual status_t        setVideoSurfaceTexture(
                                         const sp<IGraphicBufferProducer>& bufferProducer);
+        virtual status_t        setBufferingSettings(const BufferingSettings& buffering) override;
+        virtual status_t        getDefaultBufferingSettings(
+                                        BufferingSettings* buffering /* nonnull */) override;
         virtual status_t        prepareAsync();
         virtual status_t        start();
         virtual status_t        stop();
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 3a04651..ec9ced2 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1287,36 +1287,54 @@
         // particular client process:  no risk to block the whole media server process or mixer
         // threads if we are stuck here
         Mutex::Autolock _l(mCblk->lock);
-        if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
-            mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
+
+        // keep local copy of index in case of client corruption b/32220769
+        const uint32_t clientIndex = mCblk->clientIndex;
+        const uint32_t serverIndex = mCblk->serverIndex;
+        if (clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
+            serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
             mCblk->serverIndex = 0;
             mCblk->clientIndex = 0;
             return BAD_VALUE;
         }
         status_t status = NO_ERROR;
-        while (mCblk->serverIndex < mCblk->clientIndex) {
-            int reply;
-            uint32_t rsize = sizeof(int);
-            int *p = (int *)(mBuffer + mCblk->serverIndex);
-            int size = *p++;
-            if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
+        effect_param_t *param = NULL;
+        for (uint32_t index = serverIndex; index < clientIndex;) {
+            int *p = (int *)(mBuffer + index);
+            const int size = *p++;
+            if (size < 0
+                    || size > EFFECT_PARAM_BUFFER_SIZE
+                    || ((uint8_t *)p + size) > mBuffer + clientIndex) {
                 ALOGW("command(): invalid parameter block size");
+                status = BAD_VALUE;
                 break;
             }
-            effect_param_t *param = (effect_param_t *)p;
-            if (param->psize == 0 || param->vsize == 0) {
-                ALOGW("command(): null parameter or value size");
-                mCblk->serverIndex += size;
-                continue;
+
+            // copy to local memory in case of client corruption b/32220769
+            param = (effect_param_t *)realloc(param, size);
+            if (param == NULL) {
+                ALOGW("command(): out of memory");
+                status = NO_MEMORY;
+                break;
             }
-            uint32_t psize = sizeof(effect_param_t) +
-                             ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
-                             param->vsize;
+            memcpy(param, p, size);
+
+            int reply = 0;
+            uint32_t rsize = sizeof(reply);
             status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
-                                            psize,
-                                            p,
+                                            size,
+                                            param,
                                             &rsize,
                                             &reply);
+
+            // verify shared memory: server index shouldn't change; client index can't go back.
+            if (serverIndex != mCblk->serverIndex
+                    || clientIndex > mCblk->clientIndex) {
+                android_errorWriteLog(0x534e4554, "32220769");
+                status = BAD_VALUE;
+                break;
+            }
+
             // stop at first error encountered
             if (ret != NO_ERROR) {
                 status = ret;
@@ -1326,8 +1344,9 @@
                 *(int *)pReplyData = reply;
                 break;
             }
-            mCblk->serverIndex += size;
+            index += size;
         }
+        free(param);
         mCblk->serverIndex = 0;
         mCblk->clientIndex = 0;
         return status;
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 818da72..a224004 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -384,6 +384,7 @@
             sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
             if (source == NULL) {
                 ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
+                free(sourcesLiteral);
                 return BAD_VALUE;
             }
             sources.add(source);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5ef0216..a714041 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4477,9 +4477,7 @@
 
 bool AudioPolicyManager::streamsMatchForvolume(audio_stream_type_t stream1,
                                                audio_stream_type_t stream2) {
-    return ((stream1 == stream2) ||
-            ((stream1 == AUDIO_STREAM_ACCESSIBILITY) && (stream2 == AUDIO_STREAM_MUSIC)) ||
-            ((stream1 == AUDIO_STREAM_MUSIC) && (stream2 == AUDIO_STREAM_ACCESSIBILITY)));
+    return (stream1 == stream2);
 }
 
 uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) {
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index bcd62d6..bfbf640 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -993,7 +993,7 @@
 }
 
 status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
-    status_t res;
+    status_t res = OK;
 
     ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);