[RESTRICT AUTOMERGE] Updated AdbUtils.java and memutils file

Added functions in AdbUtils.java which enable testing for both hangs and crashes
Updated memutils file to support different configurations

Bug: 147497306
Test: none

Change-Id: I554ac7674317cf203206411b69e6e4ef31883e75
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 62f866d..8d4203e 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -204,6 +204,20 @@
         <option name="test-file-name" value="CtsHostLaunchAnyWhereApp.apk" />
     </target_preparer>
 
+    <!-- The following tests hit either 32-bit or 64-bit, but not both. All tests in this -->
+    <!-- section should take care to build either 32 bit or 64 bit binary, but not both.  -->
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+
+        <!-- Please add 32-bit binary tests below to avoid merge conflict -->
+
+
+        <!-- Please add 64-bit binary tests below to avoid merge conflict -->
+
+
+        <option name="append-bitness" value="false" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="OomCatcher.apk" />
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.c b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
new file mode 100644
index 0000000..650d2f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
@@ -0,0 +1,267 @@
+/**
+ * Copyright (C) 2019 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 <sys/mman.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include "memutils.h"
+
+void exit_handler(void) {
+    size_t page_size = getpagesize();
+    for (int i = 0; i < s_mem_map_index; i++) {
+        if (NULL != s_mem_map[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                              (s_mem_map[i].num_pages * page_size));
+        }
+    }
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+    for (int i = 0; i < MAX_ENTRIES; i++) {
+        if (NULL != s_free_list[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_free_list[i].start_ptr,
+                    (s_free_list[i].num_pages * page_size));
+            real_free(s_free_list[i].start_ptr);
+            memset(&s_free_list[i], 0, sizeof(map_struct_t));
+        }
+    }
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void* context) {
+    exit_handler();
+    (*old_sa.sa_sigaction)(signum, info, context);
+}
+
+void sighandler_init(void) {
+    sigemptyset(&new_sa.sa_mask);
+    new_sa.sa_flags = SA_SIGINFO;
+    new_sa.sa_sigaction = sigsegv_handler;
+    sigaction(SIGSEGV, &new_sa, &old_sa);
+}
+
+void memutils_init(void) {
+    real_memalign = dlsym(RTLD_NEXT, "memalign");
+    if (NULL == real_memalign) {
+        return;
+    }
+    real_calloc = dlsym(RTLD_NEXT, "calloc");
+    if (NULL == real_calloc) {
+        return;
+    }
+    real_malloc = dlsym(RTLD_NEXT, "malloc");
+    if (NULL == real_malloc) {
+        return;
+    }
+    real_realloc = dlsym(RTLD_NEXT, "realloc");
+    if (NULL == real_realloc) {
+        return;
+    }
+    real_free = dlsym(RTLD_NEXT, "free");
+    if (NULL == real_free) {
+        return;
+    }
+    memset(&s_mem_map, 0, MAX_ENTRIES * sizeof(map_struct_t));
+    sighandler_init();
+    atexit(exit_handler);
+    s_memutils_initialized = 1;
+}
+
+void *memalign(size_t alignment, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MEMALIGN_CHECK) != ENABLE_MEMALIGN_CHECK) {
+        return real_memalign(alignment, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    char* start_ptr;
+    char* mem_ptr;
+    size_t total_size;
+    size_t aligned_size = size;
+    size_t num_pages;
+    size_t page_size = getpagesize();
+
+    /* User specified alignment is not respected and is overridden by
+     * "new_alignment". This is required to catch OOB read when read offset is
+     * less than user specified alignment. "new_alignment" is derived based on
+     * size_t, and helps to avoid bus errors due to non-aligned memory.
+     * "new_alignment", whenever used, is checked to ensure sizeof(size_t)
+     * has returned proper value                                            */
+    size_t new_alignment = sizeof(size_t);
+
+    if (s_mem_map_index == MAX_ENTRIES) {
+        return real_memalign(alignment, size);
+    }
+
+    if (alignment > page_size) {
+        return real_memalign(alignment, size);
+    }
+
+    if ((0 == page_size) || (0 == alignment) || (0 == size)
+            || (0 == new_alignment)) {
+        return real_memalign(alignment, size);
+    }
+#ifdef CHECK_OVERFLOW
+    if (0 != (size % new_alignment)) {
+        aligned_size = size + (new_alignment - (size % new_alignment));
+    }
+#endif
+
+    if (0 != (aligned_size % page_size)) {
+        num_pages = (aligned_size / page_size) + 2;
+    } else {
+        num_pages = (aligned_size / page_size) + 1;
+    }
+
+    total_size = (num_pages * page_size);
+    start_ptr = (char *) real_memalign(page_size, total_size);
+#ifdef CHECK_OVERFLOW
+#ifdef FORCE_UNALIGN
+    mem_ptr = (char *) start_ptr + ((num_pages - 1) * page_size) - size;
+#else
+    mem_ptr = (char *) start_ptr + ((num_pages - 1) * page_size) - aligned_size;
+#endif /* FORCE_UNALIGN */
+    DISABLE_MEM_ACCESS((start_ptr + ((num_pages - 1) * page_size)), page_size);
+#endif /* CHECK_OVERFLOW */
+#ifdef CHECK_UNDERFLOW
+    mem_ptr = (char *) start_ptr + page_size;
+    DISABLE_MEM_ACCESS(start_ptr, page_size);
+#endif /* CHECK_UNDERFLOW */
+    s_mem_map[s_mem_map_index].start_ptr = start_ptr;
+    s_mem_map[s_mem_map_index].mem_ptr = mem_ptr;
+    s_mem_map[s_mem_map_index].num_pages = num_pages;
+    s_mem_map[s_mem_map_index].mem_size = size;
+    s_mem_map_index++;
+    memset(mem_ptr, INITIAL_VAL, size);
+    return mem_ptr;
+}
+
+void *malloc(size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MALLOC_CHECK) != ENABLE_MALLOC_CHECK) {
+        return real_malloc(size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    return memalign(sizeof(size_t), size);
+}
+
+void *calloc(size_t nitems, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_CALLOC_CHECK) != ENABLE_CALLOC_CHECK) {
+        return real_calloc(nitems, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    void *ptr = memalign(sizeof(size_t), (nitems * size));
+    if (ptr)
+        memset(ptr, 0, (nitems * size));
+    return ptr;
+}
+
+void *realloc(void *ptr, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_REALLOC_CHECK) != ENABLE_REALLOC_CHECK) {
+        return real_realloc(ptr, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    if (ptr != NULL) {
+        int i = 0;
+        for (i = 0; i < s_mem_map_index; i++) {
+            if (ptr == s_mem_map[i].mem_ptr) {
+                void* temp = malloc(size);
+                if (temp == NULL) {
+                    return NULL;
+                }
+                if (s_mem_map[i].mem_size > size) {
+                    memcpy(temp, ptr, size);
+                } else {
+                    memcpy(temp, ptr, s_mem_map[i].mem_size);
+                }
+                free(s_mem_map[i].mem_ptr);
+                return temp;
+            }
+        }
+    }
+    return real_realloc(ptr, size);
+}
+
+void free(void *ptr) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_FREE_CHECK) != ENABLE_FREE_CHECK) {
+        return real_free(ptr);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    if (ptr != NULL) {
+        int i = 0;
+        size_t page_size = getpagesize();
+        for (i = 0; i < s_mem_map_index; i++) {
+            if (ptr == s_mem_map[i].mem_ptr) {
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+                s_free_list[s_free_write_index].start_ptr =
+                s_mem_map[i].start_ptr;
+                s_free_list[s_free_write_index].mem_ptr = s_mem_map[i].mem_ptr;
+                s_free_list[s_free_write_index].num_pages =
+                s_mem_map[i].num_pages;
+                s_free_list[s_free_write_index].mem_size = s_mem_map[i].mem_size;
+                s_free_write_index++;
+                s_free_list_size += s_mem_map[i].mem_size;
+                DISABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                        (s_mem_map[i].num_pages * page_size));
+                memset(&s_mem_map[i], 0, sizeof(map_struct_t));
+                while (s_free_list_size > CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE) {
+                    ENABLE_MEM_ACCESS(
+                            s_free_list[s_free_read_index].start_ptr,
+                            (s_free_list[s_free_read_index].num_pages * page_size));
+                    real_free(s_free_list[s_free_read_index].start_ptr);
+                    s_free_list_size -= s_free_list[s_free_read_index].mem_size;
+                    memset(&s_free_list[s_free_read_index], 0,
+                            sizeof(map_struct_t));
+                    s_free_read_index++;
+                    if ((s_free_read_index == MAX_ENTRIES)
+                            || (s_free_read_index >= s_free_write_index)) {
+                        break;
+                    }
+                }
+                return;
+#else
+                ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                                  (s_mem_map[i].num_pages * page_size));
+                real_free(s_mem_map[i].start_ptr);
+                memset(&s_mem_map[i], 0, sizeof(map_struct_t));
+                return;
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+            }
+        }
+    }
+    real_free(ptr);
+    return;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.h b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
new file mode 100644
index 0000000..10ee31e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2019 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#define MAX_ENTRIES        (1024 * 1024)
+#define INITIAL_VAL        (0xBE)
+
+#define DISABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_NONE);
+
+#define ENABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_READ | PROT_WRITE);
+
+#define ENABLE_NONE               0x00
+#define ENABLE_MEMALIGN_CHECK     0x01
+#define ENABLE_MALLOC_CHECK       0x02
+#define ENABLE_CALLOC_CHECK       0x04
+#define ENABLE_REALLOC_CHECK      0x08
+#define ENABLE_FREE_CHECK         0x10
+#define ENABLE_ALL                ENABLE_MEMALIGN_CHECK | ENABLE_MALLOC_CHECK |\
+    ENABLE_CALLOC_CHECK | ENABLE_REALLOC_CHECK | ENABLE_FREE_CHECK
+
+typedef struct _map_struct_t {
+    void *start_ptr;
+    void *mem_ptr;
+    int num_pages;
+    size_t mem_size;
+} map_struct_t;
+
+static void* (*real_memalign)(size_t, size_t) = NULL;
+static void* (*real_calloc)(size_t, size_t) = NULL;
+static void* (*real_malloc)(size_t) = NULL;
+static void* (*real_realloc)(void *ptr, size_t size) = NULL;
+static void (*real_free)(void *) = NULL;
+static int s_memutils_initialized = 0;
+static int s_mem_map_index = 0;
+static struct sigaction new_sa, old_sa;
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+extern char enable_selective_overload;
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+static int s_free_write_index = 0;
+static int s_free_read_index = 0;
+static int s_free_list_size = 0;
+map_struct_t s_free_list[MAX_ENTRIES];
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+map_struct_t s_mem_map[MAX_ENTRIES];
+#if (!(defined CHECK_OVERFLOW) && !(defined CHECK_UNDERFLOW))
+    #error "CHECK MACROS NOT DEFINED"
+#endif
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
index 85b8422..ac28dba 100644
--- a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
@@ -24,6 +24,7 @@
 int32_t mLastMsgGeneration;
 int32_t mCurGeneration;
 List<omx_message> mMessageQueue;
