Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e19fc9eb authored by Corey Tabaka's avatar Corey Tabaka
Browse files

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
parent 186d7721
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,12 @@ struct FunctionTraits<Return_(Args_...)> {
      SignatureType<ConditionalRewrite<Return_, ReturnType>(
      SignatureType<ConditionalRewrite<Return_, ReturnType>(
          ConditionalRewrite<Args_, Params>...)>;
          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>
  template <typename ReturnType>
  using RewriteReturn =
  using RewriteReturn =
      SignatureType<ConditionalRewrite<Return_, ReturnType>(Args_...)>;
      SignatureType<ConditionalRewrite<Return_, ReturnType>(Args_...)>;
+72 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
#include <pdx/rpc/payload.h>
#include <pdx/rpc/payload.h>
#include <pdx/rpc/remote_method_type.h>
#include <pdx/rpc/remote_method_type.h>
#include <pdx/service.h>
#include <pdx/service.h>
#include <pdx/status.h>


namespace android {
namespace android {
namespace pdx {
namespace pdx {
@@ -157,6 +158,25 @@ EnableIfNotDirectReturn<typename RemoteMethodType::Return> RemoteMethodReturn(
           strerror(-ret));
           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
// Dispatches a method by deserializing arguments from the given Message, with
// compile-time interface check. Overload for void return types.
// compile-time interface check. Overload for void return types.
template <typename RemoteMethodType, typename Class, typename... Args,
template <typename RemoteMethodType, typename Class, typename... Args,
@@ -340,6 +360,46 @@ void DispatchRemoteMethod(Class& instance,
    RemoteMethodReturn<RemoteMethodType>(message, return_value);
    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__
#ifdef __clang__
// Overloads to handle Void argument type without exploding clang.
// Overloads to handle Void argument type without exploding clang.


@@ -399,6 +459,18 @@ void DispatchRemoteMethod(Class& instance, Return (Class::*method)(Message&),
  if (message)
  if (message)
    RemoteMethodReturn<RemoteMethodType>(message, return_value);
    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
#endif


}  // namespace rpc
}  // namespace rpc
+6 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,12 @@ struct RemoteMethodType {
  using RewriteSignature =
  using RewriteSignature =
      typename Traits::template RewriteSignature<ReturnType, Params...>;
      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>
  template <typename ReturnType>
  using RewriteReturn = typename Traits::template RewriteReturn<ReturnType>;
  using RewriteReturn = typename Traits::template RewriteReturn<ReturnType>;
};
};