Add mechanism to collect fuzzer run data. am: a043386784
am: 898a3e4a3e

Change-Id: I1a449caadc8ae7cbd6e97d86fab0f2abfd884590
diff --git a/iface_fuzzer/Android.bp b/iface_fuzzer/Android.bp
index 17bd091..c4c59a8 100644
--- a/iface_fuzzer/Android.bp
+++ b/iface_fuzzer/Android.bp
@@ -21,6 +21,7 @@
         "ProtoFuzzerMutator.cpp",
         "ProtoFuzzerMutateFns.cpp",
         "ProtoFuzzerRunner.cpp",
+        "ProtoFuzzerStats.cpp",
     ],
     include_dirs: [
         "test/vts/drivers/hal/common/include",
diff --git a/iface_fuzzer/ProtoFuzzerMain.cpp b/iface_fuzzer/ProtoFuzzerMain.cpp
index f1b2c3a..7fa208d 100644
--- a/iface_fuzzer/ProtoFuzzerMain.cpp
+++ b/iface_fuzzer/ProtoFuzzerMain.cpp
@@ -79,6 +79,8 @@
   for (const auto &iface_desc : runner->GetOpenedIfaces()) {
     cerr << iface_desc.first << endl;
   }
+  cerr << endl;
+  cerr << runner->GetStats().StatsString();
 }
 
 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
diff --git a/iface_fuzzer/ProtoFuzzerMutator.cpp b/iface_fuzzer/ProtoFuzzerMutator.cpp
index 3e6cdc4..b2baa77 100644
--- a/iface_fuzzer/ProtoFuzzerMutator.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutator.cpp
@@ -17,9 +17,9 @@
 #include "ProtoFuzzerMutator.h"
 #include <iostream>
 
-using std::endl;
 using std::cerr;
 using std::cout;
+using std::endl;
 using std::make_unique;
 using std::unordered_map;
 using namespace std::placeholders;
diff --git a/iface_fuzzer/ProtoFuzzerRunner.cpp b/iface_fuzzer/ProtoFuzzerRunner.cpp
index 7c9ea84..ec9dee1 100644
--- a/iface_fuzzer/ProtoFuzzerRunner.cpp
+++ b/iface_fuzzer/ProtoFuzzerRunner.cpp
@@ -25,11 +25,11 @@
 
 using android::vintf::HalManifest;
 
-using std::cout;
 using std::cerr;
+using std::cout;
 using std::string;
-using std::vector;
 using std::unordered_map;
+using std::vector;
 
 namespace android {
 namespace vts {
@@ -188,6 +188,7 @@
   FuncSpec result{};
   iface_desc->second.hal_->CallFunction(func_spec, "", &result);
 
+  stats_.RegisterTouch(iface_name, func_spec.name());
   ProcessReturnValue(result);
 }
 
diff --git a/iface_fuzzer/ProtoFuzzerStats.cpp b/iface_fuzzer/ProtoFuzzerStats.cpp
new file mode 100644
index 0000000..659fc59
--- /dev/null
+++ b/iface_fuzzer/ProtoFuzzerStats.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "ProtoFuzzerStats.h"
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+
+using std::endl;
+using std::map;
+using std::string;
+using std::unordered_map;
+
+namespace android {
+namespace vts {
+namespace fuzzer {
+
+void ProtoFuzzerStats::RegisterTouch(string iface_name, string func_name) {
+  string key = iface_name + "::" + func_name;
+  touch_count_[key]++;
+}
+
+string ProtoFuzzerStats::StatsString() const {
+  std::map<string, uint64_t> ordered_result{touch_count_.cbegin(),
+                                            touch_count_.cend()};
+
+  std::stringstream ss{};
+  ss << "HAL api function touch count: " << endl;
+  for (const auto &entry : ordered_result) {
+    ss << std::left << std::setfill(' ') << std::setw(40) << entry.first
+       << std::setw(40) << entry.second << endl;
+  }
+  ss << endl;
+  return ss.str();
+}
+
+}  // namespace fuzzer
+}  // namespace vts
+}  // namespace android
diff --git a/iface_fuzzer/ProtoFuzzerUtils.cpp b/iface_fuzzer/ProtoFuzzerUtils.cpp
index 43710f0..6ae3019 100644
--- a/iface_fuzzer/ProtoFuzzerUtils.cpp
+++ b/iface_fuzzer/ProtoFuzzerUtils.cpp
@@ -145,7 +145,7 @@
   return params;
 }
 
