Add process priority to service definition.

This change allows to set prioirrity of the process to be set through
*.rc file.

Bug: 28866384
Change-Id: If0108ef05c8a151749c43d2d7de1187653255ce8
diff --git a/init/readme.txt b/init/readme.txt
index aa372eb..8130806 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -184,6 +184,9 @@
   Write the child's pid to the given files when it forks. Meant for
   cgroup/cpuset usage.
 
+priority <priority>
+  Scheduling priority of the service process. This value has to be in range
+  -20 to 19. Default priority is 0. Priority is set via setpriority().
 
 Triggers
 --------
diff --git a/init/service.cpp b/init/service.cpp
index 4175d05..4ea8936 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -17,7 +17,9 @@
 #include "service.h"
 
 #include <fcntl.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <termios.h>
@@ -29,6 +31,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/android_reboot.h>
 #include <cutils/sockets.h>
+#include <system/thread_defs.h>
 
 #include <processgroup/processgroup.h>
 
@@ -65,7 +68,7 @@
                  const std::vector<std::string>& args)
     : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
       time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""),
-      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) {
+      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -74,7 +77,8 @@
                  const std::string& seclabel,  const std::vector<std::string>& args)
     : name_(name), classname_(classname), flags_(flags), pid_(0), time_started_(0),
       time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), supp_gids_(supp_gids),
-      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) {
+      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
+      args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -197,6 +201,19 @@
     return true;
 }
 
+bool Service::HandlePriority(const std::vector<std::string>& args, std::string* err) {
+    priority_ = std::stoi(args[1]);
+
+    if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
+        priority_ = 0;
+        *err = StringPrintf("process priority value must be range %d - %d",
+                ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
+        return false;
+    }
+
+    return true;
+}
+
 bool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) {
     ioprio_pri_ = std::stoul(args[2], 0, 8);
 
@@ -290,6 +307,7 @@
         {"disabled",    {0,     0,    &Service::HandleDisabled}},
         {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
         {"ioprio",      {2,     2,    &Service::HandleIoprio}},
+        {"priority",    {1,     1,    &Service::HandlePriority}},
         {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
         {"oneshot",     {0,     0,    &Service::HandleOneshot}},
         {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
@@ -470,6 +488,12 @@
                 _exit(127);
             }
         }
+        if (priority_ != 0) {
+            if (setpriority(PRIO_PROCESS, 0, priority_) != 0) {
+                ERROR("setpriority failed: %s\n", strerror(errno));
+                _exit(127);
+            }
+        }
 
         std::vector<char*> strs;
         for (const auto& s : args_) {
diff --git a/init/service.h b/init/service.h
index d6ce664..dc14f9a 100644
--- a/init/service.h
+++ b/init/service.h
@@ -93,6 +93,7 @@
     pid_t pid() const { return pid_; }
     uid_t uid() const { return uid_; }
     gid_t gid() const { return gid_; }
+    int priority() const { return priority_; }
     const std::vector<gid_t>& supp_gids() const { return supp_gids_; }
     const std::string& seclabel() const { return seclabel_; }
     const std::vector<int>& keycodes() const { return keycodes_; }
@@ -116,6 +117,7 @@
     bool HandleCritical(const std::vector<std::string>& args, std::string* err);
     bool HandleDisabled(const std::vector<std::string>& args, std::string* err);
     bool HandleGroup(const std::vector<std::string>& args, std::string* err);
+    bool HandlePriority(const std::vector<std::string>& args, std::string* err);
     bool HandleIoprio(const std::vector<std::string>& args, std::string* err);
     bool HandleKeycodes(const std::vector<std::string>& args, std::string* err);
     bool HandleOneshot(const std::vector<std::string>& args, std::string* err);
@@ -155,6 +157,7 @@
 
     IoSchedClass ioprio_class_;
     int ioprio_pri_;
+    int priority_;
 
     std::vector<std::string> args_;
 };