Merge "Revert "libbinder: Choose the binder driver at runtime based on system/vendor process.""
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3c47767..51b2307 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>
@@ -1184,6 +1186,15 @@
 }
 
 static void DumpHals() {
+    if (!ds.IsZipping()) {
+        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
+                   CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+        return;
+    }
+    DurationReporter duration_reporter("DUMP HALS");
+    RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
+               CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+
     using android::hidl::manager::V1_0::IServiceManager;
     using android::hardware::defaultServiceManager;
 
@@ -1260,14 +1271,7 @@
                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
     RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
 
-    if (ds.IsZipping()) {
-        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
-                   CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
-        DumpHals();
-    } else {
-        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
-                   CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
-    }
+    DumpHals();
 
     RunCommand("PRINTENV", {"printenv"});
     RunCommand("NETSTAT", {"netstat", "-nW"});
@@ -1444,7 +1448,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());
@@ -1567,20 +1571,121 @@
     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
 
-    if (ds.IsZipping()) {
-        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
-                   CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
-        DumpHals();
-    } else {
-        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
-                   CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
-    }
+    DumpHals();
 
     printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
     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 c326bb6..603af71 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -73,13 +73,13 @@
  */
 class DurationReporter {
   public:
-    explicit DurationReporter(const std::string& title, bool log_only = false);
+    explicit DurationReporter(const std::string& title, bool logcat_only = false);
 
     ~DurationReporter();
 
   private:
     std::string title_;
-    bool log_only_;
+    bool logcat_only_;
     uint64_t started_;
 
     DISALLOW_COPY_AND_ASSIGN(DurationReporter);
@@ -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 2a5516d..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>
 
@@ -95,8 +93,8 @@
     return singleton_;
 }
 
