wpa_supplicant(hidl): Helper functions for invoking hidl cont callbacks

The helper functions are used to invoke an internal method which
implements the functionality and then invoke the HIDL callback
with the return values.

HIDL's auto-generated code uses on-stack callbacks to return
non-primitive/multiple values from HIDL methods. This is unwieldy and
the implementation of the method's functionality gets mixed up with the
semantics of handling these callbacks. This tries to hide the semantics
of HIDL auto-generated code from the functionality.

Note: This is a port of go/aog/295772.

Bug: 32869248
Test: Compiles
Change-Id: I68868cdd90c772cfbd4ea080ba15af6b6c8ab18d
diff --git a/wpa_supplicant/hidl/hidl_return_macros.h b/wpa_supplicant/hidl/hidl_return_macros.h
deleted file mode 100644
index 25e8f49..0000000
--- a/wpa_supplicant/hidl/hidl_return_macros.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-// Macros to invoke the _hidl_cb to return status along with any return values.
-#define HIDL_RETURN(status_code, ...)                         \
-	do {                                                  \
-		SupplicantStatus status{.code = status_code}; \
-		_hidl_cb(status, ##__VA_ARGS__);              \
-		return Void();                                \
-	} while (false)
diff --git a/wpa_supplicant/hidl/hidl_return_util.h b/wpa_supplicant/hidl/hidl_return_util.h
new file mode 100644
index 0000000..c077fc8
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl_return_util.h
@@ -0,0 +1,101 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HIDL_RETURN_UTIL_H_
+#define HIDL_RETURN_UTIL_H_
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+namespace hidl_return_util {
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * HIDL interface object.
+ * These functions checks if the provided HIDL interface object is valid.
+ * a) if valid, Invokes the corresponding internal implementation function of
+ * the HIDL method. It then invokes the HIDL continuation callback with
+ * the status and any returned values.
+ * b) if invalid, invokes the HIDL continuation callback with the
+ * provided error status and default values.
+ */
+// Use for HIDL methods which return only an instance of SupplicantStatus.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&)>& hidl_cb, Args&&... args)
+{
+	if (obj->isValid()) {
+		hidl_cb((obj->*work)(std::forward<Args>(args)...));
+	} else {
+		hidl_cb({status_code_if_invalid, ""});
+	}
+	return Void();
+}
+
+// Use for HIDL methods which return instance of SupplicantStatus and a single
+// return value.
+template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&, ReturnT)>& hidl_cb,
+    Args&&... args)
+{
+	if (obj->isValid()) {
+		const auto& ret_pair =
+		    (obj->*work)(std::forward<Args>(args)...);
+		const SupplicantStatus& status = std::get<0>(ret_pair);
+		const auto& ret_value = std::get<1>(ret_pair);
+		hidl_cb(status, ret_value);
+	} else {
+		hidl_cb(
+		    {status_code_if_invalid, ""},
+		    typename std::remove_reference<ReturnT>::type());
+	}
+	return Void();
+}
+
+// Use for HIDL methods which return instance of SupplicantStatus and 2 return
+// values.
+template <
+    typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2,
+    typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&, ReturnT1, ReturnT2)>&
+	hidl_cb,
+    Args&&... args)
+{
+	if (obj->isValid()) {
+		const auto& ret_tuple =
+		    (obj->*work)(std::forward<Args>(args)...);
+		const SupplicantStatus& status = std::get<0>(ret_tuple);
+		const auto& ret_value1 = std::get<1>(ret_tuple);
+		const auto& ret_value2 = std::get<2>(ret_tuple);
+		hidl_cb(status, ret_value1, ret_value2);
+	} else {
+		hidl_cb(
+		    {status_code_if_invalid, ""},
+		    typename std::remove_reference<ReturnT1>::type(),
+		    typename std::remove_reference<ReturnT2>::type());
+	}
+	return Void();
+}
+
+}  // namespace hidl_util
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // HIDL_RETURN_UTIL_H_