Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6281db5 authored by T.J. Mercier's avatar T.J. Mercier
Browse files

libprocessgroup: Add support for SetUserProfiles

Provide SetUserProfiles API to apply profiles at UID level.

This enables applying the freezer profile to an entire UID instead of
just individual process cgroups.

Test: bash arg: -p
Test: bash arg: com.haok.nirvana
Test: bash arg: 1
Test: args: [-p, com.haok.nirvana, 1]
Test: arg: "-p"
Test: arg: "com.haok.nirvana"
Test: arg: "1"
Test: data="com.haok.nirvana"
Test: Events injected: 1
Test: ## Network stats: elapsed time=14ms (0ms mobile, 0ms wifi, 14ms not connected)
Test: raven:/ $ ps -eo pid,uid,ppid,name|grep 10266
Test: 2499 10266   823 com.haok.nirvana
Test: 2577 10266   823 com.haok.nirvana:resident
Test: 2584 10266   823 android.media
Test: 2669 10266     1 app_d
Test: 2672 10266     1 app_d
Test: raven:/ $ am force-stop com.haok.nirvana
Test: raven:/ $ ps -eo pid,uid,ppid,name|grep 10266
Test: 1|raven:/ $
Ignore-AOSP-First: Topic with AMS changes which is developed on git_master
Bug: 236708592
Change-Id: I45e34244f9943c217757cf346c9410672a1ce365
parent 2dcd08af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::s

bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache = false);
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles);

#ifndef __ANDROID_VNDK__

+4 −0
Original line number Diff line number Diff line
@@ -174,6 +174,10 @@ extern "C" bool android_set_process_profiles(uid_t uid, pid_t pid, size_t num_pr
    return SetProcessProfiles(uid, pid, profiles_);
}

bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles) {
    return TaskProfiles::GetInstance().SetUserProfiles(uid, profiles, false);
}

static std::string ConvertUidToPath(const char* cgroup, uid_t uid) {
    return StringPrintf("%s/uid_%d", cgroup, uid);
}
+66 −0
Original line number Diff line number Diff line
@@ -139,6 +139,19 @@ bool ProfileAttribute::GetPathForTask(int tid, std::string* path) const {
    return true;
}

bool ProfileAttribute::GetPathForUID(uid_t uid, std::string* path) const
{
    if (path == nullptr) {
        return true;
    }

    const std::string& file_name =
            controller()->version() == 2 && !file_v2_name_.empty() ? file_v2_name_ : file_name_;
    *path = StringPrintf("%s/uid_%d/%s", controller()->path(), uid, file_name.c_str());
    return true;
}


bool SetClampsAction::ExecuteForProcess(uid_t, pid_t) const {
    // TODO: add support when kernel supports util_clamp
    LOG(WARNING) << "SetClampsAction::ExecuteForProcess is not supported";
@@ -225,6 +238,31 @@ bool SetAttributeAction::ExecuteForTask(int tid) const {
    return true;
}

bool SetAttributeAction::ExecuteForUID(uid_t uid) const
{
    std::string path;

    if (!attribute_->GetPathForUID(uid, &path)) {
        LOG(ERROR) << "Failed to find cgroup for uid " << uid;
        return false;
    }

    if (!WriteStringToFile(value_, path)) {
        if (access(path.c_str(), F_OK) < 0) {
            if (optional_) {
                return true;
            } else {
                LOG(ERROR) << "No such cgroup attribute: " << path;
                return false;
            }
        }
        PLOG(ERROR) << "Failed to write '" << value_ << "' to " << path;
        return false;
    }
    return true;
}


SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
    : controller_(c), path_(p) {
    FdCacheHelper::Init(controller_.GetTasksFilePath(path_), fd_[ProfileAction::RCT_TASK]);
@@ -552,6 +590,16 @@ bool TaskProfile::ExecuteForTask(int tid) const {
    return true;
}

bool TaskProfile::ExecuteForUID(uid_t uid) const {
    for (const auto& element : elements_) {
        if (!element->ExecuteForUID(uid)) {
            LOG(VERBOSE) << "Applying profile action " << element->Name() << " failed";
            return false;
        }
    }
    return true;
}

void TaskProfile::EnableResourceCaching(ProfileAction::ResourceCacheType cache_type) {
    if (res_cached_) {
        return;
@@ -804,6 +852,24 @@ const IProfileAttribute* TaskProfiles::GetAttribute(const std::string& name) con
    return nullptr;
}

bool TaskProfiles::SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles,
                                   bool use_fd_cache) {
    for (const auto& name : profiles) {
        TaskProfile* profile = GetProfile(name);
        if (profile != nullptr) {
            if (use_fd_cache) {
                profile->EnableResourceCaching(ProfileAction::RCT_PROCESS);
            }
            if (!profile->ExecuteForUID(uid)) {
                PLOG(WARNING) << "Failed to apply " << name << " process profile";
            }
        } else {
            PLOG(WARNING) << "Failed to find " << name << "process profile";
        }
    }
    return true;
}

bool TaskProfiles::SetProcessProfiles(uid_t uid, pid_t pid,
                                      const std::vector<std::string>& profiles, bool use_fd_cache) {
    bool success = true;
+6 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ class IProfileAttribute {
    virtual const CgroupController* controller() const = 0;
    virtual const std::string& file_name() const = 0;
    virtual bool GetPathForTask(int tid, std::string* path) const = 0;
    virtual bool GetPathForUID(uid_t uid, std::string* path) const = 0;
};

class ProfileAttribute : public IProfileAttribute {
@@ -50,6 +51,7 @@ class ProfileAttribute : public IProfileAttribute {
    void Reset(const CgroupController& controller, const std::string& file_name) override;

    bool GetPathForTask(int tid, std::string* path) const override;
    bool GetPathForUID(uid_t uid, std::string* path) const override;

  private:
    CgroupController controller_;
@@ -69,6 +71,7 @@ class ProfileAction {
    // Default implementations will fail
    virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; };
    virtual bool ExecuteForTask(int) const { return false; };
    virtual bool ExecuteForUID(uid_t) const { return false; };

    virtual void EnableResourceCaching(ResourceCacheType) {}
    virtual void DropResourceCaching(ResourceCacheType) {}
@@ -113,6 +116,7 @@ class SetAttributeAction : public ProfileAction {
    const char* Name() const override { return "SetAttribute"; }
    bool ExecuteForProcess(uid_t uid, pid_t pid) const override;
    bool ExecuteForTask(int tid) const override;
    bool ExecuteForUID(uid_t uid) const override;

  private:
    const IProfileAttribute* attribute_;
@@ -176,6 +180,7 @@ class TaskProfile {

    bool ExecuteForProcess(uid_t uid, pid_t pid) const;
    bool ExecuteForTask(int tid) const;
    bool ExecuteForUID(uid_t uid) const;
    void EnableResourceCaching(ProfileAction::ResourceCacheType cache_type);
    void DropResourceCaching(ProfileAction::ResourceCacheType cache_type);

@@ -212,6 +217,7 @@ class TaskProfiles {
    bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
                            bool use_fd_cache);
    bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache);
    bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles, bool use_fd_cache);

  private:
    std::map<std::string, std::shared_ptr<TaskProfile>> profiles_;
+4 −0
Original line number Diff line number Diff line
@@ -121,6 +121,10 @@ class ProfileAttributeMock : public IProfileAttribute {
        return true;
    };

    bool GetPathForUID(uid_t, std::string *) const override {
        return false;
    }

  private:
    const std::string file_name_;
};