driver framework change for host-driven control of nested interface

Test: mma
Bug: 36486289
Change-Id: I6b88d81cf67aabc83b0ec9581220e2db82829fa0
diff --git a/drivers/hal/common/component_loader/DllLoader.cpp b/drivers/hal/common/component_loader/DllLoader.cpp
index 1c66431..b8ce3a8 100644
--- a/drivers/hal/common/component_loader/DllLoader.cpp
+++ b/drivers/hal/common/component_loader/DllLoader.cpp
@@ -104,9 +104,13 @@
   return device_;
 }
 
-loader_function DllLoader::GetLoaderFunction(const char* function_name) {
-  loader_function func = (loader_function)LoadSymbol(function_name);
-  return func;
+loader_function DllLoader::GetLoaderFunction(const char* function_name) const {
+  return (loader_function)LoadSymbol(function_name);
+}
+
+loader_function_with_arg DllLoader::GetLoaderFunctionWithArg(
+    const char* function_name) const {
+  return (loader_function_with_arg)LoadSymbol(function_name);
 }
 
 bool DllLoader::SancovResetCoverage() {
@@ -137,7 +141,7 @@
   return true;
 }
 
-void* DllLoader::LoadSymbol(const char* symbol_name) {
+void* DllLoader::LoadSymbol(const char* symbol_name) const {
   const char* error = dlerror();
   if (error != NULL) {
     cerr << __func__ << ": existing error message before loading "
diff --git a/drivers/hal/common/fuzz_tester/FuzzerWrapper.cpp b/drivers/hal/common/fuzz_tester/FuzzerWrapper.cpp
index 6b05240..5c27d8d 100644
--- a/drivers/hal/common/fuzz_tester/FuzzerWrapper.cpp
+++ b/drivers/hal/common/fuzz_tester/FuzzerWrapper.cpp
@@ -19,11 +19,13 @@
 #include <dlfcn.h>
 
 #include <iostream>
+#include <sstream>
 #include <string>
 
 #include "component_loader/DllLoader.h"
 #include "fuzz_tester/FuzzerBase.h"
 #include "utils/InterfaceSpecUtil.h"
+#include "utils/StringUtil.h"
 
 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
 
@@ -82,5 +84,26 @@
   return fuzzer_base_;
 }
 
+FuzzerBase* FuzzerWrapper::GetFuzzer(const string& name,
+                                     const uint64_t interface_pt) const {
+  // Assumption: no shared library lookup is needed because that is handled
+  // the by the driver's linking dependency.
+  // Example: name (android::hardware::gnss::V1_0::IAGnssRil) converted to
+  // function name (vts_func_4_android_hardware_tests_bar_V1_0_IBar_with_arg)
+  stringstream prefix_ss;
+  string mutable_name = name;
+  ReplaceSubString(mutable_name, "::", "_");
+  prefix_ss << VTS_INTERFACE_SPECIFICATION_FUNCTION_NAME_PREFIX << HAL_HIDL
+            << mutable_name << "_with_arg";
+  string function_name_prefix = prefix_ss.str();
+  loader_function_with_arg func =
+      dll_loader_.GetLoaderFunctionWithArg(function_name_prefix.c_str());
+  if (!func) {
+    cerr << __func__ << ": function not found." << endl;
+    return NULL;
+  }
+  return func(interface_pt);
+}
+
 }  // namespace vts
 }  // namespace android
diff --git a/drivers/hal/common/include/component_loader/DllLoader.h b/drivers/hal/common/include/component_loader/DllLoader.h
index 0cf5b16..21ca3b1 100644
--- a/drivers/hal/common/include/component_loader/DllLoader.h
+++ b/drivers/hal/common/include/component_loader/DllLoader.h
@@ -26,6 +26,7 @@
 
 // Pointer type for a function in a loaded component.
 typedef FuzzerBase* (*loader_function)();
+typedef FuzzerBase* (*loader_function_with_arg)(uint64_t arg);
 typedef void (*writeout_fn)();
 typedef void (*flush_fn)();
 
@@ -49,7 +50,9 @@
 
   // Finds and returns a requested function defined in the loaded file.
   // Returns NULL if not found.
-  loader_function GetLoaderFunction(const char* function_name);
+  loader_function GetLoaderFunction(const char* function_name) const;
+  loader_function_with_arg GetLoaderFunctionWithArg(
+      const char* function_name) const;
 
   // (for sancov) Reset coverage data.
   bool SancovResetCoverage();
@@ -72,7 +75,7 @@
 
   // Loads a symbol and prints error message.
   // Returns the symbol value if successful; NULL otherwise.
-  void* LoadSymbol(const char* symbol_name);
+  void* LoadSymbol(const char* symbol_name) const;
 };
 
 }  // namespace vts
diff --git a/drivers/hal/common/include/fuzz_tester/FuzzerWrapper.h b/drivers/hal/common/include/fuzz_tester/FuzzerWrapper.h
index a1b1ca9..6b71da2 100644
--- a/drivers/hal/common/include/fuzz_tester/FuzzerWrapper.h
+++ b/drivers/hal/common/include/fuzz_tester/FuzzerWrapper.h
@@ -42,6 +42,10 @@
   // specification message.
   FuzzerBase* GetFuzzer(const vts::ComponentSpecificationMessage& message);
 
+  // Returns FuzzerBase of a nested interface specified by 'name' and its
+  // HIDL proxy interface pointer ('interface_pt').
+  FuzzerBase* GetFuzzer(const string& name, const uint64_t interface_pt) const;
+
  private:
   // loaded file path.
   string spec_dll_path_;
