libprocessgroup: Activate controllers in cgroup v2 hierarchy at intermediate levels

When creating uid/pid hierarchy, cgroup.subtree_control should be set at
every level of that hierarchy except for the leaf level.

Bug: 195149205
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: Iedc2e859715b31db62158c85016708f252db2b70
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 5ca0967..0734f25 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -43,6 +43,7 @@
 using android::base::GetBoolProperty;
 using android::base::StringPrintf;
 using android::base::unique_fd;
+using android::base::WriteStringToFile;
 
 static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
 static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
@@ -202,3 +203,21 @@
 
     return CgroupController(nullptr);
 }
+
+int CgroupMap::ActivateControllers(const std::string& path) const {
+    if (__builtin_available(android 30, *)) {
+        auto controller_count = ACgroupFile_getControllerCount();
+        for (uint32_t i = 0; i < controller_count; ++i) {
+            const ACgroupController* controller = ACgroupFile_getController(i);
+            if (ACgroupController_getFlags(controller) &
+                CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
+                std::string str = std::string("+") + ACgroupController_getName(controller);
+                if (!WriteStringToFile(str, path + "/cgroup.subtree_control")) {
+                    return -errno;
+                }
+            }
+        }
+        return 0;
+    }
+    return -ENOSYS;
+}