Merge "Update HidlInstrumentor."
diff --git a/transport/Android.bp b/transport/Android.bp
index a5903e0..9dc54b4 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -55,6 +55,7 @@
     srcs: [
         "HidlBinderSupport.cpp",
         "HidlPassthroughSupport.cpp",
+        "LegacySupport.cpp",
         "ServiceManagement.cpp",
         "Static.cpp"
     ],
diff --git a/transport/LegacySupport.cpp b/transport/LegacySupport.cpp
new file mode 100644
index 0000000..d2e8688
--- /dev/null
+++ b/transport/LegacySupport.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "libhidltransport"
+
+#include <hidl/LegacySupport.h>
+
+#include <chrono>
+#include <cutils/properties.h>
+#include <thread>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+
+static const char* kDataProperty = "vold.post_fs_data_done";
+
+void waitForData() {
+    using namespace std::literals::chrono_literals;
+
+    // TODO(b/34274385) remove this
+    while (!property_get_bool(kDataProperty, false)) {
+        std::this_thread::sleep_for(300ms);
+    }
+}
+
+namespace details {
+
+bool blockingHalBinderizationEnabled() {
+    waitForData();
+    return property_get_bool("persist.hal.binderization", false);
+}
+
+void blockIfBinderizationDisabled(const std::string& interface,
+                                  const std::string& instance) {
+    // TODO(b/34274385) remove this
+    // Must wait for data to be mounted and persistant properties to be read,
+    // but only delay the start of hals which require reading this property.
+    bool enabled = blockingHalBinderizationEnabled();
+
+    if (!enabled) {
+        ALOGI("Deactivating %s/%s binderized service to"
+              " yield to passthrough implementation.",
+              interface.c_str(),
+              instance.c_str());
+        while (true) {
+            sleep(UINT_MAX);
+        }
+    }
+}
+}  // namespace details
+
+}  // namespace hardware
+}  // namespace android
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 9a6a3b5..5795b02 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -16,26 +16,33 @@
 
 #define LOG_TAG "ServiceManagement"
 
+#include <condition_variable>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <mutex>
+#include <regex>
+
 #include <hidl/HidlBinderSupport.h>
 #include <hidl/ServiceManagement.h>
 #include <hidl/Static.h>
 #include <hidl/Status.h>
 
 #include <android-base/logging.h>
-#include <condition_variable>
-#include <dlfcn.h>
-#include <dirent.h>
 #include <hidl-util/FQName.h>
 #include <hidl-util/StringHelper.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/Parcel.h>
-#include <mutex>
-#include <unistd.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android/hidl/manager/1.0/BpHwServiceManager.h>
 #include <android/hidl/manager/1.0/BnHwServiceManager.h>
 
+#define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
+#define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
+static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
+
 using android::hidl::manager::V1_0::IServiceManager;
 using android::hidl::manager::V1_0::IServiceNotification;
 using android::hidl::manager::V1_0::BpHwServiceManager;
@@ -86,6 +93,15 @@
     return results;
 }
 
+bool matchPackageName(const std::string &lib, std::string *matchedName) {
+    std::smatch match;
+    if (std::regex_match(lib, match, gLibraryFileNamePattern)) {
+        *matchedName = match.str(1) + "::I*";
+        return true;
+    }
+    return false;
+}
+
 struct PassthroughServiceManager : IServiceManager {
     Return<sp<IBase>> get(const hidl_string& fqName,
                      const hidl_string& name) override {
@@ -170,6 +186,27 @@
         return false;
     }
 
+    Return<void> debugDump(debugDump_cb _cb) override {
+        std::vector<InstanceDebugInfo> vec;
+        for (const std::string &path : {
+            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
+        }) {
+            std::vector<std::string> libs = search(path, "", ".so");
+            for (const std::string &lib : libs) {
+                std::string matchedName;
+                if (matchPackageName(lib, &matchedName)) {
+                    vec.push_back({
+                        .interfaceName = matchedName,
+                        .instanceName = "",
+                        .refCount = 0,
+                    });
+                }
+            }
+        }
+        _cb(vec);
+        return Void();
+    }
+
 };
 
 sp<IServiceManager> getPassthroughServiceManager() {
diff --git a/transport/include/hidl/LegacySupport.h b/transport/include/hidl/LegacySupport.h
index fab8a1d..9ee0635 100644
--- a/transport/include/hidl/LegacySupport.h
+++ b/transport/include/hidl/LegacySupport.h
@@ -26,12 +26,25 @@
 namespace android {
 namespace hardware {
 
+namespace details {
+bool blockingHalBinderizationEnabled();
+void blockIfBinderizationDisabled(const std::string& interface,
+                                  const std::string& instance);
+} // namespace details
+
 /**
  * Registers passthrough service implementation.
  */
 template<class Interface>
 status_t registerPassthroughServiceImplementation(
-      std::string name = "default") {
+        std::string name = "default") {
+    // TODO(b/34274385)
+    // If binderization is enabled, we should start up. Otherwise, wait around.
+    // If we return/kill ourselves, we will just be restarted by init. This
+    // function is only called from thin wrapping services, so blocking won't
+    // stop anything important from happening.
+    details::blockIfBinderizationDisabled(Interface::descriptor, name);
+
     sp<Interface> service = Interface::getService(name, true /* getStub */);
 
     if (service == nullptr) {
diff --git a/transport/manager/1.0/IServiceManager.hal b/transport/manager/1.0/IServiceManager.hal
index 321ee21..ff7201e 100644
--- a/transport/manager/1.0/IServiceManager.hal
+++ b/transport/manager/1.0/IServiceManager.hal
@@ -107,4 +107,17 @@
                              string name,
                              IServiceNotification callback)
         generates (bool success);
-};
\ No newline at end of file
+
+    struct InstanceDebugInfo {
+        string interfaceName;
+        string instanceName;
+        uint64_t refCount;
+    };
+
+    /*
+     * Similar to list, but contains more information for each instance.
+     * @return info a vector where each item contains debug information for each
+     *         instance.
+     */
+    debugDump() generates (vec<InstanceDebugInfo> info);
+};