Make per-application memcg hierarchy configurable via a property

Introduce ro.config.per_app_memcg Android property to enable/disable
per-application memcg hierarchy.
On low-ram devices (ro.config.low_ram=true) ro.config.per_app_memcg
defaults to true, otherwise it defaults to false.

Bug: 80201565
Test: set ro.config.per_app_memcg=true and verify /proc/<app_pid>/cgroup
membership (memory:/apps/uid_xxx/pid_xxx)
Test: set ro.config.per_app_memcg=false and verify /proc/<app_pid>/cgroup
membership (memory:/)
Change-Id: Iabd3ef6c9c16c774b9da959a7f43b5f66df120a3
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 6dfa697..58295fa 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -39,12 +39,18 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#ifdef __ANDROID__
+#include <android-base/properties.h>
+#endif
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <private/android_filesystem_config.h>
 
 #include <processgroup/processgroup.h>
 
+#ifdef __ANDROID__
+using android::base::GetBoolProperty;
+#endif
 using android::base::StartsWith;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
@@ -62,12 +68,25 @@
 static const std::string& GetCgroupRootPath() {
     static std::string cgroup_root_path;
     std::call_once(init_path_flag, [&]() {
-            // Check if mem cgroup is mounted, only then check for write-access to avoid
-            // SELinux denials
+#ifdef __ANDROID__
+        // low-ram devices use per-app memcg by default, unlike high-end ones
+        bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);
+        bool per_app_memcg =
+            GetBoolProperty("ro.config.per_app_memcg", low_ram_device);
+#else
+        // host does not support Android properties
+        bool per_app_memcg = false;
+#endif
+        if (per_app_memcg) {
+            // Check if mem cgroup is mounted, only then check for
+            // write-access to avoid SELinux denials
             cgroup_root_path =
-                (access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ? ACCT_CGROUP_PATH
-                                                                                 : MEM_CGROUP_PATH);
-            });
+                (access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ?
+                ACCT_CGROUP_PATH : MEM_CGROUP_PATH);
+        } else {
+            cgroup_root_path = ACCT_CGROUP_PATH;
+        }
+    });
     return cgroup_root_path;
 }