add "shutdown critical" to service

- "shutdown critical" prevents killing the service during
  shutdown. And the service will be started if not running.
- Without it, services will be killed by SIGTERM / SIGKILL during shutdown.
- Even services with "shutdown critical" will be killed if shutdown
  times out.
- Removes ueventd and vold from hard coded list. Each service's rc will
  be updated to add "shutdown critical". watchdogd is still kept in the list.

bug: 37626581
Test: reboot and check last kmsg

Change-Id: Ie8cc699d1efbc59b9a2561bdd40fec64aed5a4bb
diff --git a/init/README.md b/init/README.md
index 72b6c6b..422fdad 100644
--- a/init/README.md
+++ b/init/README.md
@@ -260,6 +260,14 @@
 > Sets the child's /proc/self/oom\_score\_adj to the specified value,
   which must range from -1000 to 1000.
 
+`shutdown <shutdown_behavior>`
+> Set shutdown behavior of the service process. When this is not specified,
+  the service is killed during shutdown process by using SIGTERM and SIGKILL.
+  The service with shutdown_behavior of "critical" is not killed during shutdown
+  until shutdown times out. When shutdown times out, even services tagged with
+  "shutdown critical" will be killed. When the service tagged with "shutdown critical"
+  is not running when shut down starts, it will be started.
+
 
 Triggers
 --------
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 34c98a7..a489c16 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -364,13 +364,15 @@
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
-    const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
+    const std::set<std::string> to_starts{"watchdogd"};
     ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
         if (kill_after_apps.count(s->name())) {
             s->SetShutdownCritical();
         } else if (to_starts.count(s->name())) {
             s->Start();
             s->SetShutdownCritical();
+        } else if (s->IsShutdownCritical()) {
+            s->Start();  // start shutdown critical service if not started
         }
     });
 
diff --git a/init/service.cpp b/init/service.cpp
index f2e5d22..82c7bc1 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -499,6 +499,14 @@
     return true;
 }
 
+bool Service::ParseShutdown(const std::vector<std::string>& args, std::string* err) {
+    if (args[1] == "critical") {
+        flags_ |= SVC_SHUTDOWN_CRITICAL;
+        return true;
+    }
+    return false;
+}
+
 template <typename T>
 bool Service::AddDescriptor(const std::vector<std::string>& args, std::string* err) {
     int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1;
@@ -602,6 +610,7 @@
         {"namespace",   {1,     2,    &Service::ParseNamespace}},
         {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
         {"setenv",      {2,     2,    &Service::ParseSetenv}},
+        {"shutdown",    {1,     1,    &Service::ParseShutdown}},
         {"socket",      {3,     6,    &Service::ParseSocket}},
         {"file",        {2,     2,    &Service::ParseFile}},
         {"user",        {1,     1,    &Service::ParseUser}},
diff --git a/init/service.h b/init/service.h
index 3c7dc74..7eeab67 100644
--- a/init/service.h
+++ b/init/service.h
@@ -137,6 +137,7 @@
     bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
     bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
     bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
+    bool ParseShutdown(const std::vector<std::string>& args, std::string* err);
     bool ParseSocket(const std::vector<std::string>& args, std::string* err);
     bool ParseFile(const std::vector<std::string>& args, std::string* err);
     bool ParseUser(const std::vector<std::string>& args, std::string* err);
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ebbec35..a7216d4 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -687,6 +687,7 @@
     class core
     critical
     seclabel u:r:ueventd:s0
+    shutdown critical
 
 service healthd /sbin/healthd
     class core