Merge "Initialize si_code in siginfo."
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index 7ee0464..ccb1aa6 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -32,3 +32,22 @@
         "-Werror",
     ],
 }
+
+// ========================================================
+// Benchmark
+// ========================================================
+cc_benchmark {
+    name: "android_fork_execvp_ext_benchmark",
+    srcs: [
+        "android_fork_execvp_ext_benchmark.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "liblogwrap",
+    ],
+    cflags: [
+        "-Werror",
+    ]
+}
diff --git a/logwrapper/android_fork_execvp_ext_benchmark.cpp b/logwrapper/android_fork_execvp_ext_benchmark.cpp
new file mode 100644
index 0000000..1abd932
--- /dev/null
+++ b/logwrapper/android_fork_execvp_ext_benchmark.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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 "logwrap/logwrap.h"
+
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+
+static void BM_android_fork_execvp_ext(benchmark::State& state) {
+    const char* argv[] = {"/system/bin/echo", "hello", "world"};
+    const int argc = 3;
+    while (state.KeepRunning()) {
+        int rc = android_fork_execvp_ext(
+            argc, (char**)argv, NULL /* status */, false /* ignore_int_quit */, LOG_NONE,
+            false /* abbreviated */, NULL /* file_path */, NULL /* opts */, 0 /* opts_len */);
+        CHECK_EQ(0, rc);
+    }
+}
+BENCHMARK(BM_android_fork_execvp_ext);
+
+BENCHMARK_MAIN();
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index 89a8fdd..d3538b3 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -54,9 +54,8 @@
  *           the specified log until the child has exited.
  *   file_path: if log_target has the LOG_FILE bit set, then this parameter
  *           must be set to the pathname of the file to log to.
- *   opts: set to non-NULL if you want to use one or more of the
- *           FORK_EXECVP_OPTION_* features.
- *   opts_len: the length of the opts array. When opts is NULL, pass 0.
+ *   unused_opts: currently unused.
+ *   unused_opts_len: currently unused.
  *
  * Return value:
  *   0 when logwrap successfully run the child process and captured its status
@@ -72,30 +71,10 @@
 #define LOG_KLOG        2
 #define LOG_FILE        4
 
-/* Write data to child's stdin. */
-#define FORK_EXECVP_OPTION_INPUT             0
-/* Capture data from child's stdout and stderr. */
-#define FORK_EXECVP_OPTION_CAPTURE_OUTPUT    1
-
-struct AndroidForkExecvpOption {
-    int opt_type;
-    union {
-        struct {
-            const uint8_t* input;
-            size_t input_len;
-        } opt_input;
-        struct {
-            void (*on_output)(const uint8_t* /*output*/,
-                              size_t /*output_len*/,
-                              void* /* user_pointer */);
-            void* user_pointer;
-        } opt_capture_output;
-    };
-};
-
+// TODO: Remove unused_opts / unused_opts_len in a followup change.
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len);
+        int log_target, bool abbreviated, char *file_path, void* unused_opts,
+        int unused_opts_len);
 
 /* Similar to above, except abbreviated logging is not available, and if logwrap
  * is true, logging is to the Android system log, and if false, there is no
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 3ad0983..7076078 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -291,8 +291,7 @@
 }
 
 static int parent(const char *tag, int parent_read, pid_t pid,
-        int *chld_sts, int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len) {
+        int *chld_sts, int log_target, bool abbreviated, char *file_path) {
     int status = 0;
     char buffer[4096];
     struct pollfd poll_fds[] = {
@@ -359,13 +358,6 @@
             sz = TEMP_FAILURE_RETRY(
                 read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
 
-            for (size_t i = 0; sz > 0 && i < opts_len; ++i) {
-                if (opts[i].opt_type == FORK_EXECVP_OPTION_CAPTURE_OUTPUT) {
-                  opts[i].opt_capture_output.on_output(
-                      (uint8_t*)&buffer[b], sz, opts[i].opt_capture_output.user_pointer);
-                }
-            }
-
             sz += b;
             // Log one line at a time
             for (b = 0; b < sz; b++) {
@@ -483,7 +475,7 @@
 
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
         int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len) {
+        void *unused_opts, int unused_opts_len) {
     pid_t pid;
     int parent_ptty;
     int child_ptty;
@@ -493,6 +485,9 @@
     sigset_t oldset;
     int rc = 0;
 
+    LOG_ALWAYS_FATAL_IF(unused_opts != NULL);
+    LOG_ALWAYS_FATAL_IF(unused_opts_len != 0);
+
     rc = pthread_mutex_lock(&fd_mutex);
     if (rc) {
         ERROR("failed to lock signal_fd mutex\n");
@@ -538,13 +533,6 @@
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
         close(parent_ptty);
 
-        // redirect stdin, stdout and stderr
-        for (size_t i = 0; i < opts_len; ++i) {
-            if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
-                dup2(child_ptty, 0);
-                break;
-            }
-        }
         dup2(child_ptty, 1);
         dup2(child_ptty, 2);
         close(child_ptty);
@@ -561,24 +549,8 @@
             sigaction(SIGQUIT, &ignact, &quitact);
         }
 
-        for (size_t i = 0; i < opts_len; ++i) {
-            if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
-                size_t left = opts[i].opt_input.input_len;
-                const uint8_t* input = opts[i].opt_input.input;
-                while (left > 0) {
-                    ssize_t res =
-                        TEMP_FAILURE_RETRY(write(parent_ptty, input, left));
-                    if (res < 0) {
-                        break;
-                    }
-                    left -= res;
-                    input += res;
-                }
-            }
-        }
-
         rc = parent(argv[0], parent_ptty, pid, status, log_target,
-                    abbreviated, file_path, opts, opts_len);
+                    abbreviated, file_path);
     }
 
     if (ignore_int_quit) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index dcb3b25..06dc88b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -346,6 +346,9 @@
     # create the lost+found directories, so as to enforce our permissions
     mkdir /cache/lost+found 0770 root root
 
+on late-fs
+    start hwservicemanager
+
 on post-fs-data
     # We chown/chmod /data again so because mount is run as root + defaults
     chown system system /data
@@ -586,8 +589,9 @@
     # Define default initial receive window size in segments.
     setprop net.tcp.default_init_rwnd 60
 
-    # Start all binderized HAL daemons
-    start hwservicemanager
+    # Start standard binderized HAL daemons
+    class_start hal
+
     class_start core
 
 on nonencrypted