Return<T>: fail hard on unchecked error.

If a transaction error occurs during a hidl call, and it isn't handled,
we want to fail hard, fast, and early. This adds a check in the Return
destructors which does this.

As part of this, I also combined the common parts of Return<*> and its
specialization Return<void> into a parent type, details::return_status.

Bug: 31348667
Test: hidl_test
Change-Id: Iba6d43ffb2e1dc68ba2c291f6f0c5ef1257e1da9
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index 06aa09c..cacaf08 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -141,45 +141,66 @@
 // For gtest output logging
 std::stringstream& operator<< (std::stringstream& stream, const Status& s);
 
-template<typename T> class Return : private details::hidl_log_base {
+namespace details {
+    class return_status : public details::hidl_log_base {
+    private:
+        Status mStatus {};
+        mutable bool mCheckedStatus = false;
+    public:
+        return_status() {}
+        return_status(Status s) : mStatus(s) {}
+
+        return_status(const return_status &) = default;
+
+        ~return_status() {
+            // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
+            if (!mCheckedStatus && !isOk()) {
+                logAlwaysFatal("HIDL return status not checked and transport error occured.");
+            }
+        }
+
+        bool isOk() const {
+            mCheckedStatus = true;
+            return mStatus.isOk();
+        }
+
+        // TODO(b/31348667) deprecate and replace with 'string description()'
+        const Status& getStatus() const {
+            mCheckedStatus = true;
+            return mStatus;
+        }
+    };
+}  // namespace details
+
+template<typename T> class Return : public details::return_status {
 private:
     T mVal {};
-    Status mStatus {};
 public:
-    Return(T v) : mVal{v} {}
-    Return(Status s) : mStatus(s) {}
+    Return(T v) : details::return_status(), mVal{v} {}
+    Return(Status s) : details::return_status(s) {}
 
-    bool isOk() const {
-        return mStatus.isOk();
-    }
+    Return(const Return &) = default;
+
+    ~Return() = default;
 
     operator T() const {
-        if (!mStatus.isOk()) {
+        if (!isOk()) {
             logAlwaysFatal("Attempted to retrieve value from hidl service, "
                            "but there was a transport error.");
         }
         return mVal;
     }
 
-    const Status& getStatus() const {
-        return mStatus;
-    }
 };
 
-template<> class Return<void> {
-private:
-    Status mStatus {};
+template<> class Return<void> : public details::return_status {
 public:
-    Return() = default;
-    Return(Status s) : mStatus(s) {}
+    Return() : details::return_status() {}
+    Return(Status s) : details::return_status(s) {}
 
-    bool isOk() const {
-        return mStatus.isOk();
-    }
+    Return(const Return &) = default;
 
-    const Status& getStatus() const {
-        return mStatus;
-    }
+    ~Return() = default;
 };
 
 static inline Return<void> Void() {