diff --git a/drivers/hal/common/include/specification_parser/SpecificationBuilder.h b/drivers/hal/common/include/specification_parser/SpecificationBuilder.h
index 2192294..3cd8baa 100644
--- a/drivers/hal/common/include/specification_parser/SpecificationBuilder.h
+++ b/drivers/hal/common/include/specification_parser/SpecificationBuilder.h
@@ -91,6 +91,21 @@
   // Returns the loaded interface specification message.
   ComponentSpecificationMessage* GetComponentSpecification() const;
 
+ protected:
+  // Registers a HIDL interface (proxy) in a map.
+  int32_t RegisterHidlInterface(const string& name,
+                                const uint64_t interface_pt);
+
+  // Returns a pre-registered HIDL interface proxy object's pointer address.
+  uint64_t GetHidlInterfacePointer(const int32_t id) const;
+
+  // Returns FuzzerBase pointer of a pre-registered HIDL interface proxy.
+  FuzzerBase* GetHidlInterfaceFuzzerBase(const int32_t id) const;
+
+  // Creates and returns FuzzerBase pointer of a HIDL interface (proxy).
+  FuzzerBase* GetFuzzerBase(const string& name,
+                            const uint64_t interface_pt) const;
+
  private:
   // A FuzzerWrapper instance.
   FuzzerWrapper wrapper_;
@@ -113,6 +128,9 @@
   // map for submodule interface specification messages.
   map<string, ComponentSpecificationMessage*> submodule_if_spec_map_;
   map<string, FuzzerBase*> submodule_fuzzerbase_map_;
+  // mapping from a nested interface ID to a tuple containing
+  // its interface name, FuzzerBase pointer, and HIDL proxy pointer.
+  map<int32_t, tuple<string, FuzzerBase*, uint64_t>> interface_map_;
 };
 
 }  // namespace vts
diff --git a/drivers/hal/common/specification_parser/SpecificationBuilder.cpp b/drivers/hal/common/specification_parser/SpecificationBuilder.cpp
index ae74082..af97b0e 100644
--- a/drivers/hal/common/specification_parser/SpecificationBuilder.cpp
+++ b/drivers/hal/common/specification_parser/SpecificationBuilder.cpp
@@ -313,6 +313,46 @@
 
 const string empty_string = string();
 
+FuzzerBase* SpecificationBuilder::GetFuzzerBase(
+    const string& name, const uint64_t interface_pt) const {
+  return wrapper_.GetFuzzer(name, interface_pt);
+}
+
+int32_t SpecificationBuilder::RegisterHidlInterface(
+    const string& name, const uint64_t interface_pt) {
+  FuzzerBase* fuzz_base_pt;
+  int32_t max_id = 0;
+  for (auto it : interface_map_) {
+    if (get<0>(it.second) == name && get<2>(it.second) == interface_pt) {
+      return it.first;
+    }
+    if (it.first > max_id) {
+      max_id = it.first;
+    }
+  }
+  max_id++;
+  fuzz_base_pt = GetFuzzerBase(name, interface_pt);
+  interface_map_.insert(
+      make_pair(max_id, make_tuple(name, fuzz_base_pt, interface_pt)));
+  return max_id;
+}
+
+uint64_t SpecificationBuilder::GetHidlInterfacePointer(const int32_t id) const {
+  cout << __func__ << " *** id " << id << endl;
+  auto res = interface_map_.find(id);
+  if (res == interface_map_.end()) return 0;
+  return reinterpret_cast<uint64_t>(get<2>(res->second));
+}
+
+FuzzerBase* SpecificationBuilder::GetHidlInterfaceFuzzerBase(
+    const int32_t id) const {
+  cout << __func__ << " *** id " << id << endl;
+  auto res = interface_map_.find(id);
+  if (res == interface_map_.end()) return nullptr;
+  cout << __func__ << " *** id " << id << " found" << endl;
+  return reinterpret_cast<FuzzerBase*>(get<1>(res->second));
+}
+
 const string& SpecificationBuilder::CallFunction(
     FunctionSpecificationMessage* func_msg) {
   cout << __func__ << ":" << __LINE__ << " entry" << endl;
@@ -337,8 +377,13 @@
       return empty_string;
     }
   } else {
-    func_fuzzer = GetFuzzerBase(*if_spec_msg_, dll_file_name_,
-                                func_msg->name().c_str());
+    if (func_msg->hidl_interface_id() == 0 ||
+        (if_spec_msg_ && if_spec_msg_->component_class() != HAL_HIDL)) {
+      func_fuzzer = GetFuzzerBase(*if_spec_msg_, dll_file_name_,
+                                  func_msg->name().c_str());
+    } else {
+      func_fuzzer = GetHidlInterfaceFuzzerBase(func_msg->hidl_interface_id());
+    }
   }
   cout << __func__ << ":" << __LINE__ << endl;
   if (!func_fuzzer) {
@@ -393,6 +438,16 @@
            << endl;
       return *(new string("error"));
     }
+
+    for (int index = 0; index < result_msg.return_type_hidl_size(); index++) {
+      VariableSpecificationMessage* return_val =
+          result_msg.mutable_return_type_hidl(index);
+      if (return_val->hidl_interface_pointer() != 0) {
+        return_val->set_hidl_interface_id(
+            RegisterHidlInterface(return_val->predefined_type(),
+                                  return_val->hidl_interface_pointer()));
+      }
+    }
   } else {
     if (!func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_)) {
       cerr << __func__ << " function not found - todo handle more explicitly"