feat: add killProcessesInBatch

Signed-off-by: yangxuguang-huawei <yangxuguang3@huawei.com>
This commit is contained in:
yangxuguang-huawei 2024-11-17 16:28:06 +08:00
parent 360bb87f4f
commit 158a439bb5
11 changed files with 193 additions and 0 deletions

View File

@ -125,6 +125,11 @@ public:
GET_CB_INFO_AND_CALL(env, info, JsAppManager, OnKillProcessWithAccount);
}
static napi_value KillProcessesInBatch(napi_env env, napi_callback_info info)
{
GET_CB_INFO_AND_CALL(env, info, JsAppManager, OnKillProcessesInBatch);
}
static napi_value KillProcessesByBundleName(napi_env env, napi_callback_info info)
{
GET_CB_INFO_AND_CALL(env, info, JsAppManager, OnKillProcessesByBundleName);
@ -1124,6 +1129,45 @@ private:
return result;
}
napi_value OnKillProcessesInBatch(napi_env env, size_t argc, napi_value* argv)
{
TAG_LOGD(AAFwkTag::APPMGR, "called");
if (argc < ARGC_ONE) {
TAG_LOGE(AAFwkTag::APPMGR, "Params mismatch");
ThrowTooFewParametersError(env);
return CreateJsUndefined(env);
}
std::vector<int32_t> pids;
if (!AppExecFwk::UnwrapArrayInt32FromJS(env, argv[INDEX_ZERO], pids)) {
TAG_LOGE(AAFwkTag::APPMGR, "Parse pids failed");
ThrowInvalidParamError(env, "Parse param pids failed, must be array of numbers.");
return CreateJsUndefined(env);
}
auto innerErrorCode = std::make_shared<int32_t>(ERR_OK);
NapiAsyncTask::ExecuteCallback execute = [pids, appManager = appManager_, innerErrorCode]() {
if (appManager == nullptr || appManager->GetAmsMgr() == nullptr) {
TAG_LOGW(AAFwkTag::APPMGR, "null appManager or amsMgr");
*innerErrorCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
return;
}
*innerErrorCode = appManager->GetAmsMgr()->KillProcessesInBatch(pids);
};
NapiAsyncTask::CompleteCallback complete =
[innerErrorCode](napi_env env, NapiAsyncTask &task, int32_t status) {
if (*innerErrorCode == ERR_OK) {
task.ResolveWithNoError(env, CreateJsUndefined(env));
return;
}
TAG_LOGE(AAFwkTag::APPMGR, "KillProcessesInBatch failed:%{public}d", *innerErrorCode);
task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrorCode));
};
napi_value result = nullptr;
NapiAsyncTask::ScheduleHighQos("JSAppManager::OnKillProcessesInBatch",
env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
return result;
}
napi_value OnGetAppMemorySize(napi_env env, size_t argc, napi_value* argv)
{
napi_value lastParam = (argc > ARGC_ZERO) ? argv[INDEX_ZERO] : nullptr;
@ -1680,6 +1724,7 @@ napi_value JsAppManagerInit(napi_env env, napi_value exportObj)
JsAppManager::GetRunningProcessInformation);
BindNativeFunction(env, exportObj, "isRunningInStabilityTest", moduleName, JsAppManager::IsRunningInStabilityTest);
BindNativeFunction(env, exportObj, "killProcessWithAccount", moduleName, JsAppManager::KillProcessWithAccount);
BindNativeFunction(env, exportObj, "killProcessesInBatch", moduleName, JsAppManager::KillProcessesInBatch);
BindNativeFunction(env, exportObj, "killProcessesByBundleName", moduleName,
JsAppManager::KillProcessesByBundleName);
BindNativeFunction(env, exportObj, "clearUpApplicationData", moduleName, JsAppManager::ClearUpApplicationData);

View File