+int numCallbackEmptyBufferDone;
 
 struct CodecObserver : public BnOMXObserver {
  public:
@@ -42,7 +43,11 @@
     Mutex::Autolock autoLock(mLock);
     for (std::list<omx_message>::const_iterator it = messages.cbegin();
             it != messages.cend();) {
-        mMessageQueue.push_back(*it++);
+        mMessageQueue.push_back(*it);
+        const omx_message &msg = *it++;
+        if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
+            numCallbackEmptyBufferDone++;
+        }
         mLastMsgGeneration = gen;
     }
     mMessageAddedCondition.signal();
@@ -51,6 +56,22 @@
     handleMessages(mGeneration, messages);
 }
 
+struct DeathNotifier : public IBinder::DeathRecipient,
+        public ::android::hardware::hidl_death_recipient {
+    explicit DeathNotifier() {
+    }
+    virtual void binderDied(const wp<IBinder> &) {
+        ALOGE("Binder Died");
+        exit (EXIT_FAILURE);
+    }
+    virtual void serviceDied(
+            uint64_t /* cookie */,
+            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
+        ALOGE("Service Died");
+        exit (EXIT_FAILURE);
+    }
+};
+sp<DeathNotifier> mDeathNotifier;
 status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
     int64_t finishBy = ALooper::GetNowUs() + timeoutUs;
     status_t err = OK;
