Fix getService should retry on DEAD_OBJECT

If getService sees DEAD_OBJECT or nullptr when calling
interfaceChain on the retrieved service, it should
retry. Otherwise (e.g. TRANSACTION_FAILED for selinux
denials), it should bail out.

Test: calling Debug.getMemoryInfo from apps does not hang
Test: kill system_server, audio_server restarts exactly once
      (tested 10/10 times)
Test: taking screenshots / using camera / using maps
Test: adb push
$OUT/data/nativetest/VtsHalNfcV1_0TargetTest/VtsHalNfcV1_0TargetTest
/data/local/tmp && adb shell
/data/local/tmp/VtsHalNfcV1_0TargetTest

Bug: 36153684
Bug: 36611652

Change-Id: Iee10d4b9a1c4edfd154afb588a56fcd8c489641e
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index a4a83f4..a04cf77 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -21,6 +21,7 @@
 #include <sstream>
 
 #include <android-base/macros.h>
+#include <hidl/HidlInternal.h>
 #include <utils/Errors.h>
 #include <utils/StrongPointer.h>
 
@@ -129,11 +130,16 @@
 // For gtest output logging
 std::ostream& operator<< (std::ostream& stream, const Status& s);
 
+template<typename T> class Return;
+
 namespace details {
     class return_status {
     private:
         Status mStatus {};
         mutable bool mCheckedStatus = false;
+
+        template <typename T, typename U>
+        friend Return<U> StatusOf(const Return<T> &other);
     protected:
         void assertOk() const;
     public:
@@ -155,6 +161,12 @@
             return mStatus.isOk();
         }
 
+        // Check if underlying error is DEAD_OBJECT.
+        // Does not set mCheckedStatus.
+        bool isDeadObject() const {
+            return mStatus.transactionError() == DEAD_OBJECT;
+        }
+
         // For debugging purposes only
         std::string description() const {
             // Doesn't consider checked.
@@ -229,6 +241,18 @@
     return Return<void>();
 }
 
+namespace details {
+// Create a Return<U> from the Status of Return<T>. The provided
+// Return<T> must have an error status and have it checked.
+template <typename T, typename U>
+Return<U> StatusOf(const Return<T> &other) {
+    if (other.mStatus.isOk() || !other.mCheckedStatus) {
+        details::logAlwaysFatal("cannot call statusOf on an OK Status or an unchecked status");
+    }
+    return Return<U>{other.mStatus};
+}
+}  // namespace details
+
 }  // namespace hardware
 }  // namespace android
 
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 8a2a70a..3cac1e9 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -50,16 +50,28 @@
 namespace details {
 
 // cast the interface IParent to IChild.
-// Return nullptr if parent is null or any failure.
+// Return nonnull if cast successful.
+// Return nullptr if:
+// 1. parent is null
+// 2. cast failed because IChild is not a child type of IParent.
+// 3. !emitError, calling into parent fails.
+// Return an error Return object if:
+// 1. emitError, calling into parent fails.
 template<typename IChild, typename IParent, typename BpChild, typename BpParent>
-sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) {
+Return<sp<IChild>> castInterface(sp<IParent> parent, const char *childIndicator, bool emitError) {
     if (parent.get() == nullptr) {
         // casts always succeed with nullptrs.
         return nullptr;
     }
-    bool canCast = details::canCastInterface(parent.get(), childIndicator);
+    Return<bool> canCastRet = details::canCastInterface(parent.get(), childIndicator, emitError);
+    if (!canCastRet.isOk()) {
+        // call fails, propagate the error if emitError
+        return emitError
+                ? details::StatusOf<bool, sp<IChild>>(canCastRet)
+                : Return<sp<IChild>>(sp<IChild>(nullptr));
+    }
 
-    if (!canCast) {
+    if (!canCastRet) {
         return sp<IChild>(nullptr); // cast failed.
     }
     // TODO b/32001926 Needs to be fixed for socket mode.
diff --git a/transport/include/hidl/HidlTransportUtils.h b/transport/include/hidl/HidlTransportUtils.h
index 0fe70c4..fbd6516 100644
--- a/transport/include/hidl/HidlTransportUtils.h
+++ b/transport/include/hidl/HidlTransportUtils.h
@@ -25,14 +25,17 @@
 
 /*
  * Verifies the interface chain of 'interface' contains 'castTo'
+ * @param emitError if emitError is false, return Return<bool>{false} on error; if emitError
+ * is true, the Return<bool> object contains the actual error.
  */
-inline bool canCastInterface(::android::hidl::base::V1_0::IBase* interface, const char* castTo) {
+inline Return<bool> canCastInterface(::android::hidl::base::V1_0::IBase* interface,
+        const char* castTo, bool emitError = false) {
     if (interface == nullptr) {
         return false;
     }
 
     bool canCast = false;
-    auto ret = interface->interfaceChain([&](const hidl_vec<hidl_string> &types) {
+    auto chainRet = interface->interfaceChain([&](const hidl_vec<hidl_string> &types) {
         for (size_t i = 0; i < types.size(); i++) {
             if (types[i] == castTo) {
                 canCast = true;
@@ -40,7 +43,15 @@
             }
         }
     });
-    return ret.isOk() && canCast;
+
+    if (!chainRet.isOk()) {
+        // call fails, propagate the error if emitError
+        return emitError
+                ? details::StatusOf<void, bool>(chainRet)
+                : Return<bool>(false);
+    }
+
+    return canCast;
 }
 
 inline std::string getDescriptor(::android::hidl::base::V1_0::IBase* interface) {