Merge "ueventd: make parallel restorecon functionality optional"
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index c592c37..7e90e0c 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -110,3 +110,9 @@
 
 For boot time purposes, this is done in parallel across a set of child processes. `ueventd.cpp` in
 this directory contains documentation on how the parallelization is done.
+
+There is an option to parallelize the restorecon function during cold boot as well. This should only
+be done for devices that do not use genfscon, which is the recommended method for labeling sysfs
+nodes. To enable this option, use the below line in a ueventd.rc script:
+
+    parallel_restorecon enabled
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index cffc1b9..6741e2a 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -113,10 +113,12 @@
 class ColdBoot {
   public:
     ColdBoot(UeventListener& uevent_listener,
-             std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers)
+             std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers,
+             bool enable_parallel_restorecon)
         : uevent_listener_(uevent_listener),
           uevent_handlers_(uevent_handlers),
-          num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {}
+          num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4),
+          enable_parallel_restorecon_(enable_parallel_restorecon) {}
 
     void Run();
 
@@ -132,6 +134,8 @@
     std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers_;
 
     unsigned int num_handler_subprocesses_;
+    bool enable_parallel_restorecon_;
+
     std::vector<Uevent> uevent_queue_;
 
     std::set<pid_t> subprocess_pids_;
@@ -155,7 +159,6 @@
 
         selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
     }
-    _exit(EXIT_SUCCESS);
 }
 
 void ColdBoot::GenerateRestoreCon(const std::string& directory) {
@@ -195,7 +198,10 @@
 
         if (pid == 0) {
             UeventHandlerMain(i, num_handler_subprocesses_);
-            RestoreConHandler(i, num_handler_subprocesses_);
+            if (enable_parallel_restorecon_) {
+                RestoreConHandler(i, num_handler_subprocesses_);
+            }
+            _exit(EXIT_SUCCESS);
         }
 
         subprocess_pids_.emplace(pid);
@@ -240,14 +246,20 @@
 
     RegenerateUevents();
 
-    selinux_android_restorecon("/sys", 0);
-    selinux_android_restorecon("/sys/devices", 0);
-    GenerateRestoreCon("/sys");
-    // takes long time for /sys/devices, parallelize it
-    GenerateRestoreCon("/sys/devices");
+    if (enable_parallel_restorecon_) {
+        selinux_android_restorecon("/sys", 0);
+        selinux_android_restorecon("/sys/devices", 0);
+        GenerateRestoreCon("/sys");
+        // takes long time for /sys/devices, parallelize it
+        GenerateRestoreCon("/sys/devices");
+    }
 
     ForkSubProcesses();
 
+    if (!enable_parallel_restorecon_) {
+        selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
+    }
+
     WaitForSubProcesses();
 
     android::base::SetProperty(kColdBootDoneProp, "true");
@@ -293,7 +305,8 @@
     UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
 
     if (!android::base::GetBoolProperty(kColdBootDoneProp, false)) {
-        ColdBoot cold_boot(uevent_listener, uevent_handlers);
+        ColdBoot cold_boot(uevent_listener, uevent_handlers,
+                           ueventd_configuration.enable_parallel_restorecon);
         cold_boot.Run();
     }
 
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 8ee0cce..1ca1715 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -88,18 +88,17 @@
     return {};
 }
 
-Result<void> ParseModaliasHandlingLine(std::vector<std::string>&& args,
-                                       bool* enable_modalias_handling) {
+Result<void> ParseEnabledDisabledLine(std::vector<std::string>&& args, bool* feature) {
     if (args.size() != 2) {
-        return Error() << "modalias_handling lines take exactly one parameter";
+        return Error() << args[0] << " lines take exactly one parameter";
     }
 
     if (args[1] == "enabled") {
-        *enable_modalias_handling = true;
+        *feature = true;
     } else if (args[1] == "disabled") {
-        *enable_modalias_handling = false;
+        *feature = false;
     } else {
-        return Error() << "modalias_handling takes either 'enabled' or 'disabled' as a parameter";
+        return Error() << args[0] << " takes either 'enabled' or 'disabled' as a parameter";
     }
 
     return {};
@@ -213,11 +212,14 @@
                                std::bind(ParseFirmwareDirectoriesLine, _1,
                                          &ueventd_configuration.firmware_directories));
     parser.AddSingleLineParser("modalias_handling",
-                               std::bind(ParseModaliasHandlingLine, _1,
+                               std::bind(ParseEnabledDisabledLine, _1,
                                          &ueventd_configuration.enable_modalias_handling));
     parser.AddSingleLineParser("uevent_socket_rcvbuf_size",
                                std::bind(ParseUeventSocketRcvbufSizeLine, _1,
                                          &ueventd_configuration.uevent_socket_rcvbuf_size));
+    parser.AddSingleLineParser("parallel_restorecon",
+                               std::bind(ParseEnabledDisabledLine, _1,
+                                         &ueventd_configuration.enable_parallel_restorecon));
 
     for (const auto& config : configs) {
         parser.ParseConfig(config);
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index d476dec..b54dba8 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_UEVENTD_PARSER_H
-#define _INIT_UEVENTD_PARSER_H
+#pragma once
 
 #include <string>
 #include <vector>
@@ -32,11 +31,10 @@
     std::vector<std::string> firmware_directories;
     bool enable_modalias_handling = false;
     size_t uevent_socket_rcvbuf_size = 0;
+    bool enable_parallel_restorecon = false;
 };
 
 UeventdConfiguration ParseConfig(const std::vector<std::string>& configs);
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index 9c1cedf..885e79d 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -147,6 +147,24 @@
     TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 8 * 1024 * 1024});
 }
 
+TEST(ueventd_parser, EnabledDisabledLines) {
+    auto ueventd_file = R"(
+modalias_handling enabled
+parallel_restorecon enabled
+modalias_handling disabled
+)";
+
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 0, true});
+
+    auto ueventd_file2 = R"(
+parallel_restorecon enabled
+modalias_handling enabled
+parallel_restorecon disabled
+)";
+
+    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, true, 0, false});
+}
+
 TEST(ueventd_parser, AllTogether) {
     auto ueventd_file = R"(
 
@@ -179,6 +197,8 @@
 firmware_directories /more
 
 uevent_socket_rcvbuf_size 6M
+modalias_handling enabled
+parallel_restorecon enabled
 
 #ending comment
 )";
@@ -211,7 +231,7 @@
     size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
 
     TestUeventdFile(ueventd_file, {subsystems, sysfs_permissions, permissions, firmware_directories,
-                                   false, uevent_socket_rcvbuf_size});
+                                   true, uevent_socket_rcvbuf_size, true});
 }
 
 // All of these lines are ill-formed, so test that there is 0 output.
@@ -230,6 +250,13 @@
 
 subsystem #no name
 
+modalias_handling
+modalias_handling enabled enabled
+modalias_handling blah
+
+parallel_restorecon
+parallel_restorecon enabled enabled
+parallel_restorecon blah
 )";
 
     TestUeventdFile(ueventd_file, {});