Revert "Revert "getService should retry if getting nullptr""

Test: take picture with different modes
Test: take video
Test: take screenshot
Test: video plays
Test: after these steps, lshal doesn't have extra PIDs for
      gralloc passthrough hal.
Test: dmesg doesn't have denials.

Bug: 36153684
Bug: 36383997
Bug: 36462585

This reverts commit 2f7abc9a96e58e693f0db7b0c7fcf59a856a4008.

Change-Id: I5d087d55caaf38a94dae7d06ded3179041994953
diff --git a/generateCpp.cpp b/generateCpp.cpp
index e38873c..26765bb 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -156,46 +156,98 @@
 
     out << "// static\n"
         << "::android::sp<" << interfaceName << "> " << interfaceName << "::getService("
-        << "const std::string &serviceName, bool getStub) ";
+        << "const std::string &serviceName, const bool getStub) ";
     out.block([&] {
         out << "::android::sp<" << interfaceName << "> iface = nullptr;\n";
         out << "::android::vintf::Transport transport = ::android::hardware::getTransport("
             << interfaceName << "::descriptor, serviceName);\n";
 
-        out.sIf("!getStub && "
-                "(transport == ::android::vintf::Transport::HWBINDER || "
-                "transport == ::android::vintf::Transport::TOGGLED || "
-                "transport == ::android::vintf::Transport::EMPTY)", [&] {
+        // TODO(b/34274385) remove sysprop check
+        out << "const bool vintfHwbinder = (transport == ::android::vintf::Transport::HWBINDER) ||\n"
+            << "                           (transport == ::android::vintf::Transport::TOGGLED &&\n"
+            << "                            ::android::hardware::details::blockingHalBinderizationEnabled());\n"
+            << "const bool vintfPassthru = (transport == ::android::vintf::Transport::PASSTHROUGH) ||\n"
+            << "                           (transport == ::android::vintf::Transport::TOGGLED &&\n"
+            << "                            !::android::hardware::details::blockingHalBinderizationEnabled());\n"
+            << "const bool vintfEmpty    = (transport == ::android::vintf::Transport::EMPTY);\n\n";
+
+        // if (getStub) {
+        //     getPassthroughServiceManager()->get only once.
+        // } else {
+        //     if (vintfHwbinder) {
+        //         while (no alive service) {
+        //             waitForHwService
+        //             defaultServiceManager()->get
+        //         }
+        //     } else if (vintfEmpty) {
+        //         defaultServiceManager()->get only once.
+        //         getPassthroughServiceManager()->get only once.
+        //     } else if (vintfPassthru) {
+        //         getPassthroughServiceManager()->get only once.
+        //     }
+        // }
+
+        out.sFor("bool tried = false; "
+                 "!getStub && (vintfHwbinder || (vintfEmpty && !tried)); "
+                 "tried = true", [&] {
+
+            // Because this is a for loop, a "continue" statement means
+            // setting tried, and hence "break" for vintfEmpty and
+            // "retry" for vintfHwBinder
+
+            out.sIf("tried", [&] {
+                // sleep only after the first trial.
+                out << "ALOGI(\"getService: retrying in 1s...\");\n"
+                    << "sleep(1);\n";
+            }).endl();
+
             out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
             out.indent(2, [&] {
                 out << "= ::android::hardware::defaultServiceManager();\n";
             });
-            out.sIf("sm != nullptr", [&] {
-                // TODO(b/34274385) remove sysprop check
-                out.sIf("transport == ::android::vintf::Transport::HWBINDER ||"
-                         "(transport == ::android::vintf::Transport::TOGGLED &&"
-                         " ::android::hardware::details::blockingHalBinderizationEnabled())", [&]() {
-                    out << "::android::hardware::details::waitForHwService("
-                        << interfaceName << "::descriptor" << ", serviceName);\n";
-                }).endl();
-                out << "::android::hardware::Return<::android::sp<" << gIBaseFqName.cppName() << ">> ret = \n";
-                out.indent(2, [&] {
-                    out << "sm->get(" << interfaceName << "::descriptor" << ", serviceName);\n";
-                });
-                out.sIf("ret.isOk()", [&] {
-                    out << "iface = " << interfaceName << "::castFrom(ret);\n";
-                    out.sIf("iface != nullptr", [&] {
-                        out << "return iface;\n";
-                    }).endl();
-                }).endl();
+            out.sIf("sm == nullptr", [&] {
+                // hwbinder is not available on this device, so future tries
+                // would also be null. I can only "break" here and
+                // (vintfEmpty) try passthrough or (vintfHwbinder) return nullptr.
+                out << "ALOGE(\"getService: defaultServiceManager() is null\");\n"
+                    << "break;\n";
             }).endl();
+
+            out.sIf("vintfHwbinder", [&] {
+                out << "::android::hardware::details::waitForHwService("
+                    << interfaceName << "::descriptor" << ", serviceName);\n";
+            }).endl();
+
+            out << "::android::hardware::Return<::android::sp<"
+                << gIBaseFqName.cppName() << ">> ret = \n";
+            out.indent(2, [&] {
+                out << "sm->get(" << interfaceName << "::descriptor, serviceName);\n";
+            });
+
+            out.sIf("!ret.isOk()", [&] {
+                // hwservicemanager fails
+                out << "ALOGE(\"getService: defaultServiceManager()->get returns %s\", "
+                    << "ret.description().c_str());\n"
+                    << "continue;\n";
+            }).endl();
+
+            out << "iface = " << interfaceName << "::castFrom(ret);\n";
+            out.sIf("iface == nullptr", [&] {
+                // 1. race condition. hwservicemanager drops the service
+                //    from waitForHwService to here
+                // 2. service is dead (castFrom cannot call interfaceChain)
+                // 3. returned service isn't of correct type; this is a bug
+                //    to hwservicemanager or to the service itself (interfaceChain
+                //    is not consistent)
+                // In all cases, try again.
+                out << "ALOGW(\"getService: found null interface\");\n"
+                    << "continue;\n";
+            }).endl();
+
+            out << "return iface;\n";
         }).endl();
 
-        out.sIf("getStub || "
-                "transport == ::android::vintf::Transport::PASSTHROUGH || "
-                "(transport == ::android::vintf::Transport::TOGGLED &&"
-                " !::android::hardware::details::blockingHalBinderizationEnabled()) ||"
-                "transport == ::android::vintf::Transport::EMPTY", [&] {
+        out.sIf("getStub || vintfPassthru || vintfEmpty", [&] {
             out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> pm\n";
             out.indent(2, [&] {
                 out << "= ::android::hardware::getPassthroughServiceManager();\n";
@@ -212,7 +264,7 @@
                     out.sIf("baseInterface != nullptr", [&]() {
                         out << "iface = new " << fqName.getInterfacePassthroughName()
                             << "(" << interfaceName << "::castFrom(baseInterface));\n";
-                    });
+                    }).endl();
                 }).endl();
             }).endl();
         }).endl();