@@ -98,7 +119,19 @@
     }
     mOMX = new utils::LWOmx(tOmx);
     sp<CodecObserver> observer = new CodecObserver(++mCurGeneration);
-    return mOMX->allocateNode(codecName, observer, &mOMXNode);
+    status_t ret = mOMX->allocateNode(codecName, observer, &mOMXNode);
+    if (ret == OK) {
+        mDeathNotifier = new DeathNotifier();
+        auto tOmxNode = mOMXNode->getHalInterface();
+        if (tOmxNode != NULL) {
+            tOmxNode->linkToDeath(mDeathNotifier, 0);
+        } else {
+            ALOGE("No HAL Interface");
+            exit (EXIT_FAILURE);
+        }
+    }
+    numCallbackEmptyBufferDone = 0;
+    return ret;
 }
 status_t omxUtilsGetParameter(int portIndex,
                               OMX_PARAM_PORTDEFINITIONTYPE *params) {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index bc71522..2b865e1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -34,6 +34,9 @@
 import java.util.regex.Pattern;
 import java.util.concurrent.TimeUnit;
 import java.util.Scanner;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -46,6 +49,10 @@
 
 public class AdbUtils {
 
+    final static String TMP_PATH = "/data/local/tmp/";
+    final static int TIMEOUT_SEC = 9 * 60;
+    final static String RESOURCE_ROOT = "/";
+
     /** Runs a commandline on the specified device
      *
      * @param command the command to be ran
@@ -217,6 +224,40 @@
         }
     }
 
+    /**
+     * Pushes the specified files to the specified destination directory
+     *
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     */
+    public static void pushResources(String[] inputFiles, String inputFilesDestination,
+            ITestDevice device) throws Exception {
+        if ( (inputFiles != null) && (inputFilesDestination != null)) {
+            for (String tempFile : inputFiles) {
+                pushResource(RESOURCE_ROOT + tempFile, inputFilesDestination + tempFile, device);
+            }
+        }
+    }
+
+    /**
+     * Removes the specified files from the specified destination directory
+     *
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory where input files are
+     *        present
+     * @param device device to be run on
+     */
+    public static void removeResources(String[] inputFiles, String inputFilesDestination,
+            ITestDevice device) throws Exception {
+        if ( (inputFiles != null) && (inputFilesDestination != null)) {
+            for (String tempFile : inputFiles) {
+                runCommandLine("rm " + inputFilesDestination + tempFile, device);
+            }
+        }
+    }
+
    /**
      * Extracts the binary data from a resource and writes it to a temp file
      */
@@ -277,9 +318,22 @@
      */
     public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout)
             throws Exception {
-        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
+       return runPocGetExitStatus(pocName, null, device, timeout);
+    }
+
+    /**
+     * Pushes and runs a binary to the device and returns the exit status.
+     * @param pocName a string path to poc from the /res folder
+     * @param arguments input arguments for the poc
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+
+     */
+    public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device,
+            int timeout) throws Exception {
+        device.executeShellCommand("chmod +x " + TMP_PATH + pocName);
         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        String cmd = "/data/local/tmp/" + pocName + " > /dev/null 2>&1; echo $?";
+        String cmd = TMP_PATH + pocName + " " + arguments + " > /dev/null 2>&1; echo $?";
         long time = System.currentTimeMillis();
         device.executeShellCommand(cmd, receiver, timeout, TimeUnit.SECONDS, 0);
         time = System.currentTimeMillis() - time;
@@ -301,8 +355,20 @@
      */
     public static void runPocAssertExitStatusNotVulnerable(
             String pocName, ITestDevice device, int timeout) throws Exception {
+        runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout);
+    }
+
+    /**
+     * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     * @param pocName a string path to poc from the /res folder
+     * @param arguments input arguments for the poc
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     */
+    public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments,
+            ITestDevice device, int timeout) throws Exception {
         assertTrue("PoC returned exit status 113: vulnerable",
-                runPocGetExitStatus(pocName, device, timeout) != 113);
+                runPocGetExitStatus(pocName, arguments, device, timeout) != 113);
     }
 
     public static int runProxyAutoConfig(String pacName, ITestDevice device) throws Exception {
@@ -329,6 +395,99 @@
     }
 
     /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param device device to be run on
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            ITestDevice device) throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, null);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param device device to be run on
+     * @param processPatternStrings a Pattern string to match the crash tombstone
+     *        process
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            ITestDevice device, String processPatternStrings[]) throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device,
+                processPatternStrings);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            String inputFiles[], String inputFilesDestination, ITestDevice device)
+            throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, inputFiles, inputFilesDestination,
+                device, null);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 3 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. There are no security crashes that match the expected process pattern.
+     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     * @param processPatternStrings a Pattern string to match the crash tombstone
+     *        process
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            String inputFiles[], String inputFilesDestination, ITestDevice device,
+            String processPatternStrings[]) throws Exception {
+        pushResources(inputFiles, inputFilesDestination, device);
+        runCommandLine("logcat -c", device);
+        try {
+            runPocAssertExitStatusNotVulnerable(binaryName, arguments, device, TIMEOUT_SEC);
+        } catch (IllegalArgumentException e) {
+            /*
+             * Since 'runPocGetExitStatus' method raises IllegalArgumentException upon
+             * hang/timeout, catching the exception here and ignoring it. Hangs are of
+             * Moderate severity and hence patches may not be ported. This piece of code can
+             * be removed once 'runPocGetExitStatus' is updated to handle hangs.
+             */
+            CLog.w("Ignoring IllegalArgumentException: " + e);
+        } finally {
+            removeResources(inputFiles, inputFilesDestination, device);
+        }
+        List<String> processPatternList = new ArrayList<>();
+        if (processPatternStrings != null) {
+            processPatternList.addAll(Arrays.asList(processPatternStrings));
+        }
+        processPatternList.add(binaryName);
+        String[] processPatternStringsWithSelf = new String[processPatternList.size()];
+        processPatternList.toArray(processPatternStringsWithSelf);
+        assertNoCrashes(device, processPatternStringsWithSelf);
+    }
+
+    /**
      * Dumps logcat and asserts that there are no security crashes that match the expected process.
      * By default, checks min crash addresses
      * pattern. Ensure that adb logcat -c is called beforehand.
@@ -378,39 +537,4 @@
         }
         fail(error.toString());
      }
-
-    /**
-     * Executes a given poc within a given timeout. Returns error if the
-     * given poc doesnt complete its execution within timeout. It also deletes
-     * the list of files provided.
-     *
-     * @param runner the thread which will be run
-     * @param timeout the timeout within which the thread's execution should
-     *        complete
-     * @param device device to be ran on
-     * @param inputFiles list of files to be deleted
-     */
-    public static void runWithTimeoutDeleteFiles(Runnable runner, int timeout, ITestDevice device,
-            String[] inputFiles) throws Exception {
-        Thread t = new Thread(runner);
-        t.start();
-        boolean test_failed = false;
-        try {
-            t.join(timeout);
-        } catch (InterruptedException e) {
-            test_failed = true;
-        } finally {
-            if (inputFiles != null) {
-                for (String tempFile : inputFiles) {
-                    AdbUtils.runCommandLine("rm /data/local/tmp/" + tempFile, device);
-                }
-            }
-            if (test_failed) {
-                fail("PoC was interrupted");
-            }
-        }
-        if (t.isAlive()) {
-            Assert.fail("PoC not completed within timeout of " + timeout + " ms");
-        }
-    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index ecc086c..4dcb055 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -24,61 +24,27 @@
 @SecurityTest
 public class TestMedia extends SecurityTestCase {
 
-    final static int TIMEOUT_SEC = 9 * 60;
-    final static String RESOURCE_ROOT = "/";
-    final static String TMP_FILE_PATH = "/data/local/tmp/";
 
-    /****************************************************************
-     * To prevent merge conflicts, add tests for N below this comment,
-     * before any existing test methods
-     ****************************************************************/
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for N below this comment, before any
+     * existing test methods
+     ******************************************************************************/
 
 
-    /****************************************************************
-     * To prevent merge conflicts, add tests for O below this comment,
-     * before any existing test methods
-     ****************************************************************/
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for O below this comment, before any
+     * existing test methods
+     ******************************************************************************/
 
 
-    /****************************************************************
-     * To prevent merge conflicts, add tests for P below this comment,
-     * before any existing test methods
-     ****************************************************************/
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for P below this comment, before any
+     * existing test methods
+     ******************************************************************************/
 
-    /**
-     * Pushes input files, runs the PoC and checks for crash and hang
-     *
-     * @param binaryName name of the binary
-     * @param inputFiles files required as input
-     * @param arguments arguments for running the binary
-     * @param device device to be run on
-     * @param errPattern error patterns to be checked for
-     */
-    public static void runMediaTest(String binaryName,
-            String inputFiles[], String arguments, ITestDevice device,
-            String processPatternStrings[]) throws Exception {
-        if (inputFiles != null) {
-            for (String tempFile : inputFiles) {
-                AdbUtils.pushResource(RESOURCE_ROOT + tempFile,
-                        TMP_FILE_PATH + tempFile, device);
-            }
-        }
-        AdbUtils.runCommandLine("logcat -c", device);
-        AdbUtils.runWithTimeoutDeleteFiles(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    AdbUtils.runPocNoOutput(binaryName, device,
-                            TIMEOUT_SEC + 30, arguments);
-                } catch (Exception e) {
-                    CLog.w("Exception: " + e.getMessage());
-                }
-            }
-        }, TIMEOUT_SEC * 1000, device, inputFiles);
 
-        AdbUtils.assertNoCrashes(device, binaryName);
-        if (processPatternStrings != null) {
-            AdbUtils.assertNoCrashes(device, processPatternStrings);
-        }
-    }
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for Q below this comment, before any
+     * existing test methods
+     ******************************************************************************/
 }