diff --git a/frameworks/concurrent_task_client/include/concurrent_task_service_ipc_interface_code.h b/frameworks/concurrent_task_client/include/concurrent_task_service_ipc_interface_code.h index 84c93517dd43a61ab7ef73b992cd10701d4eb058..37c5df7dae8983ebea31e492990103c916cdaaac 100644 --- a/frameworks/concurrent_task_client/include/concurrent_task_service_ipc_interface_code.h +++ b/frameworks/concurrent_task_client/include/concurrent_task_service_ipc_interface_code.h @@ -24,6 +24,7 @@ enum class ConcurrentTaskInterfaceCode { QUERY_INTERVAL = 2, QUERY_DEADLINE = 3, REQUEST_AUTH = 4, + SET_GROUP_PARAM = 5, }; } // namespace ConcurrentTask } // namespace OHOS diff --git a/frameworks/concurrent_task_client/include/concurrent_task_service_proxy.h b/frameworks/concurrent_task_client/include/concurrent_task_service_proxy.h index 1b27fda81e2ee9f6a1ed2e9a9ef440b81a0abe06..6dd863f6daf9718a784846c1e21dac39cf1ec134 100644 --- a/frameworks/concurrent_task_client/include/concurrent_task_service_proxy.h +++ b/frameworks/concurrent_task_client/include/concurrent_task_service_proxy.h @@ -32,6 +32,7 @@ public: void QueryInterval(int queryItem, IntervalReply& queryRs) override; void QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload) override; void RequestAuth(const Json::Value& payload) override; + void SetGroupParam(const Json::Value& payload) override; private: DISALLOW_COPY_AND_MOVE(ConcurrentTaskServiceProxy); diff --git a/frameworks/concurrent_task_client/include/iconcurrent_task_service.h b/frameworks/concurrent_task_client/include/iconcurrent_task_service.h index 7e70d7b2e49216bcbd6c3d4d8fa285a7a33a14aa..d038c10f20937856acf101756091dc61dd8bf376 100644 --- a/frameworks/concurrent_task_client/include/iconcurrent_task_service.h +++ b/frameworks/concurrent_task_client/include/iconcurrent_task_service.h @@ -31,6 +31,7 @@ public: virtual void QueryInterval(int queryItem, IntervalReply& queryRs) = 0; virtual void QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload) = 0; virtual void RequestAuth(const Json::Value& payload) = 0; + virtual void SetGroupParam(const Json::Value& payload) = 0; }; } // namespace ConcurrentTask } // namespace OHOS diff --git a/frameworks/concurrent_task_client/src/concurrent_task_client.cpp b/frameworks/concurrent_task_client/src/concurrent_task_client.cpp index 5c9f91be351b73ac02f0053c403a3217490b8a13..f14798dc926ebc8aa7c3ef2734fbddc21fc97a14 100644 --- a/frameworks/concurrent_task_client/src/concurrent_task_client.cpp +++ b/frameworks/concurrent_task_client/src/concurrent_task_client.cpp @@ -94,6 +94,19 @@ void ConcurrentTaskClient::QueryDeadline(int queryItem, DeadlineReply& ddlReply, return; } +void ConcurrentTaskClient::SetGroupParam(const std::unordered_map& mapPayload) +{ + if (TryConnect() != ERR_OK) { + return; + } + Json::Value payload; + for (auto it = mapPayload.begin(); it != mapPayload.end(); ++it) { + payload[it->first] = it->second; + } + clientService_->SetGroupParam(payload); + return; +} + ErrCode ConcurrentTaskClient::TryConnect() { std::lock_guard lock(mutex_); diff --git a/frameworks/concurrent_task_client/src/concurrent_task_service_proxy.cpp b/frameworks/concurrent_task_client/src/concurrent_task_service_proxy.cpp index 959c918b2ca73495b7866283750f0d2ebaaecec5..5ca1f356447a7f03a604953b473e4a4bb5ef4998 100644 --- a/frameworks/concurrent_task_client/src/concurrent_task_service_proxy.cpp +++ b/frameworks/concurrent_task_client/src/concurrent_task_service_proxy.cpp @@ -123,5 +123,28 @@ void ConcurrentTaskServiceProxy::RequestAuth(const Json::Value& payload) } CONCUR_LOGD("ConcurrentTaskServiceProxy::RequestAuth success."); } + +void ConcurrentTaskServiceProxy::SetGroupParam(const Json::Value& payload) +{ + int32_t error; + MessageParcel data; + MessageParcel reply; + MessageOption option = { MessageOption::TF_SYNC }; + if (!data.WriteInterfaceToken(ConcurrentTaskServiceProxy::GetDescriptor())) { + CONCUR_LOGE("Write interface token failed in SetGroupParam Proxy"); + return; + } + if (!data.WriteString(payload.toStyledString())) { + CONCUR_LOGE("Write info failed in SetGroupParam Proxy"); + return; + } + uint32_t code = static_cast(ConcurrentTaskInterfaceCode::SET_GROUP_PARAM); + error = Remote()->SendRequest(code, data, reply, option); + if (error != NO_ERROR) { + CONCUR_LOGE("Send request error: %{public}d", error); + return; + } + CONCUR_LOGD("ConcurrentTaskServiceProxy::SetGroupParam success."); +} } // namespace ConcurrentTask } // namespace OHOS diff --git a/interfaces/inner_api/concurrent_task_client.h b/interfaces/inner_api/concurrent_task_client.h index a00c3a537312d57642533f7b55fd631abac4e740..8637e0cb5ba5ef51583b2b819160ad3cbb75d8bb 100644 --- a/interfaces/inner_api/concurrent_task_client.h +++ b/interfaces/inner_api/concurrent_task_client.h @@ -81,6 +81,14 @@ public: * @param mapPayload Indicates the context info of the auth request data. */ void RequestAuth(const std::unordered_map& mapPayload); + + /** + * @brief Report cgroup param to the concurrent task service. + * + * @param mapPayload Indicates the context info of the cgroup param. + */ + void SetGroupParam(const std::unordered_map& mapPayload); + /** * @brief Stop remote object and reset ConcurrentTaskClient. */ diff --git a/services/include/concurrent_task_controller.h b/services/include/concurrent_task_controller.h index 9b5f5e87d7eed8239b7e11f91470036a29fa03e4..cc9e9778f4968514d90f0c5bc8291ddde8e5991c 100644 --- a/services/include/concurrent_task_controller.h +++ b/services/include/concurrent_task_controller.h @@ -30,6 +30,11 @@ namespace OHOS { namespace ConcurrentTask { class ForegroundAppRecord; +enum class CgroupParam { + CFS_PERIOD = 1, + CFS_QUOTA, +}; + class TaskController { public: static TaskController& GetInstance(); @@ -39,6 +44,7 @@ public: void QueryInterval(int queryItem, IntervalReply& queryRs); void QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload); void RequestAuth(const Json::Value& payload); + void SetGroupParam(const Json::Value& payload); void Init(); void Release(); int CreateNewRtgGrp(int prioType, int rtNum); diff --git a/services/include/concurrent_task_service.h b/services/include/concurrent_task_service.h index 28b792bad188c714ee2e48d1d4a4ccc894cef363..04370ee416be85241ffa338227205359aefbff99 100644 --- a/services/include/concurrent_task_service.h +++ b/services/include/concurrent_task_service.h @@ -30,6 +30,7 @@ public: void QueryInterval(int queryItem, IntervalReply& queryRs) override; void QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload) override; void RequestAuth(const Json::Value& payload) override; + void SetGroupParam(const Json::Value& payload) override; private: DISALLOW_COPY_AND_MOVE(ConcurrentTaskService); }; diff --git a/services/include/concurrent_task_service_stub.h b/services/include/concurrent_task_service_stub.h index 4da67574c9d5ea5ef84d2e4e5ba56c74862b7858..d3faef1b155399838d6452751aec5c48e9e75720 100644 --- a/services/include/concurrent_task_service_stub.h +++ b/services/include/concurrent_task_service_stub.h @@ -34,6 +34,7 @@ private: int32_t QueryIntervalInner(MessageParcel& data, MessageParcel& reply); int32_t QueryDeadlineInner(MessageParcel& data, MessageParcel& reply); int32_t RequestAuthInner(MessageParcel& data, MessageParcel& reply); + int32_t SetGroupParamInner(MessageParcel& data, MessageParcel& reply); Json::Value StringToJson(const std::string& str); void Init(); diff --git a/services/src/concurrent_task_controller.cpp b/services/src/concurrent_task_controller.cpp index 8eb42450edc2a5d05d61ea9f1a2475e8fe991fa8..403b92355f92920f4538736a9fa53cdd8c3523fe 100644 --- a/services/src/concurrent_task_controller.cpp +++ b/services/src/concurrent_task_controller.cpp @@ -774,6 +774,63 @@ int TaskController::CreateNewRtgGrp(int prioType, int rtNum) return ret; } +static bool SetParam(std::string &cgroup, std::string value, int option) +{ + std::string path = "/dev/cpu/" + cgroup; + if (option == static_cast(CgroupParam::CFS_PERIOD)) { + path += "/cpu.cfs_period_us"; + } else if (option == static_cast(CgroupParam::CFS_QUOTA)) { + path += "/cpu.cfs_quota_us"; + } + char realPath[PATH_MAX] = { 0 }; + if (path.size() > PATH_MAX || !realpath(path.c_str(), realPath)) { + CONCUR_LOGE("[SetGroupParam] Invalid path %{public}s", path.c_str()); + return false; + } + + int fd = open(realPath, O_WRONLY); + if (fd < 0) { + CONCUR_LOGE("[SetGroupParam] failed to open %{public}s, errno: %{public}d", realPath, errno); + return false; + } + + int64_t len = static_cast(value.length()); + if (write(fd, value.c_str(), value.length()) != len) { + CONCUR_LOGE("[SetGroupParam] failed to write %{public}s, errno: %{public}d", realPath, errno); + close(fd); + return false; + } + close(fd); + return true; +} + +void TaskController::SetGroupParam(const Json::Value& payload) +{ + pid_t uid = IPCSkeleton::GetInstance().GetCallingUid(); + if (GetProcessNameByToken() != RESOURCE_SCHEDULE_PROCESS_NAME) { + CONCUR_LOGE("Invalid uid %{public}d, only RSS can call SetGroupParam", uid); + return; + } + std::string cgroup = ""; + std::string periodUs = ""; + std::string quotaUs = ""; + try { + cgroup = payload["cgroup"].asString(); + periodUs = payload["cfs_period_us"].asString(); + quotaUs = payload["cfs_quota_us"].asString(); + } catch (...) { + CONCUR_LOGE("Unexpected type format"); + return; + } + if (cgroup == "root") { + cgroup = ""; + } + bool ret = SetParam(cgroup, periodUs, static_cast(CgroupParam::CFS_PERIOD)); + CONCUR_LOGI("[SetGroupParam] set cgroup [%{public}s] periodUs, ret = %{public}d", cgroup.c_str(), ret); + ret = SetParam(cgroup, quotaUs, static_cast(CgroupParam::CFS_QUOTA)); + CONCUR_LOGI("[SetGroupParam] set cgroup [%{public}s] quotaUs, ret = %{public}d", cgroup.c_str(), ret); +} + ForegroundAppRecord::ForegroundAppRecord(int pid, int uiTid, bool createGrp) { pid_ = pid; diff --git a/services/src/concurrent_task_service.cpp b/services/src/concurrent_task_service.cpp index 4302e894c7672d31caf19777e0cafae8761e79c7..72655e5212aa964af4ae9105b550366bf50b6ea6 100644 --- a/services/src/concurrent_task_service.cpp +++ b/services/src/concurrent_task_service.cpp @@ -38,5 +38,9 @@ void ConcurrentTaskService::RequestAuth(const Json::Value& payload) TaskController::GetInstance().RequestAuth(payload); } +void ConcurrentTaskService::SetGroupParam(const Json::Value& payload) +{ + TaskController::GetInstance().SetGroupParam(payload); +} } // namespace ConcurrentTask } // namespace OHOS diff --git a/services/src/concurrent_task_service_stub.cpp b/services/src/concurrent_task_service_stub.cpp index 1a1e13446bb03dcd3bb1b9f3578112716f4556b7..4bd219b3c7d999e1a5a8b05740ff39386c5a9db5 100644 --- a/services/src/concurrent_task_service_stub.cpp +++ b/services/src/concurrent_task_service_stub.cpp @@ -121,6 +121,24 @@ int32_t ConcurrentTaskServiceStub::RequestAuthInner(MessageParcel& data, [[maybe return ERR_OK; } +int32_t ConcurrentTaskServiceStub::SetGroupParamInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply) +{ + if (!IsValidToken(data)) { + return ERR_CONCURRENT_TASK_PARCEL_ERROR; + } + + std::string payload; + if (!data.ReadString(payload)) { + CONCUR_LOGE("Read info failed in SetGroupParam Stub"); + return IPC_STUB_ERR; + } + if (payload.empty()) { + return ERR_OK; + } + SetGroupParam(StringToJson(payload)); + return ERR_OK; +} + int32_t ConcurrentTaskServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) { @@ -173,6 +191,8 @@ void ConcurrentTaskServiceStub::Init() [this](auto& data, auto& reply) {return QueryDeadlineInner(data, reply); } }, { static_cast(ConcurrentTaskInterfaceCode::REQUEST_AUTH), [this](auto& data, auto& reply) {return RequestAuthInner(data, reply); } }, + { static_cast(ConcurrentTaskInterfaceCode::SET_GROUP_PARAM), + [this](auto& data, auto& reply) {return SetGroupParamInner(data, reply); } }, }; } } // namespace ResourceSchedule diff --git a/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp b/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp index 8385204c338c0e7fe5557b46566d5037a0b5332b..ff018bb83efe1135268fb0dff3ec3a62c304f334 100644 --- a/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp +++ b/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp @@ -52,6 +52,8 @@ public: {} void RequestAuth(const Json::Value& payload) override {} + void SetGroupParam(const Json::Value& payload) override + {} }; namespace { diff --git a/test/unittest/phone/concurrent_task_controller_test.cpp b/test/unittest/phone/concurrent_task_controller_test.cpp index 416e9ce1ac61986d02efcd7ce54d093390a8740c..9cd1b59500af7abb790996941a22c1083cb3c71b 100644 --- a/test/unittest/phone/concurrent_task_controller_test.cpp +++ b/test/unittest/phone/concurrent_task_controller_test.cpp @@ -539,5 +539,22 @@ HWTEST_F(ConcurrentTaskControllerTest, ModifyGameState, TestSize.Level1) TaskController::GetInstance().ModifyGameState(payload); EXPECT_EQ(TaskController::GetInstance().curGamePid_, -1); } + +/** + * @tc.name: SetGroupParam + * @tc.desc: Test whether the SetGroupParam interface are normal. + * @tc.type: FUNC + */ +HWTEST_F(ConcurrentTaskControllerTest, SetGroupParam, TestSize.Level1) +{ + Json::Value payload; + payload["cgroup"] = "top-app"; + payload["cfs_period_us"] = "300000"; + payload["cfs_quota_us"] = "200000"; + TaskController::GetInstance().SetGroupParam(payload); + payload["cgroup"] = ""; + payload["cfs_quota_us"] = "-1"; + TaskController::GetInstance().SetGroupParam(payload); +} } }