Merge "adb: move adb to poll."
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index c508b32..d287480 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -524,6 +524,20 @@
     return android::base::StringPrintf("%s:%s", prefix, command);
 }
 
+// Checks whether the device indicated by |transport_type| and |serial| supports
+// |feature|. Returns the response string, which will be empty if the device
+// could not be found or the feature is not supported.
+static std::string CheckFeature(const std::string& feature,
+                                TransportType transport_type,
+                                const char* serial) {
+    std::string result, error, command("check-feature:" + feature);
+    if (!adb_query(format_host_command(command.c_str(), transport_type, serial),
+                   &result, &error)) {
+        return "";
+    }
+    return result;
+}
+
 static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
                                bool show_progress)
 {
@@ -783,12 +797,15 @@
         wait_for_device("wait-for-device", transport_type, serial);
     }
 
-    read_and_dump(fd);
-    int rc = adb_close(fd);
-    if (rc) {
-        perror("close");
+    bool use_shell_protocol = !CheckFeature(kFeatureShell2, transport_type,
+                                            serial).empty();
+    int exit_code = read_and_dump(fd, use_shell_protocol);
+
+    if (adb_close(fd) < 0) {
+        PLOG(ERROR) << "failure closing FD " << fd;
     }
-    return rc;
+
+    return exit_code;
 }
 
 static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
@@ -1013,20 +1030,6 @@
 #endif
 }
 
-// Checks whether the device indicated by |transport_type| and |serial| supports
-// |feature|. Returns the response string, which will be empty if the device
-// could not be found or the feature is not supported.
-static std::string CheckFeature(const std::string& feature,
-                                TransportType transport_type,
-                                const char* serial) {
-    std::string result, error, command("check-feature:" + feature);
-    if (!adb_query(format_host_command(command.c_str(), transport_type, serial),
-                   &result, &error)) {
-        return "";
-    }
-    return result;
-}
-
 int adb_commandline(int argc, const char **argv) {
     int no_daemon = 0;
     int is_daemon = 0;
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 0274ae3..f1bc36d 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -413,6 +413,14 @@
             D("closing FD %d", dead_sfd->fd());
             FD_CLR(dead_sfd->fd(), &master_read_set);
             FD_CLR(dead_sfd->fd(), &master_write_set);
+            if (dead_sfd == &protocol_sfd_) {
+                // Using SIGHUP is a decent general way to indicate that the
+                // controlling process is going away. If specific signals are
+                // needed (e.g. SIGINT), pass those through the shell protocol
+                // and only fall back on this for unexpected closures.
+                D("protocol FD died, sending SIGHUP to pid %d", pid_);
+                kill(pid_, SIGHUP);
+            }
             dead_sfd->Reset();
         }
     }
diff --git a/adb/test_device.py b/adb/test_device.py
index fedd2d7..4452eed 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -23,6 +23,7 @@
 import random
 import shlex
 import shutil
+import signal
 import subprocess
 import tempfile
 import unittest
@@ -196,6 +197,34 @@
         self.assertEqual('foo' + self.device.linesep, result[1])
         self.assertEqual('bar' + self.device.linesep, result[2])
 
+    def test_non_interactive_sigint(self):
+        """Tests that SIGINT in a non-interactive shell kills the process.
+
+        This requires the shell protocol in order to detect the broken
+        pipe; raw data transfer mode will only see the break once the
+        subprocess tries to read or write.
+
+        Bug: http://b/23825725
+        """
+        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+            raise unittest.SkipTest('shell protocol unsupported on this device')
+
+        # Start a long-running process.
+        sleep_proc = subprocess.Popen(
+                self.device.adb_cmd + shlex.split('shell echo $$; sleep 60'),
+                stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT)
+        remote_pid = sleep_proc.stdout.readline().strip()
+        self.assertIsNone(sleep_proc.returncode, 'subprocess terminated early')
+        proc_query = shlex.split('ps {0} | grep {0}'.format(remote_pid))
+
+        # Verify that the process is running, send signal, verify it stopped.
+        self.device.shell(proc_query)
+        os.kill(sleep_proc.pid, signal.SIGINT)
+        sleep_proc.communicate()
+        self.assertEqual(1, self.device.shell_nocheck(proc_query)[0],
+                         'subprocess failed to terminate')
+
 
 class ArgumentEscapingTest(DeviceTest):
     def test_shell_escaping(self):
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index ca2d260..d0d6772 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -76,6 +76,9 @@
 # Set this to 1 to allow uploading of device coredumps.
 DEVCOREDUMP_UPLOAD_FLAG_FILE="${CRASH_STATE_DIR}/device_coredump_upload_allowed"
 
+# The weave configuration file.
+WEAVE_CONF_FILE="/etc/weaved/weaved.conf"
+
 # The syslog tag for all logging we emit.
 TAG="$(basename $0)[$$]"
 
@@ -296,6 +299,7 @@
   local version="$(get_key_value "${meta_path}" "upload_var_ver")"
   local upload_prefix="$(get_key_value "${meta_path}" "upload_prefix")"
   local guid
+  local model_manifest_id="$(get_key_value "${WEAVE_CONF_FILE}" "model_id")"
 
   # If crash_reporter.server is not set return with an error.
   if [ -z "${url}" ]; then
@@ -455,6 +459,7 @@
     -F "ver=${version}" \
     -F "hwclass=${hwclass}" \
     -F "exec_name=${exec_name}" \
+    -F "model_manifest_id=${model_manifest_id}" \
     ${image_type:+-F "image_type=${image_type}"} \
     ${boot_mode:+-F "boot_mode=${boot_mode}"} \
     ${error_type:+-F "error_type=${error_type}"} \