Callback elision for HIDL interfaces.

Test: mma, hidl_test
Bug: 31380743
Change-Id: If5f0dc0279e717dafaf416776be89cc854c6f856
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index c0edb84..f17c968 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -23,6 +23,7 @@
 #include <android-base/macros.h>
 #include <hidl/HidlInternal.h>
 #include <utils/Errors.h>
+#include <utils/StrongPointer.h>
 
 namespace android {
 namespace hardware {
@@ -146,6 +147,13 @@
     private:
         Status mStatus {};
         mutable bool mCheckedStatus = false;
+    protected:
+        void checkStatus() const {
+            if (!isOk()) {
+                logAlwaysFatal("Attempted to retrieve value from hidl service, "
+                               "but there was a transport error.");
+            }
+        }
     public:
         return_status() {}
         return_status(Status s) : mStatus(s) {}
@@ -190,15 +198,33 @@
     ~Return() = default;
 
     operator T() const {
-        if (!isOk()) {
-            logAlwaysFatal("Attempted to retrieve value from hidl service, "
-                           "but there was a transport error.");
-        }
+        checkStatus();
         return mVal;
     }
 
 };
 
+template<typename T> class Return<sp<T>> : public details::return_status {
+private:
+    sp<T> mVal {};
+public:
+    Return(sp<T> v) : details::return_status(), mVal{v} {}
+    Return(T* v) : details::return_status(), mVal{v} {}
+    // Constructors matching a different type (that is related by inheritance)
+    template<typename U> Return(sp<U> v) : details::return_status(), mVal{v} {}
+    template<typename U> Return(U* v) : details::return_status(), mVal{v} {}
+    Return(Status s) : details::return_status(s) {}
+
+    Return(const Return &) = default;
+    ~Return() = default;
+
+    operator sp<T>() const {
+        checkStatus();
+        return mVal;
+    }
+};
+
+
 template<> class Return<void> : public details::return_status {
 public:
     Return() : details::return_status() {}
diff --git a/libhidlmemory/mapping.cpp b/libhidlmemory/mapping.cpp
index b4fa123..3761f99 100644
--- a/libhidlmemory/mapping.cpp
+++ b/libhidlmemory/mapping.cpp
@@ -40,19 +40,14 @@
         LOG(FATAL) << "IMapper must be a passthrough service.";
     }
 
-    sp<IMemory> retMemory = nullptr;
-
-    Return<void> ret = mapper->mapMemory(memory,
-        [&retMemory](const auto &mapped) {
-            retMemory = mapped;
-        });
+    Return<sp<IMemory>> ret = mapper->mapMemory(memory);
 
     if (!ret.isOk()) {
         LOG(FATAL) << "hidl_memory map returned transport error.";
     }
 
-    return retMemory;
+    return ret;
 }
 
 }  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/transport/memory/1.0/default/AshmemMapper.cpp b/transport/memory/1.0/default/AshmemMapper.cpp
index 37eb8af..bef4767 100644
--- a/transport/memory/1.0/default/AshmemMapper.cpp
+++ b/transport/memory/1.0/default/AshmemMapper.cpp
@@ -27,10 +27,9 @@
 namespace implementation {
 
 // Methods from ::android::hidl::memory::V1_0::IMapper follow.
-Return<void> AshmemMapper::mapMemory(const hidl_memory& mem, mapMemory_cb _hidl_cb) {
+Return<sp<IMemory>> AshmemMapper::mapMemory(const hidl_memory& mem) {
     if (mem.handle()->numFds == 0) {
-        _hidl_cb(nullptr);
-        return Void();
+        return nullptr;
     }
 
     int fd = mem.handle()->data[0];
@@ -38,14 +37,10 @@
     if (data == MAP_FAILED) {
         // mmap never maps at address zero without MAP_FIXED, so we can avoid
         // exposing clients to MAP_FAILED.
-        _hidl_cb(nullptr);
-        return Void();
+        return nullptr;
     }
 
-    sp<IMemory> memory = new AshmemMemory(mem, data);
-
-    _hidl_cb(memory);
-    return Void();
+    return new AshmemMemory(mem, data);
 }
 
 }  // namespace implementation
diff --git a/transport/memory/1.0/default/AshmemMapper.h b/transport/memory/1.0/default/AshmemMapper.h
index c6cfc37..3d3a7e1 100644
--- a/transport/memory/1.0/default/AshmemMapper.h
+++ b/transport/memory/1.0/default/AshmemMapper.h
@@ -28,6 +28,7 @@
 namespace implementation {
 
 using ::android::hidl::memory::V1_0::IMapper;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
@@ -38,7 +39,7 @@
 
 struct AshmemMapper : public IMapper {
     // Methods from ::android::hidl::memory::V1_0::IMapper follow.
-    Return<void> mapMemory(const hidl_memory& mem, mapMemory_cb _hidl_cb) override;
+    Return<sp<IMemory>> mapMemory(const hidl_memory& mem) override;
 
 };