Merge "init: add support of multiple class names" am: 3c1568aa13
am: fd450bb95a

Change-Id: Ia859d1817eb80a34f339fe99894bffa4163440ce
diff --git a/init/README.md b/init/README.md
index 709c667..65d6543 100644
--- a/init/README.md
+++ b/init/README.md
@@ -192,11 +192,12 @@
 `oneshot`
 > Do not restart the service when it exits.
 
-`class <name>`
-> Specify a class name for the service.  All services in a
+`class <name> [ <name>\* ]`
+> Specify class names for the service.  All services in a
   named class may be started or stopped together.  A service
   is in the class "default" if one is not specified via the
-  class option.
+  class option. Additional classnames beyond the (required) first
+  one are used to group services.
 
 `onrestart`
 > Execute a Command (see below) when service restarts.
diff --git a/init/service.cpp b/init/service.cpp
index c8d1cb1..c6ef838 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -149,27 +149,44 @@
     : name(name), value(value) {
 }
 
-Service::Service(const std::string& name, const std::string& classname,
-                 const std::vector<std::string>& args)
-    : name_(name), classname_(classname), flags_(0), pid_(0),
-      crash_count_(0), uid_(0), gid_(0), namespace_flags_(0),
-      seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
-      priority_(0), oom_score_adjust_(-1000), args_(args) {
+Service::Service(const std::string& name, const std::vector<std::string>& args)
+    : name_(name),
+      classnames_({"default"}),
+      flags_(0),
+      pid_(0),
+      crash_count_(0),
+      uid_(0),
+      gid_(0),
+      namespace_flags_(0),
+      seclabel_(""),
+      ioprio_class_(IoSchedClass_NONE),
+      ioprio_pri_(0),
+      priority_(0),
+      oom_score_adjust_(-1000),
+      args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
-Service::Service(const std::string& name, const std::string& classname,
-                 unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids,
-                 const CapSet& capabilities, unsigned namespace_flags,
-                 const std::string& seclabel,
+Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
+                 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
+                 unsigned namespace_flags, const std::string& seclabel,
                  const std::vector<std::string>& args)
-    : name_(name), classname_(classname), flags_(flags), pid_(0),
-      crash_count_(0), uid_(uid), gid_(gid),
-      supp_gids_(supp_gids), capabilities_(capabilities),
-      namespace_flags_(namespace_flags), seclabel_(seclabel),
-      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
-      oom_score_adjust_(-1000), args_(args) {
+    : name_(name),
+      classnames_({"default"}),
+      flags_(flags),
+      pid_(0),
+      crash_count_(0),
+      uid_(uid),
+      gid_(gid),
+      supp_gids_(supp_gids),
+      capabilities_(capabilities),
+      namespace_flags_(namespace_flags),
+      seclabel_(seclabel),
+      ioprio_class_(IoSchedClass_NONE),
+      ioprio_pri_(0),
+      priority_(0),
+      oom_score_adjust_(-1000),
+      args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -297,7 +314,7 @@
 
 void Service::DumpState() const {
     LOG(INFO) << "service " << name_;
-    LOG(INFO) << "  class '" << classname_ << "'";
+    LOG(INFO) << "  class '" << android::base::Join(classnames_, " ") << "'";
     LOG(INFO) << "  exec "<< android::base::Join(args_, " ");
     std::for_each(descriptors_.begin(), descriptors_.end(),
                   [] (const auto& info) { LOG(INFO) << *info; });
@@ -334,7 +351,7 @@
 }
 
 bool Service::ParseClass(const std::vector<std::string>& args, std::string* err) {
-    classname_ = args[1];
+    classnames_ = std::set<std::string>(args.begin() + 1, args.end());
     return true;
 }
 
@@ -516,10 +533,11 @@
 
 Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
+    // clang-format off
     static const Map option_parsers = {
         {"capabilities",
                         {1,     kMax, &Service::ParseCapabilities}},
-        {"class",       {1,     1,    &Service::ParseClass}},
+        {"class",       {1,     kMax, &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
         {"disabled",    {0,     0,    &Service::ParseDisabled}},
@@ -539,6 +557,7 @@
         {"user",        {1,     1,    &Service::ParseUser}},
         {"writepid",    {1,     kMax, &Service::ParseWritepid}},
     };
+    // clang-format on
     return option_parsers;
 }
 
@@ -889,8 +908,8 @@
         }
     }
 
-    auto svc_p = std::make_unique<Service>(name, "default", flags, uid, gid, supp_gids,
-                                           no_capabilities, namespace_flags, seclabel, str_args);
+    auto svc_p = std::make_unique<Service>(name, flags, uid, gid, supp_gids, no_capabilities,
+                                           namespace_flags, seclabel, str_args);
     Service* svc = svc_p.get();
     services_.emplace_back(std::move(svc_p));
 
@@ -940,7 +959,7 @@
 void ServiceManager::ForEachServiceInClass(const std::string& classname,
                                            void (*func)(Service* svc)) const {
     for (const auto& s : services_) {
-        if (classname == s->classname()) {
+        if (s->classnames().find(classname) != s->classnames().end()) {
             func(s.get());
         }
     }
@@ -1034,7 +1053,7 @@
     }
 
     std::vector<std::string> str_args(args.begin() + 2, args.end());
-    service_ = std::make_unique<Service>(name, "default", str_args);
+    service_ = std::make_unique<Service>(name, str_args);
     return true;
 }
 
diff --git a/init/service.h b/init/service.h
index 08388e2..9a9046b 100644
--- a/init/service.h
+++ b/init/service.h
@@ -22,6 +22,7 @@
 #include <cutils/iosched_policy.h>
 
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -61,12 +62,10 @@
 };
 
 class Service {
-public:
-    Service(const std::string& name, const std::string& classname,
-            const std::vector<std::string>& args);
+  public:
+    Service(const std::string& name, const std::vector<std::string>& args);
 
-    Service(const std::string& name, const std::string& classname,
-            unsigned flags, uid_t uid, gid_t gid,
+    Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
             const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
             unsigned namespace_flags, const std::string& seclabel,
             const std::vector<std::string>& args);
@@ -84,10 +83,10 @@
     bool Reap();
     void DumpState() const;
     void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
-    bool IsShutdownCritical() { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
+    bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
 
     const std::string& name() const { return name_; }
-    const std::string& classname() const { return classname_; }
+    const std::set<std::string>& classnames() const { return classnames_; }
     unsigned flags() const { return flags_; }
     pid_t pid() const { return pid_; }
     uid_t uid() const { return uid_; }
@@ -100,7 +99,7 @@
     void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; }
     const std::vector<std::string>& args() const { return args_; }
 
-private:
+  private:
     using OptionParser = bool (Service::*) (const std::vector<std::string>& args,
                                             std::string* err);
     class OptionParserMap;
@@ -136,7 +135,7 @@
     bool AddDescriptor(const std::vector<std::string>& args, std::string* err);
 
     std::string name_;
-    std::string classname_;
+    std::set<std::string> classnames_;
     std::string console_;
 
     unsigned flags_;