-DurationReporter::DurationReporter(const std::string& title, bool log_only)
-    : title_(title), log_only_(log_only) {
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
+    : title_(title), logcat_only_(logcat_only) {
     if (!title_.empty()) {
         started_ = Nanotime();
     }
@@ -105,15 +103,13 @@
 DurationReporter::~DurationReporter() {
     if (!title_.empty()) {
         uint64_t elapsed = Nanotime() - started_;
-        if (log_only_) {
-            MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
-        } else {
-            // TODO(124089395): Remove or rewrite when bugreport latency is fixed.
-            MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
-            // Use "Yoda grammar" to make it easier to grep|sort sections.
-            printf("------ %.3fs was the duration of '%s' ------\n", (float)elapsed / NANOS_PER_SEC,
-                   title_.c_str());
+        MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
+        if (logcat_only_) {
+            return;
         }
+        // Use "Yoda grammar" to make it easier to grep|sort sections.
+        printf("------ %.3fs was the duration of '%s' ------\n", (float)elapsed / NANOS_PER_SEC,
+               title_.c_str());
     }
 }
 
@@ -795,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/cmds/installd/OWNERS b/cmds/installd/OWNERS
index 5d4f176..5673918 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -3,6 +3,8 @@
 agampe@google.com
 calin@google.com
 jsharkey@android.com
+maco@google.com
 mathieuc@google.com
+narayan@google.com
 ngeoffray@google.com
 toddke@google.com
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 1ea2c2c..ecdc075 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -41,6 +41,13 @@
  *
  * Note that this structure is used for IPCs so its layout must be identical
  * on 64 and 32 bit processes. This is tested in StructLayout_test.cpp.
+ *
+ * Since the struct must be aligned to an 8-byte boundary, there could be uninitialized bytes
+ * in-between the defined fields. This padding data should be explicitly accounted for by adding
+ * "empty" fields into the struct. This data is memset to zero before sending the struct across
+ * the socket. Adding the explicit fields ensures that the memset is not optimized away by the
+ * compiler. When a new field is added to the struct, the corresponding change
+ * in StructLayout_test should be made.
  */
 struct InputMessage {
     enum {
@@ -61,6 +68,7 @@
     union Body {
         struct Key {
             uint32_t seq;
+            uint32_t empty1;
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
@@ -71,6 +79,7 @@
             int32_t scanCode;
             int32_t metaState;
             int32_t repeatCount;
+            uint32_t empty2;
             nsecs_t downTime __attribute__((aligned(8)));
 
             inline size_t size() const {
@@ -80,6 +89,7 @@
 
         struct Motion {
             uint32_t seq;
+            uint32_t empty1;
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
@@ -90,12 +100,14 @@
             int32_t metaState;
             int32_t buttonState;
             int32_t edgeFlags;
+            uint32_t empty2;
             nsecs_t downTime __attribute__((aligned(8)));
             float xOffset;
             float yOffset;
             float xPrecision;
             float yPrecision;
             uint32_t pointerCount;
+            uint32_t empty3;
             // Note that PointerCoords requires 8 byte alignment.
             struct Pointer {
                 PointerProperties properties;
@@ -126,6 +138,7 @@
 
     bool isValid(size_t actualSize) const;
     size_t size() const;
+    void getSanitizedCopy(InputMessage* msg) const;
 };
 
 /*
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index f9c8c8a..bdbc0d3 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -31,6 +31,7 @@
 using ::android::sp;
 using ::android::status_t;
 using ::android::String16;
+using ::android::String8;
 using ::android::wp;
 
 namespace ABBinderTag {
@@ -67,8 +68,6 @@
 AIBinder::~AIBinder() {}
 
 bool AIBinder::associateClass(const AIBinder_Class* clazz) {
-    using ::android::String8;
-
     if (clazz == nullptr) return false;
     if (mClazz == clazz) return true;
 
@@ -119,6 +118,33 @@
     return getClass()->getInterfaceDescriptor();
 }
 
+status_t ABBinder::dump(int fd, const ::android::Vector<String16>& args) {
+    AIBinder_onDump onDump = getClass()->onDump;
+
+    if (onDump == nullptr) {
+        return STATUS_OK;
+    }
+
+    // technically UINT32_MAX would be okay here, but INT32_MAX is expected since this may be
+    // null in Java
+    if (args.size() > INT32_MAX) {
+        LOG(ERROR) << "ABBinder::dump received too many arguments: " << args.size();
+        return STATUS_BAD_VALUE;
+    }
+
+    std::vector<String8> utf8Args;  // owns memory of utf8s
+    utf8Args.reserve(args.size());
+    std::vector<const char*> utf8Pointers;  // what can be passed over NDK API
+    utf8Pointers.reserve(args.size());
+
+    for (size_t i = 0; i < args.size(); i++) {
+        utf8Args.push_back(String8(args[i]));
+        utf8Pointers.push_back(utf8Args[i].c_str());
+    }
+
+    return onDump(this, fd, utf8Pointers.data(), utf8Pointers.size());
+}
+
 status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
                               binder_flags_t flags) {
     if (isUserCommand(code)) {
@@ -232,6 +258,13 @@
     return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
 }
 
+void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) {
+    CHECK(clazz != nullptr) << "setOnDump requires non-null clazz";
+
+    // this is required to be called before instances are instantiated
+    clazz->onDump = onDump;
+}
+
 void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
     CHECK(who == mWho);
 
@@ -325,6 +358,30 @@
     return PruneStatusT(binder->getBinder()->pingBinder());
 }
 
+binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint32_t numArgs) {
+    if (binder == nullptr) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    ABBinder* bBinder = binder->asABBinder();
+    if (bBinder != nullptr) {
+        AIBinder_onDump onDump = binder->getClass()->onDump;
+        if (onDump == nullptr) {
+            return STATUS_OK;
+        }
+        return PruneStatusT(onDump(bBinder, fd, args, numArgs));
+    }
+
+    ::android::Vector<String16> utf16Args;
+    utf16Args.setCapacity(numArgs);
+    for (uint32_t i = 0; i < numArgs; i++) {
+        utf16Args.push(String16(String8(args[i])));
+    }
+
+    status_t status = binder->getBinder()->dump(fd, utf16Args);
+    return PruneStatusT(status);
+}
+
 binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
                                      void* cookie) {
     if (binder == nullptr || recipient == nullptr) {
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 7852298..0dd795a 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -25,6 +25,7 @@
 
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
+#include <utils/Vector.h>
 
 inline bool isUserCommand(transaction_code_t code) {
     return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION;
@@ -66,6 +67,7 @@
     ABBinder* asABBinder() override { return this; }
 
     const ::android::String16& getInterfaceDescriptor() const override;
+    ::android::status_t dump(int fd, const ::android::Vector<::android::String16>& args) override;
     ::android::status_t onTransact(uint32_t code, const ::android::Parcel& data,
                                    ::android::Parcel* reply, binder_flags_t flags) override;
 
@@ -106,10 +108,14 @@
 
     const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
 
+    // required to be non-null, implemented for every class
     const AIBinder_Class_onCreate onCreate;
     const AIBinder_Class_onDestroy onDestroy;
     const AIBinder_Class_onTransact onTransact;
 
+    // optional methods for a class
+    AIBinder_onDump onDump;
+
    private:
     // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
     // one.
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 9c6c55e..bddc10d 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -179,6 +179,31 @@
         __INTRODUCED_IN(29);
 
 /**
+ * Dump information about an AIBinder (usually for debugging).
+ *
+ * When no arguments are provided, a brief overview of the interview should be given.
+ *
+ * \param binder interface being dumped
+ * \param fd file descriptor to be dumped to, should be flushed, ownership is not passed.
+ * \param args array of null-terminated strings for dump (may be null if numArgs is 0)
+ * \param numArgs number of args to be sent
+ *
+ * \return binder_status_t result of transaction (if remote, for instance)
+ */
+typedef binder_status_t (*AIBinder_onDump)(AIBinder* binder, int fd, const char** args,
+                                           uint32_t numArgs);
+
+/**
+ * This sets the implementation of the dump method for a class.
+ *
+ * If this isn't set, nothing will be dumped when dump is called (for instance with
+ * android.os.Binder#dump). Must be called before any instance of the class is created.
+ *
+ * \param dump function to call when an instance of this binder class is being dumped.
+ */
+void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
+
+/**
  * Creates a new binder object of the appropriate class.
  *
  * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
@@ -237,6 +262,21 @@
 binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
+ * Built-in transaction for all binder objects. This dumps information about a given binder.
+ *
+ * See also AIBinder_Class_setOnDump, AIBinder_onDump
+ *
+ * \param binder the binder to dump information about
+ * \param fd where information should be dumped to
+ * \param args null-terminated arguments to pass (may be null if numArgs is 0)
+ * \param numArgs number of args to send
+ *
+ * \return STATUS_OK if dump succeeds (or if there is nothing to dump)
+ */
+binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint32_t numArgs)
+        __INTRODUCED_IN(29);
+
+/**
  * Registers for notifications that the associated binder is dead. The same death recipient may be
  * associated with multiple different binders. If the binder is local, then no death recipient will
  * be given (since if the local process dies, then no recipient will exist to recieve a
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 a42c60b..83a1048 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -104,6 +104,39 @@
      * this will be checked using AIBinder_isRemote.
      */
     virtual bool isRemote() = 0;
+
+    /**
+     * Dumps information about the interface. By default, dumps nothing.
+     */
+    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 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);
+    };
 };
 
 /**
@@ -117,7 +150,7 @@
 
     SpAIBinder asBinder() override;
 
-    bool isRemote() override { return true; }
+    bool isRemote() override { return false; }
 
    protected:
     /**
@@ -144,10 +177,63 @@
 
     bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override {
+        return AIBinder_dump(asBinder().get(), fd, args, numArgs);
+    }
+
    private:
     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);
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 655f4d5..7e65817 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -2,10 +2,12 @@
   global:
     AIBinder_associateClass;
     AIBinder_Class_define;
+    AIBinder_Class_setOnDump;
     AIBinder_DeathRecipient_delete;
     AIBinder_DeathRecipient_new;
     AIBinder_debugGetRefCount;
     AIBinder_decStrong;
+    AIBinder_dump;
     AIBinder_fromJavaBinder;
     AIBinder_getCallingPid;
     AIBinder_getCallingUid;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index aa0bf17..03f593f 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -96,6 +96,106 @@
     return sizeof(Header);
 }
 
+/**
+ * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire
+ * memory to zero, then only copy the valid bytes on a per-field basis.
+ */
+void InputMessage::getSanitizedCopy(InputMessage* msg) const {
+    memset(msg, 0, sizeof(*msg));
+
+    // Write the header
+    msg->header.type = header.type;
+
+    // Write the body
+    switch(header.type) {
+        case InputMessage::TYPE_KEY: {
+            // uint32_t seq
+            msg->body.key.seq = body.key.seq;
+            // nsecs_t eventTime
+            msg->body.key.eventTime = body.key.eventTime;
+            // int32_t deviceId
+            msg->body.key.deviceId = body.key.deviceId;
+            // int32_t source
+            msg->body.key.source = body.key.source;
+            // int32_t displayId
+            msg->body.key.displayId = body.key.displayId;
+            // int32_t action
+            msg->body.key.action = body.key.action;
+            // int32_t flags
+            msg->body.key.flags = body.key.flags;
+            // int32_t keyCode
+            msg->body.key.keyCode = body.key.keyCode;
+            // int32_t scanCode
+            msg->body.key.scanCode = body.key.scanCode;
+            // int32_t metaState
+            msg->body.key.metaState = body.key.metaState;
+            // int32_t repeatCount
+            msg->body.key.repeatCount = body.key.repeatCount;
+            // nsecs_t downTime
+            msg->body.key.downTime = body.key.downTime;
+            break;
+        }
+        case InputMessage::TYPE_MOTION: {
+            // uint32_t seq
+            msg->body.motion.seq = body.motion.seq;
+            // nsecs_t eventTime
+            msg->body.motion.eventTime = body.motion.eventTime;
+            // int32_t deviceId
+            msg->body.motion.deviceId = body.motion.deviceId;
+            // int32_t source
+            msg->body.motion.source = body.motion.source;
+            // int32_t displayId
+            msg->body.motion.displayId = body.motion.displayId;
+            // int32_t action
+            msg->body.motion.action = body.motion.action;
+            // int32_t actionButton
+            msg->body.motion.actionButton = body.motion.actionButton;
+            // int32_t flags
+            msg->body.motion.flags = body.motion.flags;
+            // int32_t metaState
+            msg->body.motion.metaState = body.motion.metaState;
+            // int32_t buttonState
+            msg->body.motion.buttonState = body.motion.buttonState;
+            // int32_t edgeFlags
+            msg->body.motion.edgeFlags = body.motion.edgeFlags;
+            // nsecs_t downTime
+            msg->body.motion.downTime = body.motion.downTime;
+            // float xOffset
+            msg->body.motion.xOffset = body.motion.xOffset;
+            // float yOffset
+            msg->body.motion.yOffset = body.motion.yOffset;
+            // float xPrecision
+            msg->body.motion.xPrecision = body.motion.xPrecision;
+            // float yPrecision
+            msg->body.motion.yPrecision = body.motion.yPrecision;
+            // uint32_t pointerCount
+            msg->body.motion.pointerCount = body.motion.pointerCount;
+            //struct Pointer pointers[MAX_POINTERS]
+            for (size_t i = 0; i < body.motion.pointerCount; i++) {
+                // PointerProperties properties
+                msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id;
+                msg->body.motion.pointers[i].properties.toolType =
+                        body.motion.pointers[i].properties.toolType,
+                // PointerCoords coords
+                msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits;
+                const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits);
+                memcpy(&msg->body.motion.pointers[i].coords.values[0],
+                        &body.motion.pointers[i].coords.values[0],
+                        count * (sizeof(body.motion.pointers[i].coords.values[0])));
+            }
+            break;
+        }
+        case InputMessage::TYPE_FINISHED: {
+            msg->body.finished.seq = body.finished.seq;
+            msg->body.finished.handled = body.finished.handled;
+            break;
+        }
+        default: {
+            LOG_FATAL("Unexpected message type %i", header.type);
+            break;
+        }
+    }
+}
 
 // --- InputChannel ---
 
@@ -149,10 +249,12 @@
 }
 
 status_t InputChannel::sendMessage(const InputMessage* msg) {
-    size_t msgLength = msg->size();
+    const size_t msgLength = msg->size();
+    InputMessage cleanMsg;
+    msg->getSanitizedCopy(&cleanMsg);
     ssize_t nWrite;
     do {
-        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
+        nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     } while (nWrite == -1 && errno == EINTR);
 
     if (nWrite < 0) {
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index d19f3b8..12a6782 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -65,6 +65,9 @@
   CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
   CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
   CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+
+  CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
+  CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
 }
 
 } // namespace android
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index d25ad1a..ec7f927 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,6 +45,8 @@
 
         // Don't warn about struct padding
         "-Wno-padded",
+
+        "-Wno-switch-enum",
     ],
 
     sanitize: {
@@ -63,6 +65,7 @@
         "GraphicBufferMapper.cpp",
         "HdrCapabilities.cpp",
         "PixelFormat.cpp",
+        "PublicFormat.cpp",
         "Rect.cpp",
         "Region.cpp",
         "UiConfig.cpp",
diff --git a/libs/ui/PublicFormat.cpp b/libs/ui/PublicFormat.cpp
new file mode 100644
index 0000000..26eb771
--- /dev/null
+++ b/libs/ui/PublicFormat.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <ui/PublicFormat.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+int mapPublicFormatToHalFormat(PublicFormat f) {
+    switch (f) {
+        case PublicFormat::JPEG:
+        case PublicFormat::DEPTH_POINT_CLOUD:
+            return HAL_PIXEL_FORMAT_BLOB;
+        case PublicFormat::DEPTH16:
+            return HAL_PIXEL_FORMAT_Y16;
+        case PublicFormat::RAW_SENSOR:
+        case PublicFormat::RAW_DEPTH:
+            return HAL_PIXEL_FORMAT_RAW16;
+        default:
+            // Most formats map 1:1
+            return static_cast<int>(f);
+    }
+}
+
+android_dataspace mapPublicFormatToHalDataspace(PublicFormat f) {
+    switch (f) {
+        case PublicFormat::JPEG:
+            return HAL_DATASPACE_V0_JFIF;
+        case PublicFormat::DEPTH_POINT_CLOUD:
+        case PublicFormat::DEPTH16:
+        case PublicFormat::RAW_DEPTH:
+            return HAL_DATASPACE_DEPTH;
+        case PublicFormat::RAW_SENSOR:
+        case PublicFormat::RAW_PRIVATE:
+        case PublicFormat::RAW10:
+        case PublicFormat::RAW12:
+            return HAL_DATASPACE_ARBITRARY;
+        case PublicFormat::YUV_420_888:
+        case PublicFormat::NV21:
+        case PublicFormat::YV12:
+            return HAL_DATASPACE_V0_JFIF;
+        default:
+            // Most formats map to UNKNOWN
+            return HAL_DATASPACE_UNKNOWN;
+    }
+}
+
+PublicFormat mapHalFormatDataspaceToPublicFormat(int format, android_dataspace dataSpace) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_Y8:
+        case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW12:
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        case HAL_PIXEL_FORMAT_YV12:
+            // Enums overlap in both name and value
+            return static_cast<PublicFormat>(format);
+        case HAL_PIXEL_FORMAT_RAW16:
+            switch (dataSpace) {
+                case HAL_DATASPACE_DEPTH:
+                    return PublicFormat::RAW_DEPTH;
+                default:
+                    return PublicFormat::RAW_SENSOR;
+            }
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+            // Name differs, though value is the same
+            return PublicFormat::RAW_PRIVATE;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            // Name differs, though the value is the same
+            return PublicFormat::NV16;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            // Name differs, though the value is the same
+            return PublicFormat::NV21;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            // Name differs, though the value is the same
+            return PublicFormat::YUY2;
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+            // Name differs, though the value is the same
+            return PublicFormat::PRIVATE;
+        case HAL_PIXEL_FORMAT_Y16:
+            // Dataspace-dependent
+            switch (dataSpace) {
+                case HAL_DATASPACE_DEPTH:
+                    return PublicFormat::DEPTH16;
+                default:
+                    // Assume non-depth Y16 is just Y16.
+                    return PublicFormat::Y16;
+            }
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Dataspace-dependent
+            switch (dataSpace) {
+                case HAL_DATASPACE_DEPTH:
+                    return PublicFormat::DEPTH_POINT_CLOUD;
+                case HAL_DATASPACE_V0_JFIF:
+                    return PublicFormat::JPEG;
+                default:
+                    // Assume otherwise-marked blobs are also JPEG
+                    return PublicFormat::JPEG;
+            }
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            // Not defined in public API
+            return PublicFormat::UNKNOWN;
+
+        default:
+            return PublicFormat::UNKNOWN;
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/libs/ui/include/ui/PublicFormat.h b/libs/ui/include/ui/PublicFormat.h
new file mode 100644
index 0000000..75b6705
--- /dev/null
+++ b/libs/ui/include/ui/PublicFormat.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef UI_PUBLICFORMAT_H
+#define UI_PUBLICFORMAT_H
+
+#include <system/graphics.h>
+
+namespace android {
+
+/**
+ * Enum mirroring the public API definitions for image and pixel formats.
+ * Some of these are hidden in the public API
+ *
+ * Keep up to date with android.graphics.ImageFormat and
+ * android.graphics.PixelFormat
+ *
+ * TODO: PublicFormat is going to be deprecated(b/126594675)
+ */
+enum class PublicFormat {
+    UNKNOWN = 0x0,
+    RGBA_8888 = 0x1,
+    RGBX_8888 = 0x2,
+    RGB_888 = 0x3,
+    RGB_565 = 0x4,
+    NV16 = 0x10,
+    NV21 = 0x11,
+    YUY2 = 0x14,
+    RGBA_FP16 = 0x16,
+    RAW_SENSOR = 0x20,
+    PRIVATE = 0x22,
+    YUV_420_888 = 0x23,
+    RAW_PRIVATE = 0x24,
+    RAW10 = 0x25,
+    RAW12 = 0x26,
+    RGBA_1010102 = 0x2b,
+    JPEG = 0x100,
+    DEPTH_POINT_CLOUD = 0x101,
+    RAW_DEPTH = 0x1002, // @hide
+    YV12 = 0x32315659,
+    Y8 = 0x20203859,  // @hide
+    Y16 = 0x20363159, // @hide
+    DEPTH16 = 0x44363159
+};
+
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * format */
+extern int mapPublicFormatToHalFormat(PublicFormat f);
+
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * dataspace */
+extern android_dataspace mapPublicFormatToHalDataspace(PublicFormat f);
+
+/* Convert from HAL format, dataspace pair to
+ * android.graphics.ImageFormat/PixelFormat.
+ * For unknown/unspecified pairs, returns PublicFormat::UNKNOWN */
+extern PublicFormat mapHalFormatDataspaceToPublicFormat(int format, android_dataspace dataSpace);
+
+}; // namespace android
+
+#endif // UI_PUBLICFORMAT_H