libprocessgroup: Add SetSchedulerPolicy Action

Add a new profile action that allows users to set a scheduler policy and
priority for a thread when a profile with the action is applied. This
can be used with the POSIX policies specified in the sched_setscheduler
man page. A priority value is required for real-time policies. A nice
value may optionally be provided for normal policies.

If a normal policy is used and a nice value is provided, it will be
applied with setpriority() after the scheduler policy is applied. The
range of nice values that can be used in the task profiles JSON in this
case is [-20, 19].

If a real-time policy is used, the range of priorities that can be used
in the task profiles JSON is [1, 99] which will be mapped onto
[sched_get_priority_min(), sched_get_priority_max()] at runtime for the
the provided policy.

Here are some examples:

Use lowest-priority with FIFO policy:
"Actions": [
  {
    "Name": "SetSchedulerPolicy",
    "Params":
    {
      "Policy": "SCHED_FIFO",
      "Priority": 1
    }
  }
]

Use highest-priority (lowest nice) with standard NORMAL scheduler:
"Actions": [
  {
    "Name": "SetSchedulerPolicy",
    "Params":
    {
      "Policy": "SCHED_OTHER",
      "Nice": -20
    }
  }
]

Bug: 368072932
BYPASS_INCLUSIVE_LANGUAGE_REASON=false positive
Change-Id: I502ceb3913016e9f4e6b6322cc0eee905c9a5c9a
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index e52ce38..ea948b5 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -21,6 +21,7 @@
 #include <map>
 #include <memory>
 #include <mutex>
+#include <optional>
 #include <span>
 #include <string>
 #include <string_view>
@@ -187,6 +188,25 @@
     CacheUseResult UseCachedFd(ResourceCacheType cache_type, const std::string& value) const;
 };
 
+// Set scheduler policy action
+class SetSchedulerPolicyAction : public ProfileAction {
+  public:
+    SetSchedulerPolicyAction(int policy)
+        : policy_(policy) {}
+    SetSchedulerPolicyAction(int policy, int priority_or_nice)
+        : policy_(policy), priority_or_nice_(priority_or_nice) {}
+
+    const char* Name() const override { return "SetSchedulerPolicy"; }
+    bool ExecuteForTask(pid_t tid) const override;
+
+    static bool isNormalPolicy(int policy);
+    static bool toPriority(int policy, int virtual_priority, int& priority_out);
+
+  private:
+    int policy_;
+    std::optional<int> priority_or_nice_;
+};
+
 class TaskProfile {
   public:
     TaskProfile(const std::string& name) : name_(name), res_cached_(false) {}