@ -129,6 +129,15 @@ public:
virtual int KillProcessWithAccount(const std::string &bundleName, const int accountId,
const bool clearPageStack = false, int32_t appIndex = 0) = 0;
/**
* KillProcessesInBatch, kill processes in batch, call KillProcessesInBatch() through proxy object;
* the killed bundle won't be started by the watcher.
*
* @param pids, the pid list of processes are going to be killed.
* @return ERR_OK, return back success, others fail.
*/
virtual int32_t KillProcessesInBatch(const std::vector<int32_t> &pids) = 0;
/**
* UpdateApplicationInfoInstalled, call UpdateApplicationInfoInstalled() through proxy object,
* update the application info after new module installed.
@ -511,6 +520,7 @@ public:
ENABLE_START_PROCESS_FLAG_BY_USER_ID,
SET_APP_EXCEPTION_CALLBACK,
SET_KEEP_ALIVE_DKV,
KILL_PROCESSES_IN_BATCH,
// Add enumeration values above
END
};

View File

@ -119,6 +119,15 @@ public:
virtual int32_t KillProcessWithAccount(const std::string &bundleName, const int accountId,
const bool clearPageStack = false, int32_t appIndex = 0) override;
/**
* KillProcessesInBatch, kill processes in batch, call KillProcessesInBatch() through proxy object;
* the killed bundle won't be started by the watcher.
*
* @param pids, the pid list of processes are going to be killed.
* @return ERR_OK, return back success, others fail.
*/
virtual int32_t KillProcessesInBatch(const std::vector<int32_t> &pids) override;
/**
* UpdateApplicationInfoInstalled, call UpdateApplicationInfoInstalled() through proxy object,
* update the application info after new module installed.

View File

@ -54,6 +54,7 @@ private:
int32_t HandleKillProcessesByPids(MessageParcel &data, MessageParcel &reply);
int32_t HandleAttachPidToParent(MessageParcel &data, MessageParcel &reply);
int32_t HandleKillProcessWithAccount(MessageParcel &data, MessageParcel &reply);
int32_t HandleKillProcessesInBatch(MessageParcel &data, MessageParcel &reply);
int32_t HandleKillApplication(MessageParcel &data, MessageParcel &reply);
int32_t HandleForceKillApplication(MessageParcel &data, MessageParcel &reply);
int32_t HandleKillProcessesByAccessTokenId(MessageParcel &data, MessageParcel &reply);

View File

@ -355,6 +355,36 @@ int32_t AmsMgrProxy::KillProcessWithAccount(
return reply.ReadInt32();
}
int32_t AmsMgrProxy::KillProcessesInBatch(const std::vector<int32_t> &pids)
{
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_SYNC);
if (!WriteInterfaceToken(data)) {
return ERR_INVALID_DATA;
}
if (!data.WriteUint32(pids.size())) {
TAG_LOGE(AAFwkTag::APPMGR, "Write size failed");
return ERR_FLATTEN_OBJECT;
}
for (const auto &pid: pids) {
if (!data.WriteInt32(pid)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write pid failed");
return ERR_FLATTEN_OBJECT;
}
}
int32_t ret = SendTransactCmd(static_cast<uint32_t>(IAmsMgr::Message::KILL_PROCESSES_IN_BATCH),
data, reply, option);
if (ret != NO_ERROR) {
TAG_LOGW(AAFwkTag::APPMGR, "SendRequest err: %{public}d", ret);
return ret;
}
return reply.ReadInt32();
}
int32_t AmsMgrProxy::KillApplication(const std::string &bundleName, bool clearPageStack, int32_t appIndex)
{
TAG_LOGI(AAFwkTag::APPMGR, "start");

View File

@ -217,6 +217,8 @@ int32_t AmsMgrStub::OnRemoteRequestInnerFourth(uint32_t code, MessageParcel &dat
return HandleIsCallerKilling(data, reply);
case static_cast<uint32_t>(IAmsMgr::Message::SET_KEEP_ALIVE_DKV):
return HandleSetKeepAliveDkv(data, reply);
case static_cast<uint32_t>(IAmsMgr::Message::KILL_PROCESSES_IN_BATCH):
return HandleKillProcessesInBatch(data, reply);
}
return AAFwk::ERR_CODE_NOT_EXIST;
}
@ -356,6 +358,31 @@ ErrCode AmsMgrStub::HandleKillProcessWithAccount(MessageParcel &data, MessagePar
return NO_ERROR;
}
ErrCode AmsMgrStub::HandleKillProcessesInBatch(MessageParcel &data, MessageParcel &reply)
{
TAG_LOGI(AAFwkTag::APPMGR, "enter");
HITRACE_METER(HITRACE_TAG_APP);
auto size = data.ReadUint32();
TAG_LOGI(AAFwkTag::APPMGR, "pids.size=%{public}d", size);
if (size == 0 || size > MAX_KILL_PROCESS_PID_COUNT) {
TAG_LOGE(AAFwkTag::APPMGR, "Invalid size");
return ERR_INVALID_VALUE;
}
std::vector<int32_t> pids;
for (uint32_t i = 0; i < size; i++) {
pids.emplace_back(data.ReadInt32());
}
int32_t result = KillProcessesInBatch(pids);
reply.WriteInt32(result);
TAG_LOGI(AAFwkTag::APPMGR, "end");
return NO_ERROR;
}
ErrCode AmsMgrStub::HandleKillApplication(MessageParcel &data, MessageParcel &reply)
{
HITRACE_METER(HITRACE_TAG_APP);

View File

@ -133,6 +133,15 @@ public:
virtual int32_t KillProcessWithAccount(const std::string &bundleName, const int accountId,
const bool clearPageStack = false, int32_t appIndex = 0) override;
/**
* KillProcessesInBatch, kill processes in batch, call KillProcessesInBatch() through proxy object;
* the killed bundle won't be started by the watcher.
*
* @param pids, the pid list of processes are going to be killed.
* @return ERR_OK, return back success, others fail.
*/
virtual int32_t KillProcessesInBatch(const std::vector<int32_t> &pids) override;
/**
* UpdateApplicationInfoInstalled, call UpdateApplicationInfoInstalled() through proxy object,
* update the application info after new module installed.

View File

@ -195,6 +195,15 @@ public:
*/
virtual void KillProcessesByPids(std::vector<int32_t> &pids);
/**
* KillProcessesInBatch, kill processes in batch;
* the killed bundle won't be started by the watcher.
*
* @param pids, the pid list of processes are going to be killed.
* @return ERR_OK, return back success, others fail.
*/
virtual int32_t KillProcessesInBatch(const std::vector<int32_t> &pids);
/**
* Set child and parent relationship
* @param token child process
@ -1922,6 +1931,8 @@ private:
std::atomic<int32_t> willKillPidsNum_ = 0;
std::shared_ptr<AAFwk::TaskHandlerWrap> delayKillTaskHandler_;
std::unordered_set<std::string> nwebPreloadSet_ {};
ffrt::mutex killedBundleSetMutex_;
std::set<std::string> killedBundleSet_;
};
} // namespace AppExecFwk
} // namespace OHOS

View File

@ -291,6 +291,15 @@ int32_t AmsMgrScheduler::KillProcessWithAccount(
"KillProcessWithAccount");
}
int32_t AmsMgrScheduler::KillProcessesInBatch(const std::vector<int32_t> &pids)
{
TAG_LOGI(AAFwkTag::APPMGR, "pids.size=%{public}zu", pids.size());
if (!IsReady()) {
return ERR_INVALID_OPERATION;
}
return amsMgrServiceInner_->KillProcessesInBatch(pids);
}
void AmsMgrScheduler::AbilityAttachTimeOut(const sptr<IRemoteObject> &token)
{
TAG_LOGI(AAFwkTag::APPMGR, "call");

View File

@ -628,6 +628,13 @@ void AppMgrServiceInner::LoadAbility(std::shared_ptr<AbilityInfo> abilityInfo, s
TAG_LOGE(AAFwkTag::APPMGR, "checkLoadAbilityConditions fail");
return;
}
{
std::lock_guard lock(killedBundleSetMutex_);
if (killedBundleSet_.find(abilityInfo->bundleName) != killedBundleSet_.end()) {
TAG_LOGW(AAFwkTag::APPMGR, "%{public}s is being killed", abilityInfo->bundleName.c_str());
return;
}
}
if (abilityInfo->type == AbilityType::PAGE) {
AbilityRuntime::FreezeUtil::LifecycleFlow flow = {loadParam->token,
AbilityRuntime::FreezeUtil::TimeoutState::LOAD};
@ -2902,6 +2909,40 @@ void AppMgrServiceInner::KillProcessesByUserId(int32_t userId)
}
}
int32_t AppMgrServiceInner::KillProcessesInBatch(const std::vector<int32_t> &pids)
{
CHECK_CALLER_IS_SYSTEM_APP;
if (!AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
AAFwk::PermissionConstants::PERMISSION_KILL_APP_PROCESSES)) {
TAG_LOGE(AAFwkTag::APPMGR, "verify permission failed.");
return ERR_PERMISSION_DENIED;
}
if (!AAFwk::AppUtils::GetInstance().IsStartOptionsWithAnimation()) {
TAG_LOGE(AAFwkTag::APPMGR, "not supported.");
return AAFwk::ERR_CAPABILITY_NOT_SUPPORT;
}
std::vector<int32_t> killPids;
for (const auto& pid: pids) {
auto appRecord = GetAppRunningRecordByPid(pid);
if (appRecord == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "appRecord null");
continue;
}
killPids.emplace_back(pid);
std::string bundleName = appRecord->GetBundleName();
{
std::lock_guard lock(killedBundleSetMutex_);
killedBundleSet_.insert(bundleName);
}
}
std::lock_guard lock(killedBundleSetMutex_);
for (const auto& pid: killPids) {
(void)KillProcessByPid(pid, "KillProcessesInBatch");
}
killedBundleSet_.clear();
return ERR_OK;
}
void AppMgrServiceInner::KillProcessesByPids(std::vector<int32_t> &pids)
{
for (const auto& pid: pids) {

View File

@ -35,6 +35,7 @@ public:
MOCK_METHOD1(KillProcessByAbilityToken, void(const sptr<IRemoteObject>& token));
MOCK_METHOD1(KillProcessesByUserId, void(int32_t userId));
MOCK_METHOD4(KillProcessWithAccount, int(const std::string&, const int, const bool clearPageStack, int32_t));
MOCK_METHOD1(KillProcessesInBatch, int(const std::vector<int32_t> &pids));
MOCK_METHOD2(UpdateApplicationInfoInstalled, int(const std::string&, const int uid));
MOCK_METHOD3(ForceKillApplication, int32_t(const std::string& appName, const int userId, const int appIndex));
MOCK_METHOD3(KillApplication, int32_t(const std::string& bundleName, const bool clearPageStack, int32_t appIndex));