Add metadata to modules in test/vts-testcase/fuzz
am: b9c7c40a32

Change-Id: I40b822c5ce2e46496150122863cdd7272e372c6b
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..6027082
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+---
+Language: Cpp
+BasedOnStyle: Google
+ColumnLimit: 80
+IndentWidth: 2
+ContinuationIndentWidth: 4
+---
+Language: Java
+BasedOnStyle: Google
+ColumnLimit: 100
+IndentWidth: 4
+ContinuationIndentWidth: 8
+...
diff --git a/Android.bp b/Android.bp
index a19cdfd..d7d401a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,5 +15,4 @@
 subdirs = [
     "func_fuzzer",
     "iface_fuzzer",
-    "iface_fuzzer/proto",
 ]
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..344e715
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,2 @@
+trong@google.com
+yim@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..6be6e5f
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,6 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp,java
+
diff --git a/func_fuzzer/Android.bp b/func_fuzzer/Android.bp
index 47b7f6b..da7e46a 100644
--- a/func_fuzzer/Android.bp
+++ b/func_fuzzer/Android.bp
@@ -7,6 +7,6 @@
 cc_defaults {
     name: "func_fuzzer_defaults",
     static_libs: [
-        "libLLVMFuzzer"
+        "libFuzzer"
     ],
 }
diff --git a/func_fuzzer/automotive/Android.bp b/func_fuzzer/automotive/Android.bp
index b77a8d7..f39ccaa 100644
--- a/func_fuzzer/automotive/Android.bp
+++ b/func_fuzzer/automotive/Android.bp
@@ -3,5 +3,4 @@
 subdirs = [
     "evs/V1_0",
     "vehicle/V2_0",
-    "vehicle/V2_1",
 ]
