libpdx: Add support for Status<T> return type from message handlers.
Add support for returning Status<T> from a message handler for a
remote method protocol with return type T. This greatly simplifies
error reporting logic in message handler methods.
Bug: None
Test: mm -j30; tests added to libpdx_uds in a follow up CL
Change-Id: Ib84e1ddc1f1c6a6d57b35ffada06f94a28e8e0cc
diff --git a/libs/vr/libpdx/private/pdx/rpc/function_traits.h b/libs/vr/libpdx/private/pdx/rpc/function_traits.h
index 5fdad72..7641b0a 100644
--- a/libs/vr/libpdx/private/pdx/rpc/function_traits.h
+++ b/libs/vr/libpdx/private/pdx/rpc/function_traits.h
@@ -43,6 +43,12 @@
SignatureType<ConditionalRewrite<Return_, ReturnType>(
ConditionalRewrite<Args_, Params>...)>;
+ template <template <typename> class Wrapper, typename ReturnType,
+ typename... Params>
+ using RewriteSignatureWrapReturn =
+ SignatureType<Wrapper<ConditionalRewrite<Return_, ReturnType>>(
+ ConditionalRewrite<Args_, Params>...)>;
+
template <typename ReturnType>
using RewriteReturn =
SignatureType<ConditionalRewrite<Return_, ReturnType>(Args_...)>;
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
index 679503c..e5c6616 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
@@ -10,6 +10,7 @@
#include <pdx/rpc/payload.h>
#include <pdx/rpc/remote_method_type.h>
#include <pdx/service.h>
+#include <pdx/status.h>
namespace android {
namespace pdx {
@@ -157,6 +158,25 @@
strerror(-ret));
}
+// Overload for Status<void> return types.
+template <typename RemoteMethodType>
+void RemoteMethodReturn(Message& message, const Status<void>& return_value) {
+ if (return_value)
+ RemoteMethodReturn<RemoteMethodType>(message, 0);
+ else
+ RemoteMethodError(message, return_value.error());
+}
+
+// Overload for Status<T> return types. This overload forwards the underlying
+// value or error within the Status<T>.
+template <typename RemoteMethodType, typename Return>
+void RemoteMethodReturn(Message& message, const Status<Return>& return_value) {
+ if (return_value)
+ RemoteMethodReturn<RemoteMethodType, Return>(message, return_value.get());
+ else
+ RemoteMethodError(message, return_value.error());
+}
+
// Dispatches a method by deserializing arguments from the given Message, with
// compile-time interface check. Overload for void return types.
template <typename RemoteMethodType, typename Class, typename... Args,
@@ -340,6 +360,46 @@
RemoteMethodReturn<RemoteMethodType>(message, return_value);
}
+// Dispatches a method by deserializing arguments from the given Message, with
+// compile-time interface signature check. Overload for Status<T> return types.
+template <typename RemoteMethodType, typename Class, typename Return,
+ typename... Args, typename = EnableIfNotVoidMethod<RemoteMethodType>>
+void DispatchRemoteMethod(Class& instance,
+ Status<Return> (Class::*method)(Message&, Args...),
+ Message& message,
+ std::size_t max_capacity = InitialBufferCapacity) {
+ using Signature =
+ typename RemoteMethodType::template RewriteSignature<Return, Args...>;
+ using InvokeSignature =
+ typename RemoteMethodType::template RewriteSignatureWrapReturn<
+ Status, Return, Args...>;
+ rpc::ServicePayload<ReceiveBuffer> payload(message);
+ payload.Resize(max_capacity);
+
+ auto size = message.Read(payload.Data(), payload.Size());
+ if (size < 0) {
+ RemoteMethodError(message, -size);
+ return;
+ }
+
+ payload.Resize(size);
+
+ ErrorType error;
+ auto decoder = MakeArgumentDecoder<Signature>(&payload);
+ auto arguments = decoder.DecodeArguments(&error);
+ if (error) {
+ RemoteMethodError(message, EIO);
+ return;
+ }
+
+ auto return_value = UnpackArguments<Class, InvokeSignature>(
+ instance, method, message, arguments)
+ .Invoke();
+ // Return the value to the caller unless the message was moved.
+ if (message)
+ RemoteMethodReturn<RemoteMethodType>(message, return_value);
+}
+
#ifdef __clang__
// Overloads to handle Void argument type without exploding clang.
@@ -399,6 +459,18 @@
if (message)
RemoteMethodReturn<RemoteMethodType>(message, return_value);
}
+
+// Overload for Status<T> return type.
+template <typename RemoteMethodType, typename Class, typename Return,
+ typename = EnableIfVoidMethod<RemoteMethodType>>
+void DispatchRemoteMethod(Class& instance,
+ Status<Return> (Class::*method)(Message&),
+ Message& message) {
+ auto return_value = (instance.*method)(message);
+ // Return the value to the caller unless the message was moved.
+ if (message)
+ RemoteMethodReturn<RemoteMethodType>(message, return_value);
+}
#endif
} // namespace rpc
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h b/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
index de9a3cc..cf9a189 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
@@ -31,6 +31,12 @@
using RewriteSignature =
typename Traits::template RewriteSignature<ReturnType, Params...>;
+ template <template <typename> class Wrapper, typename ReturnType,
+ typename... Params>
+ using RewriteSignatureWrapReturn =
+ typename Traits::template RewriteSignatureWrapReturn<Wrapper, ReturnType,
+ Params...>;
+
template <typename ReturnType>
using RewriteReturn = typename Traits::template RewriteReturn<ReturnType>;
};