-string ProtoFuzzerParams::DebugString() {
+string ProtoFuzzerParams::DebugString() const {
   std::stringstream ss;
   ss << "Execution size: " << exec_size_ << endl;
   ss << "Target interface: " << target_iface_ << endl;
diff --git a/iface_fuzzer/include/ProtoFuzzerRunner.h b/iface_fuzzer/include/ProtoFuzzerRunner.h
index 179b059..3f882a2 100644
--- a/iface_fuzzer/include/ProtoFuzzerRunner.h
+++ b/iface_fuzzer/include/ProtoFuzzerRunner.h
@@ -17,6 +17,7 @@
 #ifndef __VTS_PROTO_FUZZER_RUNNER_H_
 #define __VTS_PROTO_FUZZER_RUNNER_H_
 
+#include "ProtoFuzzerStats.h"
 #include "ProtoFuzzerUtils.h"
 
 #include <memory>
@@ -50,6 +51,8 @@
   // Accessor to interface descriptor table containing currently opened
   // interfaces.
   const IfaceDescTbl &GetOpenedIfaces() const { return opened_ifaces_; }
+  // Accessor to stats object.
+  const ProtoFuzzerStats &GetStats() const { return stats_; }
 
  private:
   // Looks up interface spec by name.
@@ -66,6 +69,9 @@
   std::unordered_map<std::string, CompSpec> comp_specs_;
   // Handle to the driver library.
   void *driver_handle_;
+
+  // Collects statistical information.
+  ProtoFuzzerStats stats_;
 };
 
 }  // namespace fuzzer
diff --git a/iface_fuzzer/include/ProtoFuzzerStats.h b/iface_fuzzer/include/ProtoFuzzerStats.h
new file mode 100644
index 0000000..6dfb164
--- /dev/null
+++ b/iface_fuzzer/include/ProtoFuzzerStats.h
@@ -0,0 +1,45 @@
+/*
+ * 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_STATS_H_
+#define __VTS_PROTO_FUZZER_STATS_H_
+
+#include <string>
+#include <unordered_map>
+
+namespace android {
+namespace vts {
+namespace fuzzer {
+
+// Holds stats about a fuzzer run.
+class ProtoFuzzerStats {
+ public:
+  // Registers fuzzer touching an interface function.
+  void RegisterTouch(std::string iface_name, std::string func_name);
+  // Returns collected stats in string form.
+  std::string StatsString() const;
+
+ private:
+  // Counts the number of times a function was touched.
+  // This object will be written to often, so we use unordered_map.
+  std::unordered_map<std::string, uint64_t> touch_count_;
+};
+
+}  // namespace fuzzer
+}  // namespace vts
+}  // namespace android
+
+#endif  // __VTS_PROTO_FUZZER_STATS__
diff --git a/iface_fuzzer/include/ProtoFuzzerUtils.h b/iface_fuzzer/include/ProtoFuzzerUtils.h
index 13e5665..145a40a 100644
--- a/iface_fuzzer/include/ProtoFuzzerUtils.h
+++ b/iface_fuzzer/include/ProtoFuzzerUtils.h
@@ -79,7 +79,7 @@
   // Seed used to initialize the random number generator.
   uint64_t seed_ = static_cast<uint64_t>(time(0));
   // Returns a string summarizing content of this object.
-  string DebugString();
+  string DebugString() const;
 };
 
 // Parses command-line flags to create a ProtoFuzzerParams instance.