Merge "Add vendor cgroups and task_profiles support" am: 3af39f36cc am: 6f8eee612c
am: c6ee857075

Change-Id: I0dd92817ee12509e3e26d005bf28229292cc3246
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index d094811..26d0754 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -45,6 +45,7 @@
 using android::base::unique_fd;
 
 static constexpr const char* CGROUPS_DESC_FILE = "/etc/cgroups.json";
+static constexpr const char* CGROUPS_DESC_VENDOR_FILE = "/vendor/etc/cgroups.json";
 
 static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
 static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
@@ -110,12 +111,13 @@
     return true;
 }
 
-static bool ReadDescriptors(std::map<std::string, CgroupDescriptor>* descriptors) {
+static bool ReadDescriptorsFromFile(const std::string& file_name,
+                                    std::map<std::string, CgroupDescriptor>* descriptors) {
     std::vector<CgroupDescriptor> result;
     std::string json_doc;
 
-    if (!android::base::ReadFileToString(CGROUPS_DESC_FILE, &json_doc)) {
-        LOG(ERROR) << "Failed to read task profiles from " << CGROUPS_DESC_FILE;
+    if (!android::base::ReadFileToString(file_name, &json_doc)) {
+        LOG(ERROR) << "Failed to read task profiles from " << file_name;
         return false;
     }
 
@@ -130,21 +132,46 @@
         const Json::Value& cgroups = root["Cgroups"];
         for (Json::Value::ArrayIndex i = 0; i < cgroups.size(); ++i) {
             std::string name = cgroups[i]["Controller"].asString();
-            descriptors->emplace(std::make_pair(
-                    name,
-                    CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
+            auto iter = descriptors->find(name);
+            if (iter == descriptors->end()) {
+                descriptors->emplace(name, CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
                                      std::strtoul(cgroups[i]["Mode"].asString().c_str(), 0, 8),
-                                     cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString())));
+                                     cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString()));
+            } else {
+                iter->second = CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
+                                     std::strtoul(cgroups[i]["Mode"].asString().c_str(), 0, 8),
+                                     cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString());
+            }
         }
     }
 
     if (root.isMember("Cgroups2")) {
         const Json::Value& cgroups2 = root["Cgroups2"];
-        descriptors->emplace(std::make_pair(
-                CGROUPV2_CONTROLLER_NAME,
-                CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
+        auto iter = descriptors->find(CGROUPV2_CONTROLLER_NAME);
+        if (iter == descriptors->end()) {
+            descriptors->emplace(CGROUPV2_CONTROLLER_NAME, CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
                                  std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
-                                 cgroups2["UID"].asString(), cgroups2["GID"].asString())));
+                                 cgroups2["UID"].asString(), cgroups2["GID"].asString()));
+        } else {
+            iter->second = CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
+                                 std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
+                                 cgroups2["UID"].asString(), cgroups2["GID"].asString());
+        }
+    }
+
+    return true;
+}
+
+static bool ReadDescriptors(std::map<std::string, CgroupDescriptor>* descriptors) {
+    // load system cgroup descriptors
+    if (!ReadDescriptorsFromFile(CGROUPS_DESC_FILE, descriptors)) {
+        return false;
+    }
+
+    // load vendor cgroup descriptors if the file exists
+    if (!access(CGROUPS_DESC_VENDOR_FILE, F_OK) &&
+        !ReadDescriptorsFromFile(CGROUPS_DESC_VENDOR_FILE, descriptors)) {
+        return false;
     }
 
     return true;
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 8ec29d3..0bc19df 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -42,6 +42,7 @@
 using android::base::WriteStringToFile;
 
 #define TASK_PROFILE_DB_FILE "/etc/task_profiles.json"
+#define TASK_PROFILE_DB_VENDOR_FILE "/vendor/etc/task_profiles.json"
 
 bool ProfileAttribute::GetPathForTask(int tid, std::string* path) const {
     std::string subgroup;
@@ -288,16 +289,24 @@
 }
 
 TaskProfiles::TaskProfiles() {
-    if (!Load(CgroupMap::GetInstance())) {
-        LOG(ERROR) << "TaskProfiles::Load for [" << getpid() << "] failed";
+    // load system task profiles
+    if (!Load(CgroupMap::GetInstance(), TASK_PROFILE_DB_FILE)) {
+        LOG(ERROR) << "Loading " << TASK_PROFILE_DB_FILE << " for [" << getpid() << "] failed";
+    }
+
+    // load vendor task profiles if the file exists
+    if (!access(TASK_PROFILE_DB_VENDOR_FILE, F_OK) &&
+        !Load(CgroupMap::GetInstance(), TASK_PROFILE_DB_VENDOR_FILE)) {
+        LOG(ERROR) << "Loading " << TASK_PROFILE_DB_VENDOR_FILE << " for [" << getpid()
+                   << "] failed";
     }
 }
 
-bool TaskProfiles::Load(const CgroupMap& cg_map) {
+bool TaskProfiles::Load(const CgroupMap& cg_map, const std::string& file_name) {
     std::string json_doc;
 
-    if (!android::base::ReadFileToString(TASK_PROFILE_DB_FILE, &json_doc)) {
-        LOG(ERROR) << "Failed to read task profiles from " << TASK_PROFILE_DB_FILE;
+    if (!android::base::ReadFileToString(file_name, &json_doc)) {
+        LOG(ERROR) << "Failed to read task profiles from " << file_name;
         return false;
     }
 
@@ -311,15 +320,15 @@
     Json::Value attr = root["Attributes"];
     for (Json::Value::ArrayIndex i = 0; i < attr.size(); ++i) {
         std::string name = attr[i]["Name"].asString();
-        std::string ctrlName = attr[i]["Controller"].asString();
-        std::string file_name = attr[i]["File"].asString();
+        std::string controller_name = attr[i]["Controller"].asString();
+        std::string file_attr = attr[i]["File"].asString();
 
         if (attributes_.find(name) == attributes_.end()) {
-            const CgroupController* controller = cg_map.FindController(ctrlName);
+            const CgroupController* controller = cg_map.FindController(controller_name);
             if (controller) {
-                attributes_[name] = std::make_unique<ProfileAttribute>(controller, file_name);
+                attributes_[name] = std::make_unique<ProfileAttribute>(controller, file_attr);
             } else {
-                LOG(WARNING) << "Controller " << ctrlName << " is not found";
+                LOG(WARNING) << "Controller " << controller_name << " is not found";
             }
         } else {
             LOG(WARNING) << "Attribute " << name << " is already defined";
@@ -341,14 +350,14 @@
             std::string actionName = actionVal["Name"].asString();
             Json::Value paramsVal = actionVal["Params"];
             if (actionName == "JoinCgroup") {
-                std::string ctrlName = paramsVal["Controller"].asString();
+                std::string controller_name = paramsVal["Controller"].asString();
                 std::string path = paramsVal["Path"].asString();
 
-                const CgroupController* controller = cg_map.FindController(ctrlName);
+                const CgroupController* controller = cg_map.FindController(controller_name);
                 if (controller) {
                     profile->Add(std::make_unique<SetCgroupAction>(controller, path));
                 } else {
-                    LOG(WARNING) << "JoinCgroup: controller " << ctrlName << " is not found";
+                    LOG(WARNING) << "JoinCgroup: controller " << controller_name << " is not found";
                 }
             } else if (actionName == "SetTimerSlack") {
                 std::string slackValue = paramsVal["Slack"].asString();
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index b2e39f9..9ee81c1 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -152,5 +152,5 @@
 
     TaskProfiles();
 
-    bool Load(const CgroupMap& cg_map);
+    bool Load(const CgroupMap& cg_map, const std::string& file_name);
 };