diff --git a/init/service_parser.cpp b/init/service_parser.cpp index 35bd41596..9e914ee7c 100644 --- a/init/service_parser.cpp +++ b/init/service_parser.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "lmkd_service.h" @@ -395,7 +396,15 @@ Result ServiceParser::ParseShutdown(std::vector&& args) { Result ServiceParser::ParseTaskProfiles(std::vector&& args) { args.erase(args.begin()); - service_->task_profiles_ = std::move(args); + if (service_->task_profiles_.empty()) { + service_->task_profiles_ = std::move(args); + } else { + // Some task profiles might have been added during writepid conversions + service_->task_profiles_.insert(service_->task_profiles_.end(), + std::make_move_iterator(args.begin()), + std::make_move_iterator(args.end())); + args.clear(); + } return {}; } @@ -521,8 +530,37 @@ Result ServiceParser::ParseUser(std::vector&& args) { return {}; } +// Convert legacy paths used to migrate processes between cgroups using writepid command. +// We can't get these paths from TaskProfiles because profile definitions are changing +// when we migrate to cgroups v2 while these hardcoded paths stay the same. +static std::optional ConvertTaskFileToProfile(const std::string& file) { + static const std::map map = { + {"/dev/stune/top-app/tasks", "MaxPerformance"}, + {"/dev/stune/foreground/tasks", "HighPerformance"}, + {"/dev/cpuset/camera-daemon/tasks", "CameraServiceCapacity"}, + {"/dev/cpuset/foreground/tasks", "ProcessCapacityHigh"}, + {"/dev/cpuset/system-background/tasks", "ServiceCapacityLow"}, + {"/dev/stune/nnapi-hal/tasks", "NNApiHALPerformance"}, + {"/dev/blkio/background/tasks", "LowIoPriority"}, + }; + auto iter = map.find(file); + return iter == map.end() ? std::nullopt : std::make_optional(iter->second); +} + Result ServiceParser::ParseWritepid(std::vector&& args) { args.erase(args.begin()); + // Convert any cgroup writes into appropriate task_profiles + for (auto iter = args.begin(); iter != args.end();) { + auto task_profile = ConvertTaskFileToProfile(*iter); + if (task_profile) { + LOG(WARNING) << "'writepid " << *iter << "' is converted into 'task_profiles " + << task_profile.value() << "' for service " << service_->name(); + service_->task_profiles_.push_back(task_profile.value()); + iter = args.erase(iter); + } else { + ++iter; + } + } service_->writepid_files_ = std::move(args); return {}; } diff --git a/init/service_utils.cpp b/init/service_utils.cpp index 263cb733f..eed5c65db 100644 --- a/init/service_utils.cpp +++ b/init/service_utils.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -305,6 +306,16 @@ Result WritePidToFiles(std::vector* files) { } else { LOG(ERROR) << "cpuset cgroup controller is not mounted!"; } + + // Issue a warning whenever writepid is being used with a cgroup. This can't be done during + // command parsing because cgroups might not be configured at the time or parsing. + for (const auto& file : *files) { + if (CgroupGetControllerFromPath(file, nullptr)) { + LOG(WARNING) << "writepid usage with cgroups path '" << file + << "' is obsolete, please use task_profiles!"; + } + } + std::string pid_str = std::to_string(getpid()); for (const auto& file : *files) { if (!WriteStringToFile(pid_str, file)) {