Merge "Log duration to logcat always."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3c47767..5b43172 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -54,7 +54,9 @@
 #include <android/os/IIncidentCompanion.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
+#include <debuggerd/client.h>
 #include <dumpsys.h>
+#include <dumputils/dump_utils.h>
 #include <hidl/ServiceManagement.h>
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
@@ -1444,7 +1446,7 @@
     RunDumpsysCritical();
 
     /* collect stack traces from Dalvik and native processes (needs root) */
-    dump_traces_path = dump_traces();
+    dump_traces_path = ds.DumpTraces();
 
     /* Run some operations that require root. */
     ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
@@ -1581,6 +1583,114 @@
     printf("========================================================\n");
 }
 
+const char* Dumpstate::DumpTraces() {
+    DurationReporter duration_reporter("DUMP TRACES");
+
+    const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
+    const size_t buf_size = temp_file_pattern.length() + 1;
+    std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
+    memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
+
+    // Create a new, empty file to receive all trace dumps.
+    //
+    // TODO: This can be simplified once we remove support for the old style
+    // dumps. We can have a file descriptor passed in to dump_traces instead
+    // of creating a file, closing it and then reopening it again.
+    android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
+    if (fd < 0) {
+        MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    // Nobody should have access to this temporary file except dumpstate, but we
+    // temporarily grant 'read' to 'others' here because this file is created
+    // when tombstoned is still running as root, but dumped after dropping. This
+    // can go away once support for old style dumping has.
+    const int chmod_ret = fchmod(fd, 0666);
+    if (chmod_ret < 0) {
+        MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+    if (proc.get() == nullptr) {
+        MYLOGE("opendir /proc failed: %s\n", strerror(errno));
+        return nullptr;
+    }
+
+    // Number of times process dumping has timed out. If we encounter too many
+    // failures, we'll give up.
+    int timeout_failures = 0;
+    bool dalvik_found = false;
+
+    const std::set<int> hal_pids = get_interesting_hal_pids();
+
+    struct dirent* d;
+    while ((d = readdir(proc.get()))) {
+        int pid = atoi(d->d_name);
+        if (pid <= 0) {
+            continue;
+        }
+
+        const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+        std::string exe;
+        if (!android::base::Readlink(link_name, &exe)) {
+            continue;
+        }
+
+        bool is_java_process;
+        if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+            // Don't bother dumping backtraces for the zygote.
+            if (IsZygote(pid)) {
+                continue;
+            }
+
+            dalvik_found = true;
+            is_java_process = true;
+        } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
+            is_java_process = false;
+        } else {
+            // Probably a native process we don't care about, continue.
+            continue;
+        }
+
+        // If 3 backtrace dumps fail in a row, consider debuggerd dead.
+        if (timeout_failures == 3) {
+            dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
+            break;
+        }
+
+        const uint64_t start = Nanotime();
+        const int ret = dump_backtrace_to_file_timeout(
+            pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+            is_java_process ? 5 : 20, fd);
+
+        if (ret == -1) {
+            // For consistency, the header and footer to this message match those
+            // dumped by debuggerd in the success case.
+            dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+            dprintf(fd, "Dump failed, likely due to a timeout.\n");
+            dprintf(fd, "---- end %d ----", pid);
+            timeout_failures++;
+            continue;
+        }
+
+        // We've successfully dumped stack traces, reset the failure count
+        // and write a summary of the elapsed time to the file and continue with the
+        // next process.
+        timeout_failures = 0;
+
+        dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
+                pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
+    }
+
+    if (!dalvik_found) {
+        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+    }
+
+    return file_name_buf.release();
+}
+
 void Dumpstate::DumpstateBoard() {
     DurationReporter duration_reporter("dumpstate_board()");
     printf("========================================================\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 96aacd4..603af71 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -291,6 +291,9 @@
     // TODO: temporary method until Dumpstate object is properly set
     void SetProgress(std::unique_ptr<Progress> progress);
 
+    // Dumps Dalvik and native stack traces, return the trace file location (nullptr if none).
+    const char* DumpTraces();
+
     void DumpstateBoard();
 
     /*
@@ -543,9 +546,6 @@
 /* create leading directories, if necessary */
 void create_parent_dirs(const char *path);
 
-/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
-const char *dump_traces();
-
 /* for each process in the system, run the specified function */
 void for_each_pid(for_each_pid_func func, const char *header);
 
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 7e641aa..8b92988 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -50,8 +50,6 @@
 #include <android-base/unique_fd.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
-#include <debuggerd/client.h>
-#include <dumputils/dump_utils.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
@@ -793,115 +791,6 @@
     return _redirect_to_file(redirect, path, O_APPEND);
 }
 
-// Dump Dalvik and native stack traces, return the trace file location (nullptr if none).
-const char* dump_traces() {
-    DurationReporter duration_reporter("DUMP TRACES");
-
-    const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
-    const size_t buf_size = temp_file_pattern.length() + 1;
-    std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
-    memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
-
-    // Create a new, empty file to receive all trace dumps.
-    //
-    // TODO: This can be simplified once we remove support for the old style
-    // dumps. We can have a file descriptor passed in to dump_traces instead
-    // of creating a file, closing it and then reopening it again.
-    android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
-    if (fd < 0) {
-        MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
-        return nullptr;
-    }
-
-    // Nobody should have access to this temporary file except dumpstate, but we
-    // temporarily grant 'read' to 'others' here because this file is created
-    // when tombstoned is still running as root, but dumped after dropping. This
-    // can go away once support for old style dumping has.
-    const int chmod_ret = fchmod(fd, 0666);
-    if (chmod_ret < 0) {
-        MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
-        return nullptr;
-    }
-
-    std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
-    if (proc.get() == nullptr) {
-        MYLOGE("opendir /proc failed: %s\n", strerror(errno));
-        return nullptr;
-    }
-
-    // Number of times process dumping has timed out. If we encounter too many
-    // failures, we'll give up.
-    int timeout_failures = 0;
-    bool dalvik_found = false;
-
-    const std::set<int> hal_pids = get_interesting_hal_pids();
-
-    struct dirent* d;
-    while ((d = readdir(proc.get()))) {
-        int pid = atoi(d->d_name);
-        if (pid <= 0) {
-            continue;
-        }
-
-        const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
-        std::string exe;
-        if (!android::base::Readlink(link_name, &exe)) {
-            continue;
-        }
-
-        bool is_java_process;
-        if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
-            // Don't bother dumping backtraces for the zygote.
-            if (IsZygote(pid)) {
-                continue;
-            }
-
-            dalvik_found = true;
-            is_java_process = true;
-        } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
-            is_java_process = false;
-        } else {
-            // Probably a native process we don't care about, continue.
-            continue;
-        }
-
-        // If 3 backtrace dumps fail in a row, consider debuggerd dead.
-        if (timeout_failures == 3) {
-            dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
-            break;
-        }
-
-        const uint64_t start = Nanotime();
-        const int ret = dump_backtrace_to_file_timeout(
-            pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
-            is_java_process ? 5 : 20, fd);
-
-        if (ret == -1) {
-            // For consistency, the header and footer to this message match those
-            // dumped by debuggerd in the success case.
-            dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
-            dprintf(fd, "Dump failed, likely due to a timeout.\n");
-            dprintf(fd, "---- end %d ----", pid);
-            timeout_failures++;
-            continue;
-        }
-
-        // We've successfully dumped stack traces, reset the failure count
-        // and write a summary of the elapsed time to the file and continue with the
-        // next process.
-        timeout_failures = 0;
-
-        dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
-                pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
-    }
-
-    if (!dalvik_found) {
-        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
-    }
-
-    return file_name_buf.release();
-}
-
 void dump_route_tables() {
     DurationReporter duration_reporter("DUMP ROUTE TABLES");
     if (PropertiesHelper::IsDryRun()) return;
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index b82141c..83a1048 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -106,28 +106,37 @@
     virtual bool isRemote() = 0;
 
     /**
-     * Dumps information about the interface.
+     * Dumps information about the interface. By default, dumps nothing.
      */
-    virtual binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
-        return STATUS_OK;
-    }
+    virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
+
+    /**
+     * Interprets this binder as this underlying interface if this has stored an ICInterface in the
+     * binder's user data.
+     *
+     * This does not do type checking and should only be used when the binder is known to originate
+     * from ICInterface. Most likely, you want to use I*::fromBinder.
+     */
+    static inline std::shared_ptr<ICInterface> asInterface(AIBinder* binder);
 
     /**
      * Helper method to create a class
      */
