diff --git a/fuzzing/fuzz/Android.bp b/fuzzing/fuzz/Android.bp
new file mode 100644
index 0000000000000000000000000000000000000000..1057c17d4e1ab574047175a534d4d899254075cb
--- /dev/null
+++ b/fuzzing/fuzz/Android.bp
@@ -0,0 +1,5 @@
+cc_prebuilt_binary {
+    name: "fuzz",
+    srcs: ["fuzz"]
+}
+
diff --git a/fuzzing/fuzz/fuzz b/fuzzing/fuzz/fuzz
new file mode 100644
index 0000000000000000000000000000000000000000..5d0975418db384c1d764b2c15e8cf90670f3b516
--- /dev/null
+++ b/fuzzing/fuzz/fuzz
@@ -0,0 +1,263 @@
+#!/system/bin/sh
+# Copyright (C) 2018 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.
+# Abort on any error
+
+# Global configuration
+FUZZER_BASE="/data/nativetest64/fuzzers"
+WORK_BASE="/data/local/tmp/fuzz"
+LAST_FUZZ="$WORK_BASE/last_session"
+
+#------------------------------ HELPER FUNCTIONS ------------------------------
+function die() {
+    echo "$@" >&2
+    exit 1
+}
+
+# Print the usage and exit.
+# Optionally takes an extra string to print.
+function usage() {
+    die "\
+Usage: $0 [-a artifacts_path] [-c corpus] [-e engine] [-l logname] [-n new_corpus] [-w workdir] fuzzer [-- fuzzer_option...]
+
+Run a fuzzing session.
+
+All of the information on the most recent session is symlinked at $LAST_FUZZ,
+which points to the most recent session's working directory.
+
+The working directory is standardized to contain the following directories (or symlinks,
+if non-default options are provided):
+
+    artifacts/      Crashing test cases and other fuzzer output
+    corpus/         Input corpus
+    corpus_new/     Mutated test cases which exercise coverage features not represented
+                    in the input corpus.
+    fuzz.log        Contents of stdout from the fuzzing session.
+
+Arguments:
+    fuzzer          Name of the fuzzer, e.g. cxa_demangle_fuzzer, or a full path to the fuzzer
+    fuzzer_option   Fuzzer-specific arguments
+
+Options:
+    -a  Path where fuzzer artifacts (logs, timeouts, crashes) should be stored
+        (Default: \$WORK/artifacts)
+
+    -c  Path where input corpus is stored.  Must not be empty.
+        (Default: \$WORK/corpus)
+
+    -e  Fuzzer engine to use.  Defaults to libFuzzer.
+
+    -l  Filename to use for the fuzzer log.
+        (Default: fuzz.log)
+
+    -n  Path to store new corpus elements
+        (Default: \$WORK/corpus_new)
+
+    -w  Work directory to use
+        (Default: $WORK_BASE/\$FUZZER)
+
+Examples:
+
+    $ adb shell fuzz IOMX
+    $ adb shell fuzz -e honggfuzz IOMX
+    $ adb shell fuzz -w /sdcard        IOMX
+    $ adb shell fuzz -c /sdcard/corpus IOMX
+    $ adb shell fuzz /data/my_fuzzer -- --foo --bar
+$@"
+}
+
+# Create a symlink from $1 ==> $2, if $2 is specified.
+# Otherwise, ensure $1 exists and is a directory.
+function symlink_or_create() {
+    DIR=$1
+    TARGET=$2
+    if [ -n "$TARGET" ]; then
+        if [ ! -d "$TARGET" ]; then
+            die "Directory does not exist: $TARGET"
+        fi
+        rm -rf "$DIR"
+        ln -sv "$TARGET" "$DIR"
+    elif [ ! -d "$DIR" ]; then
+        mkdir -p "$DIR"
+    fi
+}
+
+# Ensure that there is "enough space" left on the device for
+# the path provided.
+function ensure_space() {
+    FREE_SPACE=$(df $1 | tail -1 | awk '{print $4}')
+    TEN_MEGABYTES=$((1024*10))
+
+    if [ $FREE_SPACE -lt $TEN_MEGABYTES ]; then
+        die "Not enough free space available at $(realpath $1):\n$(df -h $1)"
+    fi
+}
+
+# Ensure that the provided directory is not empty.
+function ensure_not_empty() {
+    if [ "$(find -H $1 -type f | wc -l)" -eq "0" ]; then
+        die "$1 is empty"
+    fi
+}
+
+#--------------------------- CHECK SYSTEM VIABILITY ---------------------------
+# Make sure ASAN and coverage work
+if ! sanitizer-status asan cov &>/dev/null; then
+    # repeat the command to show the output
+    die "Sanitizer Checks Failed!\n$(sanitizer-status)"
+fi
+
+#------------------------------ CHECK ARGUMENTS -------------------------------
+# Determine what fuzzer we want to run, and ensure that it's on the device
+OPT_ARTIFACTS=""
+OPT_CORPUS=""
+OPT_CORPUS_NEW=""
+OPT_ENGINE="libFuzzer"
+OPT_LOG="fuzz.log"
+OPT_WORKDIR=""
+
+while getopts "a:c:e:l:n:w:" o; do
+    case "${o}" in
+        a) OPT_ARTIFACTS="${OPTARG}" ;;
+        c) OPT_CORPUS="${OPTARG}" ;;
+        e) OPT_ENGINE="${OPTARG}" ;;
+        l) OPT_LOG="${OPTARG}" ;;
+        n) OPT_CORPUS_NEW="${OPTARG}" ;;
+        w) OPT_WORKDIR="${OPTARG}" ;;
+        *) usage ;;
+    esac
+done
+
+shift $((OPTIND-1))
+
+if [ $# -lt 1 ]; then
+    usage "\nMissing arguments: fuzzer"
+fi
+
+if [ -e $1 ]; then
+    FUZZER_BIN="$1"
+    FUZZER="$(basename $FUZZER_BIN)"
+else
+    FUZZER="${1%_fuzzer}"
+    FUZZER_BIN="${FUZZER_BASE}/${OPT_ENGINE}/${FUZZER}_fuzzer"
+
+    if [ ! -e "$FUZZER_BIN" ]; then
+        die "Invalid fuzzer name ${FUZZER}: ($FUZZER_BIN does not exist)"
+    fi
+fi
+
+shift
+
+if [ ! -e "$FUZZER_BIN" ]; then
+    die "Invalid fuzzer path $FUZZER_BIN: File does not exist"
+fi
+
+#------------------------- CREATE DIRECTORY STRUCTURE -------------------------
+# First set up the root work directory.
+#
+# This directory is the default location where the corpus/, corpus_new/, and
+# artifacts/ directories will be created.
+#
+# We also create symlinks here if any of those options are provided, so that
+# the same directory structure is always available, and any external utilities
+# can easily find the last fuzzing session's data.
+WORK_ROOT="$WORK_BASE/$FUZZER"
+symlink_or_create "$WORK_ROOT"  "$OPT_WORKDIR"
+WORK_ROOT="${OPT_WORKDIR:-$WORK_ROOT}"
+
+# Change into the work root, in case any of the OPT_XXX paths are relative.
+cd "$WORK_ROOT"
+
+# Create the rest of the directory structure
+ARTIFACTS="$WORK_ROOT/artifacts"
+CORPUS="$WORK_ROOT/corpus"
+CORPUS_NEW="$WORK_ROOT/corpus_new"
+
+symlink_or_create "$ARTIFACTS"  "$OPT_ARTIFACTS"
+symlink_or_create "$CORPUS"     "$OPT_CORPUS"
+symlink_or_create "$CORPUS_NEW" "$OPT_CORPUS_NEW"
+
+# Update the environment variables so that the "real" paths show up in
+# the command invocation.
+ARTIFACTS="${OPT_ARTIFACTS:-$ARTIFACTS}"
+CORPUS="${OPT_CORPUS:-$CORPUS}"
+CORPUS_NEW="${OPT_CORPUS_NEW:-$CORPUS_NEW}"
+
+# Check the contents of the corpus aren't empty, this indicates a user error.
+ensure_not_empty "$CORPUS"
+
+# Ensure that there's room to grow the corpus / dump artifacts.
+ensure_space "$CORPUS_NEW"
+ensure_space "$ARTIFACTS"
+
+#------------------------- UPDATE ENVIRONMENT OPTIONS -------------------------
+# Set up the ASAN_OPTIONS for optimal everything
+# Note that we are only appending options, so that we do not override the
+# default-at-boot ASAN_OPTIONS (e.g include=/system/asan.options).
+
+ASAN_OPTIONS+=:coverage=1
+ASAN_OPTIONS+=:atexit=1
+# ASAN_OPTIONS+=:verbosity=2
+ASAN_OPTIONS+=:print_cmdline=1
+ASAN_OPTIONS+=:print_stats=1
+ASAN_OPTIONS+=:print_legend=1
+ASAN_OPTIONS+=:print_scariness=1
+ASAN_OPTIONS+=:log_path=/dev/null
+
+export ASAN_OPTIONS="$ASAN_OPTIONS"
+echo "ASAN_OPTIONS=$ASAN_OPTIONS"
+
+
+#---------------------------- BUILD FUZZER COMMAND ----------------------------
+# Based on the fuzzer engine selected, build up the command line.
+case "${OPT_ENGINE}" in
+    libFuzzer)
+        # NOTE: We use '-jobs=-1' to get libFuzzer to fuzz forever.
+        set -A FUZZ_CMD -- \
+        "$FUZZER_BIN" \
+            -artifact_prefix="$ARTIFACTS" \
+            -print_coverage=1 \
+            -detect_leaks=0 \
+            -jobs=-1 \
+            "$CORPUS_NEW" \
+            "$CORPUS" \
+            "$@"
+        ;;
+    honggfuzz)
+        set -A FUZZ_CMD -- \
+        honggfuzz \
+            --persistent \
+            --sanitizers \
+            --tmout_sigvtalrm \
+            --workspace "$ARTIFACTS" \
+            --input "$CORPUS_NEW" \
+            --covdir_new "$CORPUS_NEW" \
+            -- "$FUZZER_BIN" "$@"
+        ;;
+    *)
+        die "Unknown fuzzer engine $FUZZER_TYPE"
+        ;;
+esac
+
+#--------------------------------- RUN FUZZER ---------------------------------
+# Set up a symlink for the "last fuzz session" so that we can easily find it.
+ln -svf "$WORK_ROOT" "$LAST_FUZZ"
+
+# Change into the artifacts directory, so that anything
+# the fuzzer emits to $PWD will also be captured.
+cd "$ARTIFACTS"
+
+echo "Running fuzzer: ${FUZZ_CMD[@]}"
+echo "------------------------------"
+${FUZZ_CMD[@]} | tee "${OPT_LOG}"