Merge "[adb] Optimize fdevent machinery" into rvc-dev
diff --git a/adb/client/incremental_server.cpp b/adb/client/incremental_server.cpp
index 1f47de8..737563c 100644
--- a/adb/client/incremental_server.cpp
+++ b/adb/client/incremental_server.cpp
@@ -228,7 +228,7 @@
     std::vector<char> pendingBlocks_;
 
     // True when client notifies that all the data has been received
-    bool servingComplete_;
+    bool servingComplete_ = false;
 };
 
 bool IncrementalServer::SkipToRequest(void* buffer, size_t* size, bool blocking) {
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index 46d4bd3..2c0989e 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -34,14 +34,54 @@
 #include <stdlib.h>
 #include <string.h>
 
-void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline) {
+static void bootimg_set_cmdline_v3(boot_img_hdr_v3* h, const std::string& cmdline) {
     if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
     strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
 }
 
+void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline) {
+    if (h->header_version == 3) {
+        return bootimg_set_cmdline_v3(reinterpret_cast<boot_img_hdr_v3*>(h), cmdline);
+    }
+    if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
+    strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
+}
+
+static boot_img_hdr_v3* mkbootimg_v3(const std::vector<char>& kernel,
+                                     const std::vector<char>& ramdisk, const boot_img_hdr_v2& src,
+                                     std::vector<char>* out) {
+#define V3_PAGE_SIZE 4096
+    const size_t page_mask = V3_PAGE_SIZE - 1;
+    int64_t kernel_actual = (kernel.size() + page_mask) & (~page_mask);
+    int64_t ramdisk_actual = (ramdisk.size() + page_mask) & (~page_mask);
+
+    int64_t bootimg_size = V3_PAGE_SIZE + kernel_actual + ramdisk_actual;
+    out->resize(bootimg_size);
+
+    boot_img_hdr_v3* hdr = reinterpret_cast<boot_img_hdr_v3*>(out->data());
+
+    memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
+    hdr->kernel_size = kernel.size();
+    hdr->ramdisk_size = ramdisk.size();
+    hdr->os_version = src.os_version;
+    hdr->header_size = sizeof(boot_img_hdr_v3);
+    hdr->header_version = 3;
+
+    memcpy(hdr->magic + V3_PAGE_SIZE, kernel.data(), kernel.size());
+    memcpy(hdr->magic + V3_PAGE_SIZE + kernel_actual, ramdisk.data(), ramdisk.size());
+
+    return hdr;
+}
+
 boot_img_hdr_v2* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
                            const std::vector<char>& second, const std::vector<char>& dtb,
                            size_t base, const boot_img_hdr_v2& src, std::vector<char>* out) {
+    if (src.header_version == 3) {
+        if (!second.empty() || !dtb.empty()) {
+            die("Second stage bootloader and dtb not supported in v3 boot image\n");
+        }
+        return reinterpret_cast<boot_img_hdr_v2*>(mkbootimg_v3(kernel, ramdisk, src, out));
+    }
     const size_t page_mask = src.page_size - 1;
 
     int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 7fdc28b..7f6e723 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -464,7 +464,7 @@
     }
 
     // Is this actually a boot image?
-    if (kernel_data.size() < sizeof(boot_img_hdr_v2)) {
+    if (kernel_data.size() < sizeof(boot_img_hdr_v3)) {
         die("cannot load '%s': too short", kernel.c_str());
     }
     if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
@@ -493,7 +493,7 @@
 
     std::vector<char> dtb_data;
     if (!g_dtb_path.empty()) {
-        if (g_boot_img_hdr.header_version < 2) {
+        if (g_boot_img_hdr.header_version != 2) {
                     die("Argument dtb not supported for boot image header version %d\n",
                         g_boot_img_hdr.header_version);
         }
diff --git a/init/init.cpp b/init/init.cpp
index b29dfa3..4289dcf 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -713,8 +713,15 @@
     InitKernelLogging(argv);
     LOG(INFO) << "init second stage started!";
 
-    // Will handle EPIPE at the time of write by checking the errno
-    signal(SIGPIPE, SIG_IGN);
+    // Init should not crash because of a dependence on any other process, therefore we ignore
+    // SIGPIPE and handle EPIPE at the call site directly.  Note that setting a signal to SIG_IGN
+    // is inherited across exec, but custom signal handlers are not.  Since we do not want to
+    // ignore SIGPIPE for child processes, we set a no-op function for the signal handler instead.
+    {
+        struct sigaction action = {.sa_flags = SA_RESTART};
+        action.sa_handler = [](int) {};
+        sigaction(SIGPIPE, &action, nullptr);
+    }
 
     // Set init and its forked children's oom_adj.
     if (auto result =
diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h
index ad9b04e..0b0df2b 100644
--- a/libstats/pull/include/stats_pull_atom_callback.h
+++ b/libstats/pull/include/stats_pull_atom_callback.h
@@ -112,6 +112,8 @@
  * invoke the callback when the stats service determines that this atom needs to be
  * pulled.
  *
+ * Requires the REGISTER_STATS_PULL_ATOM permission.
+ *
  * \param atom_tag          The tag of the atom for this pull atom callback.
  * \param metadata          Optional metadata specifying the timeout, cool down time, and
  *                          additive fields for mapping isolated to host uids.
@@ -128,6 +130,8 @@
  * Unregisters a callback for an atom when that atom is to be pulled. Note that any ongoing
  * pulls will still occur.
  *
+ * Requires the REGISTER_STATS_PULL_ATOM permission.
+ *
  * \param atomTag           The tag of the atom of which to unregister
  */
 void AStatsManager_unregisterPullAtomCallback(int32_t atom_tag);
diff --git a/storaged/main.cpp b/storaged/main.cpp
index a7bda14..bbed210 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -71,6 +71,7 @@
     bool flag_dump_perf = false;
     int opt;
 
+    signal(SIGPIPE, SIG_IGN);
     android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
 
     for (;;) {