-    static AIBinder_Class* defineClass(const char* interfaceDescriptor,
-                                       AIBinder_Class_onCreate onCreate,
-                                       AIBinder_Class_onDestroy onDestroy,
-                                       AIBinder_Class_onTransact onTransact,
-                                       AIBinder_onDump onDump = nullptr) {
-        AIBinder_Class* clazz =
-                AIBinder_Class_define(interfaceDescriptor, onCreate, onDestroy, onTransact);
-        if (clazz == nullptr) {
-            return nullptr;
-        }
-        AIBinder_Class_setOnDump(clazz, onDump);
-        return clazz;
-    }
+    static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
+                                              AIBinder_Class_onTransact onTransact);
+
+   private:
+    class ICInterfaceData {
+       public:
+        std::shared_ptr<ICInterface> interface;
+
+        static inline std::shared_ptr<ICInterface> getInterface(AIBinder* binder);
+
+        static inline void* onCreate(void* args);
+        static inline void onDestroy(void* userData);
+        static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
+                                             uint32_t numArgs);
+    };
 };
 
 /**
@@ -141,7 +150,7 @@
 
     SpAIBinder asBinder() override;
 
-    bool isRemote() override { return true; }
+    bool isRemote() override { return false; }
 
    protected:
     /**
@@ -176,6 +185,55 @@
     SpAIBinder mBinder;
 };
 
+// END OF CLASS DECLARATIONS
+
+binder_status_t ICInterface::dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
+    return STATUS_OK;
+}
+
+std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
+    return ICInterfaceData::getInterface(binder);
+}
+
+AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
+                                         AIBinder_Class_onTransact onTransact) {
+    AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
+                                                  ICInterfaceData::onDestroy, onTransact);
+    if (clazz == nullptr) {
+        return nullptr;
+    }
+
+    // We can't know if this method is overriden by a subclass interface, so we must register
+    // ourselves. The default (nothing to dump) is harmless.
+    AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
+    return clazz;
+}
+
+std::shared_ptr<ICInterface> ICInterface::ICInterfaceData::getInterface(AIBinder* binder) {
+    if (binder == nullptr) return nullptr;
+
+    void* userData = AIBinder_getUserData(binder);
+    if (userData == nullptr) return nullptr;
+
+    return static_cast<ICInterfaceData*>(userData)->interface;
+}
+
+void* ICInterface::ICInterfaceData::onCreate(void* args) {
+    std::shared_ptr<ICInterface> interface = static_cast<ICInterface*>(args)->ref<ICInterface>();
+    ICInterfaceData* data = new ICInterfaceData{interface};
+    return static_cast<void*>(data);
+}
+
+void ICInterface::ICInterfaceData::onDestroy(void* userData) {
+    delete static_cast<ICInterfaceData*>(userData);
+}
+
+binder_status_t ICInterface::ICInterfaceData::onDump(AIBinder* binder, int fd, const char** args,
+                                                     uint32_t numArgs) {
+    std::shared_ptr<ICInterface> interface = getInterface(binder);
+    return interface->dump(fd, args, numArgs);
+}
+
 template <typename INTERFACE>
 SpAIBinder BnCInterface<INTERFACE>::asBinder() {
     std::lock_guard<std::mutex> l(mMutex);