libprocessgroup: Remove cgroup.rc file

The cgroup.rc file was introduced in 192aee782 ("libprocessgroup: Add
support for task profiles") back with the initial support for task
profiles. It was intended to optimize performance associated with cgroup
operations. However over time, supporting this file led to making
libprocessgroup code more complicated (such as the cgrouprc LLNDK
interface), and the file ended up getting mmaped into nearly every
process on Android even though only a handful of them actually use it.
Replacing this file with reading and parsing of cgroup information on
demand allows us to simplify and shrink libprocessgroup, and eliminates
thousands of unused mappings without negatively affecting boot time or
other performance metrics.

Bug: 349105928
Test: Verified with memcg v2 and MaxActivationDepth 1 on Cuttlefish, Raven, and Mokey
Change-Id: Ic3f01fdf7fda89a56ab80657e1cf4573156273e6
diff --git a/libprocessgroup/cgrouprc/Android.bp b/libprocessgroup/cgrouprc/Android.bp
index cb91247..38b2fa3 100644
--- a/libprocessgroup/cgrouprc/Android.bp
+++ b/libprocessgroup/cgrouprc/Android.bp
@@ -49,7 +49,8 @@
         "libbase",
     ],
     static_libs: [
-        "libcgrouprc_format",
+        "libjsoncpp",
+        "libprocessgroup_util",
     ],
     stubs: {
         symbol_file: "libcgrouprc.map.txt",
diff --git a/libprocessgroup/cgrouprc/a_cgroup_file.cpp b/libprocessgroup/cgrouprc/a_cgroup_file.cpp
index e26d841..33c8376 100644
--- a/libprocessgroup/cgrouprc/a_cgroup_file.cpp
+++ b/libprocessgroup/cgrouprc/a_cgroup_file.cpp
@@ -14,93 +14,51 @@
  * limitations under the License.
  */
 
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include <memory>
+#include <iterator>
 
 #include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
 #include <android/cgrouprc.h>
-#include <processgroup/processgroup.h>
+#include <processgroup/util.h>
 
 #include "cgrouprc_internal.h"
 
-using android::base::StringPrintf;
-using android::base::unique_fd;
-
-using android::cgrouprc::format::CgroupController;
-using android::cgrouprc::format::CgroupFile;
-
-static CgroupFile* LoadRcFile() {
-    struct stat sb;
-
-    unique_fd fd(TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_RDONLY | O_CLOEXEC)));
-    if (fd < 0) {
-        PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH;
+static CgroupDescriptorMap* LoadDescriptors() {
+    CgroupDescriptorMap* descriptors = new CgroupDescriptorMap;
+    if (!ReadDescriptors(descriptors)) {
+        LOG(ERROR) << "Failed to load cgroup description file";
         return nullptr;
     }
-
-    if (fstat(fd, &sb) < 0) {
-        PLOG(ERROR) << "fstat() failed for " << CGROUPS_RC_PATH;
-        return nullptr;
-    }
-
-    size_t file_size = sb.st_size;
-    if (file_size < sizeof(CgroupFile)) {
-        LOG(ERROR) << "Invalid file format " << CGROUPS_RC_PATH;
-        return nullptr;
-    }
-
-    CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
-    if (file_data == MAP_FAILED) {
-        PLOG(ERROR) << "Failed to mmap " << CGROUPS_RC_PATH;
-        return nullptr;
-    }
-
-    if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) {
-        LOG(ERROR) << CGROUPS_RC_PATH << " file version mismatch";
-        munmap(file_data, file_size);
-        return nullptr;
-    }
-
-    auto expected = sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController);
-    if (file_size != expected) {
-        LOG(ERROR) << CGROUPS_RC_PATH << " file has invalid size, expected " << expected
-                   << ", actual " << file_size;
-        munmap(file_data, file_size);
-        return nullptr;
-    }
-
-    return file_data;
+    return descriptors;
 }
 
-static CgroupFile* GetInstance() {
+static const CgroupDescriptorMap* GetInstance() {
     // Deliberately leak this object (not munmap) to avoid a race between destruction on
     // process exit and concurrent access from another thread.
-    static auto* file = LoadRcFile();
-    return file;
+    static const CgroupDescriptorMap* descriptors = LoadDescriptors();
+    return descriptors;
 }
 
 uint32_t ACgroupFile_getVersion() {
-    auto file = GetInstance();
-    if (file == nullptr) return 0;
-    return file->version_;
+    static constexpr uint32_t FILE_VERSION_1 = 1;
+    auto descriptors = GetInstance();
+    if (descriptors == nullptr) return 0;
+    // There has only ever been one version, and there will be no more since cgroup.rc is no more
+    return FILE_VERSION_1;
 }
 
 uint32_t ACgroupFile_getControllerCount() {
-    auto file = GetInstance();
-    if (file == nullptr) return 0;
-    return file->controller_count_;
+    auto descriptors = GetInstance();
+    if (descriptors == nullptr) return 0;
+    return descriptors->size();
 }
 
 const ACgroupController* ACgroupFile_getController(uint32_t index) {
-    auto file = GetInstance();
-    if (file == nullptr) return nullptr;
-    CHECK(index < file->controller_count_);
+    auto descriptors = GetInstance();
+    if (descriptors == nullptr) return nullptr;
+    CHECK(index < descriptors->size());
     // Although the object is not actually an ACgroupController object, all ACgroupController_*
     // functions implicitly convert ACgroupController* back to CgroupController* before invoking
     // member functions.
-    return static_cast<ACgroupController*>(&file->controllers_[index]);
+    const CgroupController* p = std::next(descriptors->begin(), index)->second.controller();
+    return static_cast<const ACgroupController*>(p);
 }
diff --git a/libprocessgroup/cgrouprc/cgrouprc_internal.h b/libprocessgroup/cgrouprc/cgrouprc_internal.h
index cd02f03..d517703 100644
--- a/libprocessgroup/cgrouprc/cgrouprc_internal.h
+++ b/libprocessgroup/cgrouprc/cgrouprc_internal.h
@@ -16,9 +16,6 @@
 
 #pragma once
 
-#include <android/cgrouprc.h>
+#include <processgroup/cgroup_controller.h>
 
-#include <processgroup/format/cgroup_controller.h>
-#include <processgroup/format/cgroup_file.h>
-
-struct ACgroupController : android::cgrouprc::format::CgroupController {};
+struct ACgroupController : CgroupController {};