diff --git a/func_fuzzer/automotive/vehicle/V2_1/Android.bp b/func_fuzzer/automotive/vehicle/V2_1/Android.bp
deleted file mode 100644
index 3e32f88..0000000
--- a/func_fuzzer/automotive/vehicle/V2_1/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// This file was auto-generated by test/vts-testcase/fuzz/script/update_makefiles.py.
-// Do not edit manually.
-genrule {
-    name: "android.hardware.automotive.vehicle@2.1-vts.func_fuzzer.Vehicle_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/automotive/vehicle/2.1/ $(genDir)/android/hardware/automotive/vehicle/2.1/",
-    srcs: [
-        ":android.hardware.automotive.vehicle@2.1_hal",
-    ],
-    out: [
-        "android/hardware/automotive/vehicle/2.1/Vehicle.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.automotive.vehicle@2.1-vts.func_fuzzer.Vehicle",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.automotive.vehicle@2.1-vts.func_fuzzer.Vehicle_genc++"],
-    shared_libs: [
-        "android.hardware.automotive.vehicle@2.1",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
diff --git a/func_fuzzer/tests/Android.bp b/func_fuzzer/tests/Android.bp
index fcc1baf..fc9b2a3 100644
--- a/func_fuzzer/tests/Android.bp
+++ b/func_fuzzer/tests/Android.bp
@@ -12,8 +12,4 @@
     "memory/V1_0",
     "msgq/V1_0",
     "pointer/V1_0",
-    "versioning/V1_0",
-    "versioning/V2_2",
-    "versioning/V2_3",
-    "versioning/V2_4",
 ]
diff --git a/func_fuzzer/tests/versioning/V1_0/Android.bp b/func_fuzzer/tests/versioning/V1_0/Android.bp
deleted file mode 100644
index edb9650..0000000
--- a/func_fuzzer/tests/versioning/V1_0/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// This file was auto-generated by test/vts-testcase/fuzz/script/update_makefiles.py.
-// Do not edit manually.
-genrule {
-    name: "android.hardware.tests.versioning@1.0-vts.func_fuzzer.Foo_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@1.0 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/1.0/ $(genDir)/android/hardware/tests/versioning/1.0/",
-    srcs: [
-        ":android.hardware.tests.versioning@1.0_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/1.0/Foo.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@1.0-vts.func_fuzzer.Foo",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@1.0-vts.func_fuzzer.Foo_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@1.0",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
diff --git a/func_fuzzer/tests/versioning/V2_2/Android.bp b/func_fuzzer/tests/versioning/V2_2/Android.bp
deleted file mode 100644
index 3a1093a..0000000
--- a/func_fuzzer/tests/versioning/V2_2/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// This file was auto-generated by test/vts-testcase/fuzz/script/update_makefiles.py.
-// Do not edit manually.
-genrule {
-    name: "android.hardware.tests.versioning@2.2-vts.func_fuzzer.Bar_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.2 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.2/ $(genDir)/android/hardware/tests/versioning/2.2/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.2_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.2/Bar.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.2-vts.func_fuzzer.Bar",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.2-vts.func_fuzzer.Bar_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.2",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
-genrule {
-    name: "android.hardware.tests.versioning@2.2-vts.func_fuzzer.Foo_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.2 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.2/ $(genDir)/android/hardware/tests/versioning/2.2/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.2_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.2/Foo.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.2-vts.func_fuzzer.Foo",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.2-vts.func_fuzzer.Foo_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.2",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
diff --git a/func_fuzzer/tests/versioning/V2_3/Android.bp b/func_fuzzer/tests/versioning/V2_3/Android.bp
deleted file mode 100644
index 84ca874..0000000
--- a/func_fuzzer/tests/versioning/V2_3/Android.bp
+++ /dev/null
@@ -1,101 +0,0 @@
-// This file was auto-generated by test/vts-testcase/fuzz/script/update_makefiles.py.
-// Do not edit manually.
-genrule {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Bar_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.3 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.3/ $(genDir)/android/hardware/tests/versioning/2.3/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.3_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.3/Bar.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Bar",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.3-vts.func_fuzzer.Bar_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.3",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
-genrule {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Baz_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.3 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.3/ $(genDir)/android/hardware/tests/versioning/2.3/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.3_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.3/Baz.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Baz",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.3-vts.func_fuzzer.Baz_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.3",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
-genrule {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Foo_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.3 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.3/ $(genDir)/android/hardware/tests/versioning/2.3/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.3_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.3/Foo.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.3-vts.func_fuzzer.Foo",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.3-vts.func_fuzzer.Foo_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.3",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
diff --git a/func_fuzzer/tests/versioning/V2_4/Android.bp b/func_fuzzer/tests/versioning/V2_4/Android.bp
deleted file mode 100644
index 355c0d2..0000000
--- a/func_fuzzer/tests/versioning/V2_4/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// This file was auto-generated by test/vts-testcase/fuzz/script/update_makefiles.py.
-// Do not edit manually.
-genrule {
-    name: "android.hardware.tests.versioning@2.4-vts.func_fuzzer.Foo_genc++",
-    tools: ["hidl-gen", "vtsc"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.4 && $(location vtsc) -mFUZZER -tSOURCE -b$(genDir) android/hardware/tests/versioning/2.4/ $(genDir)/android/hardware/tests/versioning/2.4/",
-    srcs: [
-        ":android.hardware.tests.versioning@2.4_hal",
-    ],
-    out: [
-        "android/hardware/tests/versioning/2.4/Foo.vts.cpp",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.tests.versioning@2.4-vts.func_fuzzer.Foo",
-    defaults: ["func_fuzzer_defaults"],
-    srcs: [":android.hardware.tests.versioning@2.4-vts.func_fuzzer.Foo_genc++"],
-    shared_libs: [
-        "android.hardware.tests.versioning@2.4",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libhardware",
-        "libvts_func_fuzzer_utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-}
-
diff --git a/iface_fuzzer/Android.bp b/iface_fuzzer/Android.bp
index ffc5987..fec05fb 100644
--- a/iface_fuzzer/Android.bp
+++ b/iface_fuzzer/Android.bp
@@ -20,6 +20,7 @@
         "ProtoFuzzerUtils.cpp",
         "ProtoFuzzerMutator.cpp",
         "ProtoFuzzerMutateFns.cpp",
+        "ProtoFuzzerRunner.cpp",
     ],
     include_dirs: [
         "test/vts/drivers/hal/common/include",
@@ -27,6 +28,7 @@
     ],
     shared_libs: [
         "libprotobuf-cpp-full",
+        "libvintf",
         "libvts_common",
         "libvts_multidevice_proto",
         "libvts_proto_fuzzer_proto",
@@ -54,7 +56,7 @@
         "libvts_proto_fuzzer_proto",
     ],
     static_libs: [
-        "libLLVMFuzzer",
+        "libFuzzer",
     ],
     cflags: [
         "-Wno-unused-parameter",
diff --git a/iface_fuzzer/ProtoFuzzerMain.cpp b/iface_fuzzer/ProtoFuzzerMain.cpp
index 2975bf5..6b79192 100644
--- a/iface_fuzzer/ProtoFuzzerMain.cpp
+++ b/iface_fuzzer/ProtoFuzzerMain.cpp
@@ -16,7 +16,6 @@
 
 #include "ProtoFuzzerMutator.h"
 
-#include "specification_parser/InterfaceSpecificationParser.h"
 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
 
 #include <unistd.h>
@@ -39,15 +38,12 @@
 
 // 64-bit random number generator.
 static Random random{static_cast<uint64_t>(time(0))};
-// Parameters that passed in to fuzzer.
+// Parameters that were passed in to fuzzer.
 static ProtoFuzzerParams params;
-// CompSpec corresponding to the interface targeted by
-// fuzzer.
-static CompSpec target_comp_spec;
-// VTS hal driver used to call functions of targeted interface.
-static unique_ptr<FuzzerBase> hal;
 // Used to mutate inputs to hal driver.
 static unique_ptr<ProtoFuzzerMutator> mutator;
+// Used to exercise HIDL HAL's API.
+static unique_ptr<ProtoFuzzerRunner> runner;
 
 static ProtoFuzzerMutatorConfig mutator_config{
     // Heuristic: values close to 0 are likely to be meaningful scalar input
@@ -76,27 +72,24 @@
 
 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
   params = ExtractProtoFuzzerParams(*argc, *argv);
-  target_comp_spec =
-      FindTargetCompSpec(params.comp_specs_, params.target_iface_);
   mutator = make_unique<ProtoFuzzerMutator>(
       random, ExtractPredefinedTypes(params.comp_specs_), mutator_config);
-  hal.reset(
-      InitHalDriver(target_comp_spec, params.service_name_, params.get_stub_));
+  runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_);
+
+  runner->Init(params.target_iface_, params.binder_mode_);
   return 0;
 }
 
 extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
                                           size_t max_size, unsigned int seed) {
-  ExecSpec exec_spec;
-  if (!exec_spec.ParseFromArray(data, size)) {
+  ExecSpec exec_spec{};
+  if (!FromArray(data, size, &exec_spec)) {
     exec_spec =
-        mutator->RandomGen(target_comp_spec.interface(), params.exec_size_);
+        mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
   } else {
-    mutator->Mutate(target_comp_spec.interface(), &exec_spec);
+    mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec);
   }
-  cout << exec_spec.DebugString() << endl;
-  exec_spec.SerializeToArray(data, exec_spec.ByteSize());
-  return exec_spec.ByteSize();
+  return ToArray(data, size, &exec_spec);
 }
 
 // TODO(trong): implement a meaningful cross-over mechanism.
@@ -109,11 +102,12 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  ExecSpec exec_spec;
-  if (!exec_spec.ParseFromArray(data, size) || exec_spec.api_size() == 0) {
+  ExecSpec exec_spec{};
+  if (!FromArray(data, size, &exec_spec)) {
+    cerr << "Failed to deserialize an ExecSpec." << endl;
     return 0;
   }
-  Execute(hal.get(), exec_spec);
+  runner->Execute(exec_spec);
   return 0;
 }
 
diff --git a/iface_fuzzer/ProtoFuzzerMutateFns.cpp b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
index 416320f..09fad15 100644
--- a/iface_fuzzer/ProtoFuzzerMutateFns.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
@@ -91,8 +91,9 @@
 
 VarInstance ProtoFuzzerMutator::ScalarRandomGen(const VarSpec &var_spec) {
   VarInstance result{VarInstanceStubFromSpec(var_spec)};
+  result.set_scalar_type(var_spec.scalar_type());
   (*result.mutable_scalar_value()) =
-      RandomGen(var_spec.scalar_value(), var_spec.scalar_type());
+      RandomGen(result.scalar_value(), result.scalar_type());
   return result;
 }
 
@@ -103,6 +104,58 @@
   return result;
 }
 
+VarInstance ProtoFuzzerMutator::StringRandomGen(const VarSpec &var_spec) {
+  VarInstance result{VarInstanceStubFromSpec(var_spec)};
+
+  size_t str_size = mutator_config_.default_string_size_;
+  string str(str_size, 0);
+  auto rand_char = std::bind(&ProtoFuzzerMutator::RandomAsciiChar, this);
+  std::generate_n(str.begin(), str_size, rand_char);
+
+  StringDataValueMessage string_data;
+  string_data.set_message(str.c_str());
+  string_data.set_length(str_size);
+
+  *result.mutable_string_value() = string_data;
+  return result;
+}
+
+VarInstance ProtoFuzzerMutator::StringMutate(const VarInstance &var_instance) {
+  VarInstance result{var_instance};
+  string str = result.string_value().message();
+  size_t str_size = result.string_value().length();
+
+  // Three things can happen when mutating a string:
+  // 1. A random char is inserted into a random position.
+  // 2. A randomly selected char is removed from the string.
+  // 3. A randomly selected char in the string is replaced by a random char.
+  size_t dice_roll = str.empty() ? 0 : rand_(3);
+  size_t idx = rand_(str_size);
+  switch (dice_roll) {
+    case 0:
+      // Insert a random char.
+      str.insert(str.begin() + idx, RandomAsciiChar());
+      ++str_size;
+      break;
+    case 1:
+      // Remove a randomly selected char.
+      str.erase(str.begin() + idx);
+      --str_size;
+      break;
+    case 2:
+      // Replace a randomly selected char.
+      str[idx] = RandomAsciiChar();
+      break;
+    default:
+      // Do nothing.
+      break;
+  }
+
+  result.mutable_string_value()->set_message(str);
+  result.mutable_string_value()->set_length(str_size);
+  return result;
+}
+
 VarInstance ProtoFuzzerMutator::StructRandomGen(const VarSpec &var_spec) {
   VarInstance result{VarInstanceStubFromSpec(var_spec)};
   const TypeSpec &blueprint = FindPredefinedType(result.predefined_type());
@@ -248,9 +301,7 @@
   return value ^ mask;
 }
 
-bool ProtoFuzzerMutator::Mutate(bool value) {
-  return RandomGen(value);
-}
+bool ProtoFuzzerMutator::Mutate(bool value) { return RandomGen(value); }
 
 float ProtoFuzzerMutator::Mutate(float value) {
   uint32_t copy;
@@ -270,6 +321,16 @@
   return value;
 }
 
+char ProtoFuzzerMutator::RandomAsciiChar() {
+  const char char_set[] =
+      "0123456789"
+      "`~!@#$%^&*()-_=+[{]};:',<.>/? "
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+      "abcdefghijklmnopqrstuvwxyz";
+  size_t num_chars = sizeof(char_set) - 1;
+  return char_set[rand_(num_chars)];
+}
+
 }  // namespace fuzzer
 }  // namespace vts
 }  // namespace android
diff --git a/iface_fuzzer/ProtoFuzzerMutator.cpp b/iface_fuzzer/ProtoFuzzerMutator.cpp
index f16236a..4941382 100644
--- a/iface_fuzzer/ProtoFuzzerMutator.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutator.cpp
@@ -58,11 +58,27 @@
   random_gen_fns_[TYPE_HIDL_CALLBACK] = default_transform;
   mutate_fns_[TYPE_HIDL_CALLBACK] = default_transform;
 
+  random_gen_fns_[TYPE_HIDL_INTERFACE] = default_transform;
+  mutate_fns_[TYPE_HIDL_INTERFACE] = default_transform;
+
+  // Interpret masks as enums.
+  random_gen_fns_[TYPE_MASK] =
+      std::bind(&ProtoFuzzerMutator::EnumRandomGen, this, _1);
+  mutate_fns_[TYPE_MASK] = std::bind(&ProtoFuzzerMutator::EnumMutate, this, _1);
+
+  random_gen_fns_[TYPE_POINTER] = default_transform;
+  mutate_fns_[TYPE_POINTER] = default_transform;
+
   random_gen_fns_[TYPE_SCALAR] =
       std::bind(&ProtoFuzzerMutator::ScalarRandomGen, this, _1);
   mutate_fns_[TYPE_SCALAR] =
       std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
 
+  random_gen_fns_[TYPE_STRING] =
+      std::bind(&ProtoFuzzerMutator::StringRandomGen, this, _1);
+  mutate_fns_[TYPE_STRING] =
+      std::bind(&ProtoFuzzerMutator::StringMutate, this, _1);
+
   random_gen_fns_[TYPE_STRUCT] =
       std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
   mutate_fns_[TYPE_STRUCT] =
@@ -79,22 +95,36 @@
       std::bind(&ProtoFuzzerMutator::VectorMutate, this, _1);
 }
 
-ExecSpec ProtoFuzzerMutator::RandomGen(const IfaceSpec &iface_spec,
+// TODO(trong): add a mutator config option which controls how an interface is
+// selected.
+const CompSpec *ProtoFuzzerMutator::RandomSelectIface(const IfaceDescTbl &tbl) {
+  size_t rand_idx = rand_(tbl.size());
+  auto it = tbl.begin();
+  std::advance(it, rand_idx);
+  return it->second.comp_spec_;
+}
+
+ExecSpec ProtoFuzzerMutator::RandomGen(const IfaceDescTbl &tbl,
                                        size_t num_calls) {
   ExecSpec result{};
-
   for (size_t i = 0; i < num_calls; ++i) {
+    const CompSpec *comp_spec = RandomSelectIface(tbl);
+    string iface_name = comp_spec->component_name();
+    const IfaceSpec &iface_spec = comp_spec->interface();
+
+    // Generate a random interface function call.
+    FuncCall rand_call{};
+    rand_call.set_hidl_interface_name(iface_name);
     size_t num_apis = iface_spec.api_size();
     size_t rand_api_idx = rand_(num_apis);
     FuncSpec rand_api = RandomGen(iface_spec.api(rand_api_idx));
-    result.add_api()->Swap(&rand_api);
+    *rand_call.mutable_api() = rand_api;
+    *result.add_function_call() = rand_call;
   }
-
   return result;
 }
 
-void ProtoFuzzerMutator::Mutate(const IfaceSpec &iface_spec,
-                                ExecSpec *exec_spec) {
+void ProtoFuzzerMutator::Mutate(const IfaceDescTbl &tbl, ExecSpec *exec_spec) {
   // Mutate a randomly chosen function call with probability
   // odds_for/(odds_for + odds_against).
   uint64_t odds_for = mutator_config_.func_mutated_.first;
@@ -103,16 +133,21 @@
 
   if (rand_num < odds_for) {
     // Mutate a random function in execution.
-    size_t idx = rand_(exec_spec->api_size());
-    const FuncSpec &rand_api = exec_spec->api(idx);
-    (*exec_spec->mutable_api(idx)) = Mutate(rand_api);
+    size_t idx = rand_(exec_spec->function_call_size());
+    const FuncSpec &rand_api = exec_spec->function_call(idx).api();
+    *exec_spec->mutable_function_call(idx)->mutable_api() = Mutate(rand_api);
   } else {
     // Generate a random function call in place of randomly chosen function in
     // execution.
-    size_t func_idx = rand_(exec_spec->api_size());
+    const CompSpec *comp_spec = RandomSelectIface(tbl);
+    string iface_name = comp_spec->component_name();
+    const IfaceSpec &iface_spec = comp_spec->interface();
+
+    size_t func_idx = rand_(exec_spec->function_call_size());
     size_t blueprint_idx = rand_(iface_spec.api_size());
-    *(exec_spec->mutable_api(func_idx)) =
-        RandomGen(iface_spec.api(blueprint_idx));
+    FuncCall *func_call = exec_spec->mutable_function_call(func_idx);
+    func_call->set_hidl_interface_name(iface_name);
+    *func_call->mutable_api() = RandomGen(iface_spec.api(blueprint_idx));
   }
 }
 
diff --git a/iface_fuzzer/ProtoFuzzerRunner.cpp b/iface_fuzzer/ProtoFuzzerRunner.cpp
new file mode 100644
index 0000000..dddefb9
--- /dev/null
+++ b/iface_fuzzer/ProtoFuzzerRunner.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright 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 "ProtoFuzzerRunner.h"
+
+#include <dlfcn.h>
+#include <sstream>
+
+#include "utils/InterfaceSpecUtil.h"
+#include "vintf/HalManifest.h"
+#include "vintf/VintfObject.h"
+
+using android::vintf::HalManifest;
+
+using std::cout;
+using std::cerr;
+using std::string;
+using std::vector;
+using std::unordered_map;
+
+namespace android {
+namespace vts {
+namespace fuzzer {
+
+static string GetDriverName(const CompSpec &comp_spec) {
+  stringstream version;
+  version.precision(1);
+  version << fixed << comp_spec.component_type_version();
+  string driver_name =
+      comp_spec.package() + "@" + version.str() + "-vts.driver.so";
+  return driver_name;
+}
+
+static string GetServiceName(const CompSpec &comp_spec) {
+  static const HalManifest *vendor_manifest =
+      ::android::vintf::VintfObject::GetDeviceHalManifest();
+  string hal_name = comp_spec.package();
+  string iface_name = comp_spec.component_name();
+
+  auto instance_names = vendor_manifest->getInstances(hal_name, iface_name);
+  if (instance_names.empty()) {
+    cerr << "HAL service name not available in VINTF." << endl;
+    exit(1);
+  }
+
+  // For fuzzing we don't care which instance of the HAL is targeted.
+  string service_name = *instance_names.begin();
+  cout << "Available HAL instances: " << endl;
+  for (const string &instance_name : instance_names) {
+    cout << instance_name << endl;
+  }
+  cout << "Using HAL instance: " << service_name << endl;
+
+  return service_name;
+}
+
+static void *Dlopen(string lib_name) {
+  const char *error;
+  // Clear dlerror().
+  dlerror();
+  void *handle = dlopen(lib_name.c_str(), RTLD_LAZY);
+  if (!handle) {
+    cerr << __func__ << ": " << dlerror() << endl;
+    cerr << __func__ << ": Can't load shared library: " << lib_name << endl;
+    exit(1);
+  }
+  return handle;
+}
+
+static void *Dlsym(void *handle, string function_name) {
+  const char *error;
+  // Clear dlerror().
+  dlerror();
+  void *function = dlsym(handle, function_name.c_str());
+  if ((error = dlerror()) != NULL) {
+    cerr << __func__ << ": Can't find: " << function_name << endl;
+    cerr << error << endl;
+    exit(1);
+  }
+  return function;
+}
+
+static void GetService(DriverBase *hal, string service_name, bool binder_mode) {
+  // For fuzzing, only passthrough mode provides coverage.
+  // If binder mode is not requested, attempt to open HAL in passthrough mode.
+  // If the attempt fails, fall back to binder mode.
+  if (!binder_mode) {
+    if (!hal->GetService(true, service_name.c_str())) {
+      cerr << __func__ << ": Failed to open HAL in passthrough mode. "
+           << "Falling back to binder mode." << endl;
+    } else {
+      cerr << "HAL opened in passthrough mode." << endl;
+      return;
+    }
+  }
+
+  if (!hal->GetService(false, service_name.c_str())) {
+    cerr << __func__ << ": Failed to open HAL in binder mode." << endl;
+    exit(1);
+  } else {
+    cerr << "HAL opened in binder mode." << endl;
+    return;
+  }
+}
+
+DriverBase *ProtoFuzzerRunner::LoadInterface(const CompSpec &comp_spec,
+                                             uint64_t hidl_service = 0) {
+  DriverBase *hal;
+  const char *error;
+  // Clear dlerror().
+  dlerror();
+
+  // DriverBase can be constructed with or without an argument.
+  // Using different DriverBase constructors requires dlsym'ing different
+  // symbols from the driver library.
+  string function_name = GetFunctionNamePrefix(comp_spec);
+  if (hidl_service) {
+    function_name += "with_arg";
+    using loader_func = DriverBase *(*)(uint64_t);
+    auto hal_loader = (loader_func)Dlsym(driver_handle_, function_name.c_str());
+    hal = hal_loader(hidl_service);
+  } else {
+    using loader_func = DriverBase *(*)();
+    auto hal_loader = (loader_func)Dlsym(driver_handle_, function_name.c_str());
+    hal = hal_loader();
+  }
+  return hal;
+}
+
+ProtoFuzzerRunner::ProtoFuzzerRunner(const vector<CompSpec> &comp_specs) {
+  for (const auto &comp_spec : comp_specs) {
+    if (comp_spec.has_interface()) {
+      string name = comp_spec.component_name();
+      comp_specs_[name] = comp_spec;
+    }
+  }
+}
+
+void ProtoFuzzerRunner::Init(const string &iface_name, bool binder_mode) {
+  const CompSpec *comp_spec = FindCompSpec(iface_name);
+  // dlopen VTS driver library.
+  string driver_name = GetDriverName(*comp_spec);
+  driver_handle_ = Dlopen(driver_name);
+
+  std::shared_ptr<DriverBase> hal{LoadInterface(*comp_spec)};
+  string service_name = GetServiceName(*comp_spec);
+  cerr << "HAL name: " << comp_spec->package() << endl
+       << "Interface name: " << comp_spec->component_name() << endl
+       << "Service name: " << service_name << endl;
+
+  // This should only be done for top-level interfaces.
+  GetService(hal.get(), service_name, binder_mode);
+
+  // Register this interface as opened by the runner.
+  opened_ifaces_[iface_name] = {
+      .comp_spec_ = comp_spec, .hal_ = hal,
+  };
+}
+
+void ProtoFuzzerRunner::Execute(const ExecSpec &exec_spec) {
+  for (const auto &func_call : exec_spec.function_call()) {
+    cout << func_call.DebugString() << endl;
+    Execute(func_call);
+  }
+}
+
+void ProtoFuzzerRunner::Execute(const FuncCall &func_call) {
+  string iface_name = func_call.hidl_interface_name();
+  const FuncSpec &func_spec = func_call.api();
+
+  auto iface_desc = opened_ifaces_.find(iface_name);
+  if (iface_desc == opened_ifaces_.end()) {
+    cerr << "Interface is not open: " << iface_name << endl;
+    exit(1);
+  }
+
+  FuncSpec result{};
+  iface_desc->second.hal_->CallFunction(func_spec, "", &result);
+
+  ProcessReturnValue(result);
+}
+
+static string StripNamespace(const string &type) {
+  size_t idx = type.find_last_of(':');
+  if (idx == string::npos) {
+    return "";
+  }
+  return type.substr(idx + 1);
+}
+
+void ProtoFuzzerRunner::ProcessReturnValue(const FuncSpec &result) {
+  for (const auto &var : result.return_type_hidl()) {
+    if (var.has_hidl_interface_pointer() && var.has_predefined_type()) {
+      uint64_t hidl_service = var.hidl_interface_pointer();
+      string type = var.predefined_type();
+      string iface_name = StripNamespace(type);
+
+      const CompSpec *comp_spec = FindCompSpec(iface_name);
+      std::shared_ptr<DriverBase> hal{LoadInterface(*comp_spec, hidl_service)};
+
+      // Register this interface as opened by the runner.
+      opened_ifaces_[iface_name] = {
+          .comp_spec_ = comp_spec, .hal_ = hal,
+      };
+    }
+  }
+}
+
+const CompSpec *ProtoFuzzerRunner::FindCompSpec(std::string name) {
+  auto comp_spec = comp_specs_.find(name);
+  if (comp_spec == comp_specs_.end()) {
+    cerr << "VTS spec not found: " << name << endl;
+    exit(1);
+  }
+  return &comp_spec->second;
+}
+
+}  // namespace fuzzer
+}  // namespace vts
+}  // namespace android
diff --git a/iface_fuzzer/ProtoFuzzerUtils.cpp b/iface_fuzzer/ProtoFuzzerUtils.cpp
index 0732af8..6dbdb0a 100644
--- a/iface_fuzzer/ProtoFuzzerUtils.cpp
+++ b/iface_fuzzer/ProtoFuzzerUtils.cpp
@@ -17,12 +17,10 @@
 #include "ProtoFuzzerUtils.h"
 
 #include <dirent.h>
-#include <dlfcn.h>
 #include <getopt.h>
 #include <algorithm>
 #include <sstream>
 
-#include "specification_parser/InterfaceSpecificationParser.h"
 #include "utils/InterfaceSpecUtil.h"
 
 using std::cout;
@@ -40,15 +38,20 @@
       stdout,
       "Usage:\n"
       "\n"
-      "./<fuzzer> <vts flags> -- <libfuzzer flags>\n"
+      "./vts_proto_fuzzer <vts flags> -- <libfuzzer flags>\n"
       "\n"
       "VTS flags (strictly in form --flag=value):\n"
       "\n"
-      " vts_spec_files \tColumn-separated list of paths to vts spec files.\n"
-      " vts_exec_size \t\tNumber of function calls per fuzzer execution.\n"
+      "\tvts_binder_mode: if set, fuzzer will open the HAL in binder mode.\n"
+      "\tvts_exec_size: number of function calls per 1 run of "
+      "LLVMFuzzerTestOneInput.\n"
+      "\tvts_spec_dir: \":\"-separated list of directories on the target "
+      "containing .vts spec files.\n"
+      "\tvts_target_iface: name of interface targeted for fuzz, e.g. "
+      "\"INfc\".\n"
       "\n"
       "libfuzzer flags (strictly in form -flag=value):\n"
-      " Use -help=1 to see libfuzzer flags\n"
+      "\tUse -help=1 to see libfuzzer flags\n"
       "\n");
 }
 
@@ -57,25 +60,8 @@
     {"vts_binder_mode", no_argument, 0, 'b'},
     {"vts_spec_dir", required_argument, 0, 'd'},
     {"vts_exec_size", required_argument, 0, 'e'},
-    {"vts_service_name", required_argument, 0, 's'},
     {"vts_target_iface", required_argument, 0, 't'}};
 
-static string GetDriverName(const CompSpec &comp_spec) {
-  stringstream version;
-  version.precision(1);
-  version << fixed << comp_spec.component_type_version();
-  string driver_name =
-      comp_spec.package() + "@" + version.str() + "-vts.driver.so";
-  return driver_name;
-}
-
-static string GetServiceName(const CompSpec &comp_spec) {
-  // Infer HAL service name from its package name.
-  string prefix = "android.hardware.";
-  string service_name = comp_spec.package().substr(prefix.size());
-  return service_name;
-}
-
 // Removes information from CompSpec not needed by fuzzer.
 static void TrimCompSpec(CompSpec *comp_spec) {
   if (comp_spec == nullptr) {
@@ -90,22 +76,28 @@
   }
 }
 
-static vector<CompSpec> ExtractCompSpecs(string dir_path) {
+static vector<CompSpec> ExtractCompSpecs(string arg) {
   vector<CompSpec> result{};
-  DIR *dir;
-  struct dirent *ent;
-  if (!(dir = opendir(dir_path.c_str()))) {
-    cerr << "Could not open directory: " << dir_path << endl;
-    exit(1);
-  }
-  while ((ent = readdir(dir))) {
-    string vts_spec_name{ent->d_name};
-    if (vts_spec_name.find(".vts") != string::npos) {
-      string vts_spec_path = dir_path + "/" + vts_spec_name;
-      CompSpec comp_spec{};
-      InterfaceSpecificationParser::parse(vts_spec_path.c_str(), &comp_spec);
-      TrimCompSpec(&comp_spec);
-      result.emplace_back(std::move(comp_spec));
+  string dir_path;
+  std::istringstream iss(arg);
+
+  while (std::getline(iss, dir_path, ':')) {
+    DIR *dir;
+    struct dirent *ent;
+    if (!(dir = opendir(dir_path.c_str()))) {
+      cerr << "Could not open directory: " << dir_path << endl;
+      exit(1);
+    }
+    while ((ent = readdir(dir))) {
+      string vts_spec_name{ent->d_name};
+      if (vts_spec_name.find(".vts") != string::npos) {
+        cout << "Loading: " << vts_spec_name << endl;
+        string vts_spec_path = dir_path + "/" + vts_spec_name;
+        CompSpec comp_spec{};
+        ParseInterfaceSpec(vts_spec_path.c_str(), &comp_spec);
+        TrimCompSpec(&comp_spec);
+        result.emplace_back(std::move(comp_spec));
+      }
     }
   }
   return result;
@@ -130,7 +122,7 @@
         usage();
         exit(0);
       case 'b':
-        params.get_stub_ = false;
+        params.binder_mode_ = true;
         break;
       case 'd':
         params.comp_specs_ = ExtractCompSpecs(optarg);
@@ -138,9 +130,6 @@
       case 'e':
         params.exec_size_ = atoi(optarg);
         break;
-      case 's':
-        params.service_name_ = optarg;
-        break;
       case 't':
         params.target_iface_ = optarg;
         break;
@@ -152,61 +141,6 @@
   return params;
 }
 
-CompSpec FindTargetCompSpec(const vector<CompSpec> &specs,
-                            const string &target_iface) {
-  if (target_iface.empty()) {
-    cerr << "Target interface not specified." << endl;
-    exit(1);
-  }
-  auto spec = std::find_if(specs.begin(), specs.end(), [target_iface](auto x) {
-    return x.component_name().compare(target_iface) == 0;
-  });
-  if (spec == specs.end()) {
-    cerr << "Target interface doesn't match any of the loaded .vts files."
-         << endl;
-    exit(1);
-  }
-  return *spec;
-}
-
-// TODO(trong): this should be done using FuzzerWrapper.
-FuzzerBase *InitHalDriver(const CompSpec &comp_spec, string service_name,
-                          bool get_stub) {
-  const char *error;
-  string driver_name = GetDriverName(comp_spec);
-  void *handle = dlopen(driver_name.c_str(), RTLD_LAZY);
-  if (!handle) {
-    cerr << __func__ << ": " << dlerror() << endl;
-    cerr << __func__ << ": Can't load shared library: " << driver_name << endl;
-    exit(-1);
-  }
-
-  // Clear dlerror().
-  dlerror();
-  string function_name = GetFunctionNamePrefix(comp_spec);
-  using loader_func = FuzzerBase *(*)();
-  auto hal_loader = (loader_func)dlsym(handle, function_name.c_str());
-  if ((error = dlerror()) != NULL) {
-    cerr << __func__ << ": Can't find: " << function_name << endl;
-    cerr << error << endl;
-    exit(1);
-  }
-
-  FuzzerBase *hal = hal_loader();
-  // For fuzzing, only passthrough mode provides coverage.
-  if (get_stub) {
-    cout << "HAL used in passthrough mode." << endl;
-  } else {
-    cout << "HAL used in binderized mode." << endl;
-  }
-  if (!hal->GetService(get_stub, service_name.c_str())) {
-    cerr << __func__ << ": GetService(true, " << service_name << ") failed."
-         << endl;
-    exit(1);
-  }
-  return hal;
-}
-
 unordered_map<string, TypeSpec> ExtractPredefinedTypes(
     const vector<CompSpec> &specs) {
   unordered_map<string, TypeSpec> predefined_types;
@@ -214,15 +148,24 @@
     for (const auto &var_spec : comp_spec.attribute()) {
       ExtractPredefinedTypesFromVar(var_spec, predefined_types);
     }
+    for (const auto &var_spec : comp_spec.interface().attribute()) {
+      ExtractPredefinedTypesFromVar(var_spec, predefined_types);
+    }
   }
   return predefined_types;
 }
 
-void Execute(FuzzerBase *hal, const ExecSpec &exec_spec) {
-  FuncSpec result{};
-  for (const auto &func_spec : exec_spec.api()) {
-    hal->CallFunction(func_spec, "", &result);
-  }
+bool FromArray(const uint8_t *data, size_t size, ExecSpec *exec_spec) {
+  // TODO(b/63136690): Use checksum to validate exec_spec more reliably.
+  return exec_spec->ParseFromArray(data, size) && exec_spec->has_valid() &&
+         exec_spec->valid();
+}
+
+size_t ToArray(uint8_t *data, size_t size, ExecSpec *exec_spec) {
+  exec_spec->set_valid(true);
+  size_t exec_size = exec_spec->ByteSize();
+  exec_spec->SerializeToArray(data, exec_size);
+  return exec_size;
 }
 
 }  // namespace fuzzer
diff --git a/iface_fuzzer/config/Android.mk b/iface_fuzzer/config/Android.mk
deleted file mode 100644
index f9e3276..0000000
--- a/iface_fuzzer/config/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-subdir-makefiles)
diff --git a/iface_fuzzer/config/light/Android.mk b/iface_fuzzer/config/light/Android.mk
deleted file mode 100644
index a5fdc5f..0000000
--- a/iface_fuzzer/config/light/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ILightIfaceFuzzTest
-include test/vts/tools/build/Android.host_config.mk
diff --git a/iface_fuzzer/config/light/AndroidTest.xml b/iface_fuzzer/config/light/AndroidTest.xml
deleted file mode 100644
index 0412d88..0000000
--- a/iface_fuzzer/config/light/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<configuration description="Config for VTS Light HIDL HAL's interface fuzz test case.">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="push-group" value="IfaceFuzzerTest.push" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="ILightIfaceFuzzTest" />
-        <option name="binary-test-type" value="llvmfuzzer" />
-        <option name="test-config-path" value="vts/testcases/fuzz/iface_fuzzer/config/light/ILightIfaceFuzzTest.config" />
-    </test>
-</configuration>
diff --git a/iface_fuzzer/config/light/ILightIfaceFuzzTest.config b/iface_fuzzer/config/light/ILightIfaceFuzzTest.config
deleted file mode 100644
index f6eadac..0000000
--- a/iface_fuzzer/config/light/ILightIfaceFuzzTest.config
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "fuzzer_configs": {
-        "vts_proto_fuzzer": {
-            "vts_fuzzer_params": {
-                "vts_spec_files": [
-                    "light/Light.vts",
-                    "light/types.vts"
-                ],
-                "vts_exec_size": 100
-            },
-            "llvmfuzzer_params": {
-                "max_len": 65536,
-                "runs": 100
-            }
-        }
-    }
-}
diff --git a/iface_fuzzer/config/light/__init__.py b/iface_fuzzer/config/light/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/iface_fuzzer/config/light/__init__.py
+++ /dev/null
diff --git a/iface_fuzzer/config/memtrack/Android.mk b/iface_fuzzer/config/memtrack/Android.mk
deleted file mode 100644
index b85e8e5..0000000
--- a/iface_fuzzer/config/memtrack/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := IMemtrackIfaceFuzzTest
-include test/vts/tools/build/Android.host_config.mk
diff --git a/iface_fuzzer/config/memtrack/AndroidTest.xml b/iface_fuzzer/config/memtrack/AndroidTest.xml
deleted file mode 100644
index d22b7ca..0000000
--- a/iface_fuzzer/config/memtrack/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<configuration description="Config for VTS Memtrack HIDL HAL's interface fuzz test case.">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="push-group" value="IfaceFuzzerTest.push" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="IMemtrackIfaceFuzzTest" />
-        <option name="binary-test-type" value="llvmfuzzer" />
-        <option name="test-config-path" value="vts/testcases/fuzz/iface_fuzzer/config/memtrack/IMemtrackIfaceFuzzTest.config" />
-    </test>
-</configuration>
diff --git a/iface_fuzzer/config/memtrack/IMemtrackIfaceFuzzTest.config b/iface_fuzzer/config/memtrack/IMemtrackIfaceFuzzTest.config
deleted file mode 100644
index dfd9ca9..0000000
--- a/iface_fuzzer/config/memtrack/IMemtrackIfaceFuzzTest.config
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "fuzzer_configs": {
-        "vts_proto_fuzzer": {
-            "vts_fuzzer_params": {
-                "vts_spec_files": [
-                    "memtrack/Memtrack.vts",
-                    "memtrack/types.vts"
-                ],
-                "vts_exec_size": 100
-            },
-            "llvmfuzzer_params": {
-                "max_len": 65536,
-                "runs": 100
-            }
-        }
-    }
-}
diff --git a/iface_fuzzer/config/memtrack/__init__.py b/iface_fuzzer/config/memtrack/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/iface_fuzzer/config/memtrack/__init__.py
+++ /dev/null
diff --git a/iface_fuzzer/config/power/Android.mk b/iface_fuzzer/config/power/Android.mk
deleted file mode 100644
index 3425696..0000000
--- a/iface_fuzzer/config/power/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := IPowerIfaceFuzzTest
-include test/vts/tools/build/Android.host_config.mk
diff --git a/iface_fuzzer/config/power/AndroidTest.xml b/iface_fuzzer/config/power/AndroidTest.xml
deleted file mode 100644
index 2e00115..0000000
--- a/iface_fuzzer/config/power/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<configuration description="Config for VTS Power HIDL HAL's interface fuzz test case.">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="push-group" value="IfaceFuzzerTest.push" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="IPowerIfaceFuzzTest" />
-        <option name="binary-test-type" value="llvmfuzzer" />
-        <option name="test-config-path" value="vts/testcases/fuzz/iface_fuzzer/config/power/IPowerIfaceFuzzTest.config" />
-    </test>
-</configuration>
diff --git a/iface_fuzzer/config/power/IPowerIfaceFuzzTest.config b/iface_fuzzer/config/power/IPowerIfaceFuzzTest.config
deleted file mode 100644
index e69d680..0000000
--- a/iface_fuzzer/config/power/IPowerIfaceFuzzTest.config
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "fuzzer_configs": {
-        "vts_proto_fuzzer": {
-            "vts_fuzzer_params": {
-                "vts_spec_files": [
-                    "power/Power.vts",
-                    "power/types.vts"
-                ],
-                "vts_exec_size": 100
-            },
-            "llvmfuzzer_params": {
-                "max_len": 65536,
-                "runs": 100
-            }
-        }
-    }
-}
diff --git a/iface_fuzzer/config/power/__init__.py b/iface_fuzzer/config/power/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/iface_fuzzer/config/power/__init__.py
+++ /dev/null
diff --git a/iface_fuzzer/config/sensors/Android.mk b/iface_fuzzer/config/sensors/Android.mk
deleted file mode 100644
index 7248104..0000000
--- a/iface_fuzzer/config/sensors/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ISensorsIfaceFuzzTest
-include test/vts/tools/build/Android.host_config.mk
diff --git a/iface_fuzzer/config/sensors/AndroidTest.xml b/iface_fuzzer/config/sensors/AndroidTest.xml
deleted file mode 100644
index fd00efe..0000000
--- a/iface_fuzzer/config/sensors/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<configuration description="Config for VTS Sensors HIDL HAL's interface fuzz test case.">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="push-group" value="IfaceFuzzerTest.push" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="ISensorsIfaceFuzzTest" />
-        <option name="binary-test-type" value="llvmfuzzer" />
-        <option name="test-config-path" value="vts/testcases/fuzz/iface_fuzzer/config/sensors/ISensorsIfaceFuzzTest.config" />
-    </test>
-</configuration>
diff --git a/iface_fuzzer/config/sensors/ISensorsIfaceFuzzTest.config b/iface_fuzzer/config/sensors/ISensorsIfaceFuzzTest.config
deleted file mode 100644
index f27bf68..0000000
--- a/iface_fuzzer/config/sensors/ISensorsIfaceFuzzTest.config
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "fuzzer_configs": {
-        "vts_proto_fuzzer": {
-            "vts_fuzzer_params": {
-                "vts_spec_files": [
-                    "sensors/Sensors.vts",
-                    "sensors/types.vts"
-                ],
-                "vts_exec_size": 50
-            },
-            "llvmfuzzer_params": {
-                "max_len": 65536,
-                "max_total_time": 60
-            }
-        }
-    }
-}
diff --git a/iface_fuzzer/config/sensors/__init__.py b/iface_fuzzer/config/sensors/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/iface_fuzzer/config/sensors/__init__.py
+++ /dev/null
diff --git a/iface_fuzzer/config/thermal/Android.mk b/iface_fuzzer/config/thermal/Android.mk
deleted file mode 100644
index 54baf7e..0000000
--- a/iface_fuzzer/config/thermal/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := IThermalIfaceFuzzTest
-include test/vts/tools/build/Android.host_config.mk
diff --git a/iface_fuzzer/config/thermal/AndroidTest.xml b/iface_fuzzer/config/thermal/AndroidTest.xml
deleted file mode 100644
index 06a284b..0000000
--- a/iface_fuzzer/config/thermal/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<configuration description="Config for VTS Thermal HIDL HAL's interface fuzz test case.">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="push-group" value="IfaceFuzzerTest.push" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="IThermalIfaceFuzzTest" />
-        <option name="binary-test-type" value="llvmfuzzer" />
-        <option name="test-config-path" value="vts/testcases/fuzz/iface_fuzzer/config/thermal/IThermalIfaceFuzzTest.config" />
-    </test>
-</configuration>
diff --git a/iface_fuzzer/config/thermal/IThermalIfaceFuzzTest.config b/iface_fuzzer/config/thermal/IThermalIfaceFuzzTest.config
deleted file mode 100644
index b84fa5f..0000000
--- a/iface_fuzzer/config/thermal/IThermalIfaceFuzzTest.config
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "fuzzer_configs": {
-        "vts_proto_fuzzer": {
-            "vts_fuzzer_params": {
-                "vts_spec_files": [
-                    "thermal/Thermal.vts",
-                    "thermal/types.vts"
-                ],
-                "vts_exec_size": 100
-            },
-            "llvmfuzzer_params": {
-                "max_len": 65536,
-                "runs": 100
-            }
-        }
-    }
-}
diff --git a/iface_fuzzer/config/thermal/__init__.py b/iface_fuzzer/config/thermal/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/iface_fuzzer/config/thermal/__init__.py
+++ /dev/null
diff --git a/iface_fuzzer/include/ProtoFuzzerMutator.h b/iface_fuzzer/include/ProtoFuzzerMutator.h
index 90a0562..1eda572 100644
--- a/iface_fuzzer/include/ProtoFuzzerMutator.h
+++ b/iface_fuzzer/include/ProtoFuzzerMutator.h
@@ -22,9 +22,8 @@
 #include <string>
 #include <unordered_map>
 
+#include "ProtoFuzzerRunner.h"
 #include "ProtoFuzzerUtils.h"
-#include "test/vts-testcase/fuzz/iface_fuzzer/proto/ExecutionSpecificationMessage.pb.h"
-#include "test/vts/proto/ComponentSpecificationMessage.pb.h"
 
 namespace android {
 namespace vts {
@@ -47,6 +46,8 @@
   Odds func_mutated_ = {100, 1};
   // Default size used to randomly generate a vector.
   size_t default_vector_size_ = 64;
+  // Default size used to randomly generate a string.
+  size_t default_string_size_ = 16;
 };
 
 // Provides methods for mutation or random generation.
@@ -55,9 +56,9 @@
   ProtoFuzzerMutator(Random &, std::unordered_map<std::string, TypeSpec>,
                      ProtoFuzzerMutatorConfig);
   // Generates a random ExecSpec.
-  ExecSpec RandomGen(const IfaceSpec &, size_t);
+  ExecSpec RandomGen(const IfaceDescTbl &, size_t);
   // Mutates in-place an ExecSpec.
-  void Mutate(const IfaceSpec &, ExecSpec *);
+  void Mutate(const IfaceDescTbl &, ExecSpec *);
   // Generates a random FuncSpec.
   FuncSpec RandomGen(const FuncSpec &);
   // Mutates a FuncSpec.
@@ -68,6 +69,9 @@
   VarInstance Mutate(const VarInstance &);
 
  private:
+  // Randomly selects an interface.
+  const CompSpec *RandomSelectIface(const IfaceDescTbl &);
+
   // Used for mutation/random generation of VarInstance.
   VarInstance ArrayRandomGen(const VarSpec &);
   VarInstance ArrayMutate(const VarInstance &);
@@ -75,6 +79,8 @@
   VarInstance EnumMutate(const VarInstance &);
   VarInstance ScalarRandomGen(const VarSpec &);
   VarInstance ScalarMutate(const VarInstance &);
+  VarInstance StringRandomGen(const VarSpec &);
+  VarInstance StringMutate(const VarInstance &);
   VarInstance StructRandomGen(const VarSpec &);
   VarInstance StructMutate(const VarInstance &);
   VarInstance UnionRandomGen(const VarSpec &);
@@ -95,6 +101,8 @@
   bool Mutate(bool);
   float Mutate(float);
   double Mutate(double);
+  // Generates a random ASCII character.
+  char RandomAsciiChar();
 
   // Looks up predefined type by name.
   const TypeSpec &FindPredefinedType(std::string);
diff --git a/iface_fuzzer/include/ProtoFuzzerRunner.h b/iface_fuzzer/include/ProtoFuzzerRunner.h
new file mode 100644
index 0000000..179b059
--- /dev/null
+++ b/iface_fuzzer/include/ProtoFuzzerRunner.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 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 __VTS_PROTO_FUZZER_RUNNER_H_
+#define __VTS_PROTO_FUZZER_RUNNER_H_
+
+#include "ProtoFuzzerUtils.h"
+
+#include <memory>
+
+namespace android {
+namespace vts {
+namespace fuzzer {
+
+// Describes a HIDL HAL interface.
+struct IfaceDesc {
+  // VTS spec of the interface.
+  const CompSpec *comp_spec_;
+  // Handle to an interface instance.
+  std::shared_ptr<DriverBase> hal_;
+};
+
+using IfaceDescTbl = std::unordered_map<std::string, IfaceDesc>;
+
+// Responsible for issuing function calls to the HAL and keeps track of
+// HAL-related information, e.g. which interfaces has been opened so far.
+class ProtoFuzzerRunner {
+ public:
+  ProtoFuzzerRunner(const std::vector<CompSpec> &comp_specs);
+
+  // Initializes interface descriptor table by opening the root interface.
+  void Init(const std::string &, bool);
+  // Call every API from call sequence specified by the ExecSpec.
+  void Execute(const ExecSpec &);
+  // Execute the specified interface function call.
+  void Execute(const FuncCall &);
+  // Accessor to interface descriptor table containing currently opened
+  // interfaces.
+  const IfaceDescTbl &GetOpenedIfaces() const { return opened_ifaces_; }
+
+ private:
+  // Looks up interface spec by name.
+  const CompSpec *FindCompSpec(std::string);
+  // Processes return value from a function call.
+  void ProcessReturnValue(const FuncSpec &result);
+  // Loads the interface corresponding to the given VTS spec. Interface is
+  // constructed with the given argument.
+  DriverBase *LoadInterface(const CompSpec &, uint64_t);
+
+  // Keeps track of opened interfaces.
+  IfaceDescTbl opened_ifaces_;
+  // All loaded VTS specs indexed by name.
+  std::unordered_map<std::string, CompSpec> comp_specs_;
+  // Handle to the driver library.
+  void *driver_handle_;
+};
+
+}  // namespace fuzzer
+}  // namespace vts
+}  // namespace android
+
+#endif  // __VTS_PROTO_FUZZER_RUNNER_H__
diff --git a/iface_fuzzer/include/ProtoFuzzerUtils.h b/iface_fuzzer/include/ProtoFuzzerUtils.h
index b5516c3..85af37f 100644
--- a/iface_fuzzer/include/ProtoFuzzerUtils.h
+++ b/iface_fuzzer/include/ProtoFuzzerUtils.h
@@ -23,9 +23,8 @@
 #include <unordered_map>
 #include <vector>
 
-#include "fuzz_tester/FuzzerBase.h"
-#include "test/vts-testcase/fuzz/iface_fuzzer/proto/ExecutionSpecificationMessage.pb.h"
-#include "test/vts/proto/ComponentSpecificationMessage.pb.h"
+#include "driver_base/DriverBase.h"
+#include "test/vts/proto/ExecutionSpecificationMessage.pb.h"
 
 namespace android {
 namespace vts {
@@ -34,6 +33,7 @@
 // Use shorter names for convenience.
 using CompSpec = ComponentSpecificationMessage;
 using ExecSpec = ExecutionSpecificationMessage;
+using FuncCall = FunctionCallMessage;
 using FuncSpec = FunctionSpecificationMessage;
 using IfaceSpec = InterfaceSpecificationMessage;
 
@@ -69,32 +69,31 @@
   size_t exec_size_;
   // VTS specs supplied to the fuzzer.
   std::vector<CompSpec> comp_specs_;
-  // Service name of target interface, e.g. "INfc".
-  std::string service_name_ = "default";
-  // Name of target interface, e.g. "default".
+  // Name of target interface, e.g. "INfc".
   std::string target_iface_;
   // Controls whether HAL is opened in passthrough or binder mode.
-  // Passthrough mode is default. Used for testsing.
-  bool get_stub_ = true;
+  // Passthrough mode is default. Used for testing.
+  bool binder_mode_ = false;
 };
 
 // Parses command-line flags to create a ProtoFuzzerParams instance.
 ProtoFuzzerParams ExtractProtoFuzzerParams(int, char **);
 
-// Returns CompSpec corresponding to targeted interface.
-CompSpec FindTargetCompSpec(const std::vector<CompSpec> &, const std::string &);
-
-// Loads VTS HAL driver library.
-FuzzerBase *InitHalDriver(const CompSpec &, std::string, bool);
+// Returns CompSpec corresponding to given interface name.
+const CompSpec &FindCompSpec(const std::vector<CompSpec> &,
+                             const std::string &);
 
 // Creates a key, value look-up table with keys being names of predefined types,
 // and values being their definitions.
 std::unordered_map<std::string, TypeSpec> ExtractPredefinedTypes(
     const std::vector<CompSpec> &);
 
-// Call every API from call sequence specified by the
-// ExecutionSpecificationMessage.
-void Execute(FuzzerBase *, const ExecutionSpecificationMessage &);
+// Serializes ExecSpec into byte form and writes it to buffer. Returns number of
+// written bytes.
+size_t ToArray(uint8_t *, size_t, ExecSpec *);
+
+// Deserializes given buffer to an ExecSpec. Returns true on success.
+bool FromArray(const uint8_t *, size_t, ExecSpec *);
 
 }  // namespace fuzzer
 }  // namespace vts
diff --git a/iface_fuzzer/proto/Android.bp b/iface_fuzzer/proto/Android.bp
deleted file mode 100644
index 4112cbf..0000000
--- a/iface_fuzzer/proto/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// 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.
-//
-
-cc_library_shared {
-    name: "libvts_proto_fuzzer_proto",
-    proto: {
-        export_proto_headers: true,
-        type: "full",
-    },
-    srcs: [
-        "ExecutionSpecificationMessage.proto",
-    ],
-    shared_libs: [
-        "libprotobuf-cpp-full",
-        "libvts_multidevice_proto",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-    ],
-}
diff --git a/iface_fuzzer/proto/ExecutionSpecificationMessage.proto b/iface_fuzzer/proto/ExecutionSpecificationMessage.proto
deleted file mode 100644
index 53322aa..0000000
--- a/iface_fuzzer/proto/ExecutionSpecificationMessage.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.vts;
-
-import "test/vts/proto/ComponentSpecificationMessage.proto";
-
-// Specifies API call sequence.
-message ExecutionSpecificationMessage {
-  // Lists API calls.
-  repeated FunctionSpecificationMessage api = 1;
-}
diff --git a/script/build/template/func_fuzzer_build_defaults.bp b/script/build/template/func_fuzzer_build_defaults.bp
index a6c45da..0710611 100644
--- a/script/build/template/func_fuzzer_build_defaults.bp
+++ b/script/build/template/func_fuzzer_build_defaults.bp
@@ -5,6 +5,6 @@
 cc_defaults {
     name: "func_fuzzer_defaults",
     static_libs: [
-        "libLLVMFuzzer"
+        "libFuzzer"
     ],
 }
diff --git a/template/iface_fuzzer_test/iface_fuzzer_test.py b/template/iface_fuzzer_test/iface_fuzzer_test.py
index 9082e60..59d7ebb 100644
--- a/template/iface_fuzzer_test/iface_fuzzer_test.py
+++ b/template/iface_fuzzer_test/iface_fuzzer_test.py
@@ -45,48 +45,77 @@
             hal_version: string, version of the hal, e.g '7.4'
         """
         # Push .vts spec files.
-        hal_name_dir = hal_name.replace('.', '/')
+        hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
         src_dir = os.path.join(self.data_file_path, 'spec', 'hardware',
                                'interfaces', hal_name_dir, hal_version, 'vts')
+        dst_dir = os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
+                               hal_version)
 
         # Push corresponding VTS drivers.
         driver_name = 'android.hardware.%s@%s-vts.driver.so' % (hal_name,
                                                                 hal_version)
-        driver32 = os.path.join(self.data_file_path, 'DATA', 'lib', driver_name)
-        driver64 = os.path.join(self.data_file_path, 'DATA', 'lib64',
-                                driver_name)
+        asan_path = os.path.join(self.data_file_path, 'DATA', 'asan', 'system')
+        driver32 = os.path.join(asan_path, 'lib', driver_name)
+        driver64 = os.path.join(asan_path, 'lib64', driver_name)
         try:
-            self._dut.adb.push(src_dir, self._VTS_SPEC_DIR_TARGET)
+            self._dut.adb.push(src_dir, dst_dir)
             self._dut.adb.push(driver32, 'data/local/tmp/32')
             self._dut.adb.push(driver64, 'data/local/tmp/64')
         except adb.AdbError as e:
             logging.exception(e)
 
+    def _VtsSpecDirsTarget(self, hal_name, hal_version):
+        """Returns a list of directories on target with .vts specs.
+
+        Args:
+            hal_name: string, name of the hal, e.g. 'vibrator'.
+            hal_version: string, version of the hal, e.g '7.4'
+
+        Returns:
+            string list, directories on target
+        """
+        hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
+        spec_dirs = [os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
+                                  hal_version)]
+
+        imported_hals = self._vts_spec_parser.ImportedHals(hal_name,
+                                                           hal_version)
+        for name, version in imported_hals:
+            spec_dirs.append(
+                os.path.join(self._VTS_SPEC_DIR_TARGET,
+                             vts_spec_utils.HalNameDir(name), version))
+        return spec_dirs
+
     # Override
     def CreateTestCases(self):
         """See base class."""
         hal_package = self.hal_hidl_package_name
         hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion(
             hal_package)
+
+        imported_hals = self._vts_spec_parser.IndirectImportedHals(hal_name,
+                                                                   hal_version)
         self._PushVtsResources(hal_name, hal_version)
-        vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name,
-                                                            hal_version)
-        registered_interfaces = self._RegisteredInterfaces(
-            self.hal_hidl_package_name)
+        for name, version in imported_hals:
+            self._PushVtsResources(name, version)
+
+        registered_interfaces = self._RegisteredInterfaces(hal_package)
+        spec_dirs = ':'.join(self._VtsSpecDirsTarget(hal_name, hal_version))
 
         test_cases = []
         for iface in registered_interfaces:
             additional_params = {
-                'vts_spec_dir': self._VTS_SPEC_DIR_TARGET,
-                'vts_exec_size': 128,
+                'vts_spec_dir': spec_dirs,
+                'vts_exec_size': 16,
                 'vts_target_iface': iface,
             }
-            libfuzzer_params = {
+            libfuzzer_params = config.FUZZER_DEFAULT_PARAMS.copy()
+            libfuzzer_params.update({
                 'max_len': 65536,
-                'max_total_time': 1,
-            }
+                'max_total_time': 10,
+            })
             bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin',
-                                           'vts_proto_fuzzer')
+                                         'vts_proto_fuzzer')
             test_case = libfuzzer_test_case.LibFuzzerTestCase(
                 bin_host_path, libfuzzer_params, additional_params)
             test_case.test_name = iface
@@ -94,6 +123,15 @@
 
         return test_cases
 
+    # Override
+    def LogCrashReport(self, test_case):
+        """See base class."""
+        # Re-run the failing test case in debug mode.
+        logging.info('Attempting to reproduce the failure.')
+        repro_cmd = '"%s %s"' % (test_case.GetRunCommand(debug_mode=True),
+                                 config.FUZZER_TEST_CRASH_REPORT)
+        self._dut.adb.shell(repro_cmd, no_except=True)
+
 
 if __name__ == '__main__':
     test_runner.main()
diff --git a/template/libfuzzer_test/libfuzzer_test.py b/template/libfuzzer_test/libfuzzer_test.py
index 9689a27..20539ea 100644
--- a/template/libfuzzer_test/libfuzzer_test.py
+++ b/template/libfuzzer_test/libfuzzer_test.py
@@ -57,14 +57,14 @@
 
     def tearDownClass(self):
         """Deletes all copied data."""
-        self._dut.adb.shell('rm -rf %s' % self.data_file_path)
+        self._dut.adb.shell('rm -rf %s' % config.FUZZER_TEST_DIR)
         self._dut.start()
 
     def PushFiles(self, src):
         """adb pushes test case file to target."""
         push_src = os.path.join(self.data_file_path, src)
         push_dst = config.FUZZER_TEST_DIR
-        self._dut.adb.push('%s %s' % (push_src, push_dst))
+        self._dut.adb.push('%s %s' % (push_src, push_dst), no_except=True)
         logging.info('Adb pushed: %s \nto: %s', push_src, push_dst)
         return push_dst
 
@@ -93,21 +93,9 @@
         """
         self.PushFiles(test_case.bin_host_path)
         self.CreateCorpusDir(test_case)
-        fuzz_cmd = test_case.GetRunCommand()
-        logging.info('Executing: %s', fuzz_cmd)
-        try:
-            stdout = self._dut.adb.shell('"%s"' % fuzz_cmd)
-            result = {
-                const.STDOUT: stdout,
-                const.STDERR: '',
-                const.EXIT_CODE: 0
-            }
-        except adb.AdbError as e:
-            result = {
-                const.STDOUT: e.stdout,
-                const.STDERR: e.stderr,
-                const.EXIT_CODE: e.ret_code
-            }
+        fuzz_cmd = '"%s"' % test_case.GetRunCommand()
+        result = self._dut.adb.shell(fuzz_cmd, no_except=True)
+
         # TODO: upload the corpus and, possibly, crash log.
         self.AssertTestResult(test_case, result)
 
diff --git a/template/libfuzzer_test/libfuzzer_test_case.py b/template/libfuzzer_test/libfuzzer_test_case.py
index cb4b684..6a1223a 100644
--- a/template/libfuzzer_test/libfuzzer_test_case.py
+++ b/template/libfuzzer_test/libfuzzer_test_case.py
@@ -63,16 +63,18 @@
             flags = '%s %s %s' % (additional_flags, DELIMITER, libfuzzer_flags)
         return flags
 
-    def GetRunCommand(self):
+    def GetRunCommand(self, debug_mode=False):
         """Returns target shell command to run the fuzzer binary."""
         test_flags = self.CreateFuzzerFlags()
-        corpus_dir = self.GetCorpusName()
+        corpus_dir = '' if debug_mode else self.GetCorpusName()
 
         cd_cmd = 'cd %s' % config.FUZZER_TEST_DIR
         chmod_cmd = 'chmod 777 %s' % self._binary_name
         ld_path = 'LD_LIBRARY_PATH=/data/local/tmp/64:/data/local/tmp/32:$LD_LIBRARY_PATH'
-        test_cmd = '%s ./%s %s %s > /dev/null' % (ld_path, self._binary_name,
-                                                  corpus_dir, test_flags)
+        test_cmd = '%s ./%s %s %s' % (ld_path, self._binary_name, corpus_dir,
+                                      test_flags)
+        if not debug_mode:
+          test_cmd += ' > /dev/null'
         return ' && '.join([cd_cmd, chmod_cmd, test_cmd])
 
     @property
diff --git a/template/libfuzzer_test/libfuzzer_test_config.py b/template/libfuzzer_test/libfuzzer_test_config.py
index d191404..c330f48 100644
--- a/template/libfuzzer_test/libfuzzer_test_config.py
+++ b/template/libfuzzer_test/libfuzzer_test_config.py
@@ -37,5 +37,6 @@
 FUZZER_DEFAULT_PARAMS = {
     "max_len": 100,
     "max_total_time": 60,
-    "exact_artifact_path": FUZZER_TEST_CRASH_REPORT
+    "exact_artifact_path": FUZZER_TEST_CRASH_REPORT,
+    "timeout": 120,
 }