• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bg_continuous_task_napi_module.h"
17 
18 #include "ability.h"
19 #include "iservice_registry.h"
20 #include "napi_base_context.h"
21 #include "system_ability_definition.h"
22 #include "want_agent.h"
23 #ifdef SUPPORT_JSSTACK
24 #include "xpower_event_js.h"
25 #endif
26 
27 #include "background_mode.h"
28 #include "background_task_mgr_helper.h"
29 #include "bgtaskmgr_inner_errors.h"
30 #include "common.h"
31 #include "continuous_task_log.h"
32 #include "continuous_task_param.h"
33 
34 namespace OHOS {
35 namespace BackgroundTaskMgr {
36 namespace {
37 static constexpr uint32_t MAX_START_BG_RUNNING_PARAMS = 4;
38 static constexpr uint32_t MAX_STOP_BG_RUNNING_PARAMS = 2;
39 static constexpr uint32_t CALLBACK_RESULT_PARAMS_NUM = 2;
40 static constexpr uint32_t BG_MODE_ID_BEGIN = 1;
41 static constexpr uint32_t BG_MODE_ID_END = 9;
42 }
43 
44 struct AsyncCallbackInfo : public AsyncWorkData {
AsyncCallbackInfoOHOS::BackgroundTaskMgr::AsyncCallbackInfo45     explicit AsyncCallbackInfo(napi_env env) : AsyncWorkData(env) {}
46     std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext {nullptr};
47     uint32_t bgMode {0};
48     std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> wantAgent {nullptr};
49 };
50 
WrapVoidToJS(napi_env env)51 napi_value WrapVoidToJS(napi_env env)
52 {
53     napi_value result = nullptr;
54     NAPI_CALL(env, napi_get_null(env, &result));
55     return result;
56 }
57 
WrapUndefinedToJS(napi_env env)58 napi_value WrapUndefinedToJS(napi_env env)
59 {
60     napi_value result = nullptr;
61     NAPI_CALL(env, napi_get_undefined(env, &result));
62     return result;
63 }
64 
GetCallbackErrorValue(napi_env env,int32_t errCode)65 napi_value GetCallbackErrorValue(napi_env env, int32_t errCode)
66 {
67     napi_value jsObject = nullptr;
68     napi_value jsValue = nullptr;
69     NAPI_CALL(env, napi_create_int32(env, errCode, &jsValue));
70     NAPI_CALL(env, napi_create_object(env, &jsObject));
71     NAPI_CALL(env, napi_set_named_property(env, jsObject, "code", jsValue));
72     return jsObject;
73 }
74 
GetAbilityContext(const napi_env & env,const napi_value & value,std::shared_ptr<AbilityRuntime::AbilityContext> & abilityContext)75 napi_value GetAbilityContext(const napi_env &env, const napi_value &value,
76     std::shared_ptr<AbilityRuntime::AbilityContext> &abilityContext)
77 {
78     bool stageMode = false;
79     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, value, stageMode);
80     BGTASK_LOGI("is stage mode: %{public}s", stageMode ? "true" : "false");
81 
82     if (status != napi_ok || !stageMode) {
83         BGTASK_LOGI("Getting context with FA model");
84         auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
85         if (!ability) {
86             BGTASK_LOGE("Failed to get native ability instance");
87             return nullptr;
88         }
89         abilityContext = ability->GetAbilityContext();
90         if (!abilityContext) {
91             BGTASK_LOGE("get FA model ability context failed");
92             return nullptr;
93         }
94         return WrapVoidToJS(env);
95     } else {
96         BGTASK_LOGI("Getting context with stage model");
97         auto context = AbilityRuntime::GetStageModeContext(env, value);
98         if (!context) {
99             BGTASK_LOGE("get context failed");
100             return nullptr;
101         }
102         abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
103         if (!abilityContext) {
104             BGTASK_LOGE("get Stage model ability context failed");
105             return nullptr;
106         }
107         return WrapVoidToJS(env);
108     }
109 }
110 
GetMainAbilityLabel(const std::string & bundleName)111 std::string GetMainAbilityLabel(const std::string &bundleName)
112 {
113     sptr<ISystemAbilityManager> systemAbilityManager =
114         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
115     if (systemAbilityManager == nullptr) {
116         BGTASK_LOGE("get SystemAbilityManager failed");
117         return "";
118     }
119 
120     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
121     if (remoteObject == nullptr) {
122         BGTASK_LOGE("get Bundle Manager object failed");
123         return "";
124     }
125 
126     auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
127     if (bundleMgr == nullptr) {
128         BGTASK_LOGE("get Bundle Manager Proxy failed");
129         return "";
130     }
131 
132     AAFwk::Want want;
133     want.SetAction("action.system.home");
134     want.AddEntity("entity.system.home");
135     want.SetElementName("", bundleName, "", "");
136     AppExecFwk::AbilityInfo abilityInfo;
137     bundleMgr->QueryAbilityInfo(want, abilityInfo);
138     return bundleMgr->GetAbilityLabel(bundleName, abilityInfo.name);
139 }
140 
StartBackgroundRunningCheckParam(napi_env env,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)141 bool StartBackgroundRunningCheckParam(napi_env env, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
142 {
143     if (asyncCallbackInfo == nullptr) {
144         BGTASK_LOGE("asyncCallbackInfo is nullptr");
145         return false;
146     }
147     if (asyncCallbackInfo->errCode != ERR_OK) {
148         BGTASK_LOGE("input params parse failed");
149         return false;
150     }
151     if (asyncCallbackInfo->abilityContext == nullptr) {
152         asyncCallbackInfo->errCode = ERR_CONTEXT_NULL_OR_TYPE_ERR;
153         Common::HandleParamErr(env, ERR_CONTEXT_NULL_OR_TYPE_ERR, isThrow);
154         BGTASK_LOGE("abilityContext is null");
155         return false;
156     }
157     const std::shared_ptr<AppExecFwk::AbilityInfo> info = asyncCallbackInfo->abilityContext->GetAbilityInfo();
158     if (info == nullptr) {
159         BGTASK_LOGE("ability info is null");
160         Common::HandleParamErr(env, ERR_ABILITY_INFO_EMPTY, isThrow);
161         asyncCallbackInfo->errCode = ERR_ABILITY_INFO_EMPTY;
162         return false;
163     }
164 
165     if (asyncCallbackInfo->wantAgent == nullptr) {
166         BGTASK_LOGE("wantAgent param is nullptr");
167         Common::HandleParamErr(env, ERR_WANTAGENT_NULL_OR_TYPE_ERR, isThrow);
168         asyncCallbackInfo->errCode = ERR_WANTAGENT_NULL_OR_TYPE_ERR;
169         return false;
170     }
171 
172     sptr<IRemoteObject> token = asyncCallbackInfo->abilityContext->GetToken();
173     if (!token) {
174         BGTASK_LOGE("get ability token info failed");
175         Common::HandleParamErr(env, ERR_GET_TOKEN_ERR, isThrow);
176         asyncCallbackInfo->errCode = ERR_GET_TOKEN_ERR;
177         return false;
178     }
179 
180     if (asyncCallbackInfo->bgMode < BG_MODE_ID_BEGIN || asyncCallbackInfo->bgMode > BG_MODE_ID_END) {
181         BGTASK_LOGE("request background mode id: %{public}u out of range", asyncCallbackInfo->bgMode);
182         Common::HandleParamErr(env, ERR_BGMODE_RANGE_ERR, isThrow);
183         asyncCallbackInfo->errCode = ERR_BGMODE_RANGE_ERR;
184         return false;
185     }
186 
187     return true;
188 }
189 
StartBackgroundRunningExecuteCB(napi_env env,void * data)190 void StartBackgroundRunningExecuteCB(napi_env env, void *data)
191 {
192     AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
193     if (asyncCallbackInfo == nullptr || asyncCallbackInfo->errCode != ERR_OK) {
194         BGTASK_LOGE("input params error");
195         return;
196     }
197     const std::shared_ptr<AppExecFwk::AbilityInfo> info = asyncCallbackInfo->abilityContext->GetAbilityInfo();
198 
199     ContinuousTaskParam taskParam = ContinuousTaskParam(true, asyncCallbackInfo->bgMode,
200         asyncCallbackInfo->wantAgent, info->name, asyncCallbackInfo->abilityContext->GetToken(),
201         GetMainAbilityLabel(info->bundleName));
202     asyncCallbackInfo->errCode = BackgroundTaskMgrHelper::RequestStartBackgroundRunning(taskParam);
203 }
204 
CallbackCompletedCB(napi_env env,napi_status status,void * data)205 void CallbackCompletedCB(napi_env env, napi_status status, void *data)
206 {
207     AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
208     std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
209     napi_value callback {nullptr};
210     napi_value undefined {nullptr};
211     napi_value result[CALLBACK_RESULT_PARAMS_NUM] = {nullptr};
212     napi_value callResult = {nullptr};
213     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
214     if (asyncCallbackInfo->errCode == ERR_OK) {
215         result[0] = WrapUndefinedToJS(env);
216         napi_create_int32(env, 0, &result[1]);
217     } else {
218         result[1] = WrapUndefinedToJS(env);
219         std::string errMsg = Common::FindErrMsg(env, asyncCallbackInfo->errCode);
220         int32_t errCodeInfo = Common::FindErrCode(env, asyncCallbackInfo->errCode);
221         result[0] = Common::GetCallbackErrorValue(env, errCodeInfo, errMsg);
222     }
223 
224     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
225     NAPI_CALL_RETURN_VOID(env,
226         napi_call_function(env, undefined, callback, CALLBACK_RESULT_PARAMS_NUM, result, &callResult));
227 }
228 
PromiseCompletedCB(napi_env env,napi_status status,void * data)229 void PromiseCompletedCB(napi_env env, napi_status status, void *data)
230 {
231     AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
232     std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
233     napi_value result {nullptr};
234     if (asyncCallbackInfo->errCode == ERR_OK) {
235         napi_create_int32(env, 0, &result);
236         NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result));
237     } else {
238         std::string errMsg = Common::FindErrMsg(env, asyncCallbackInfo->errCode);
239         int32_t errCodeInfo = Common::FindErrCode(env, asyncCallbackInfo->errCode);
240         result = Common::GetCallbackErrorValue(env, errCodeInfo, errMsg);
241         NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result));
242     }
243 }
244 
StartBackgroundRunningAsync(napi_env env,napi_value * argv,const uint32_t argCallback,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)245 napi_value StartBackgroundRunningAsync(napi_env env, napi_value *argv,
246     const uint32_t argCallback, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
247 {
248     if (argv == nullptr || asyncCallbackInfo == nullptr) {
249         BGTASK_LOGE("param is nullptr");
250         return nullptr;
251     }
252     if (isThrow && asyncCallbackInfo->errCode != ERR_OK) {
253         return nullptr;
254     }
255     napi_value resourceName {nullptr};
256     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
257 
258     napi_valuetype valuetype = napi_undefined;
259     NAPI_CALL(env, napi_typeof(env, argv[argCallback], &valuetype));
260     if (valuetype != napi_function) {
261         Common::HandleParamErr(env, ERR_CALLBACK_NULL_OR_TYPE_ERR, isThrow);
262         return nullptr;
263     }
264     NAPI_CALL(env, napi_create_reference(env, argv[argCallback], 1, &asyncCallbackInfo->callback));
265     if (!StartBackgroundRunningCheckParam(env, asyncCallbackInfo, isThrow) && isThrow) {
266         return nullptr;
267     }
268 
269     NAPI_CALL(env, napi_create_async_work(env,
270         nullptr,
271         resourceName,
272         StartBackgroundRunningExecuteCB,
273         CallbackCompletedCB,
274         static_cast<void *>(asyncCallbackInfo),
275         &asyncCallbackInfo->asyncWork));
276     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
277 
278     return WrapVoidToJS(env);
279 }
280 
StartBackgroundRunningPromise(napi_env env,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)281 napi_value StartBackgroundRunningPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
282 {
283     if (asyncCallbackInfo == nullptr) {
284         BGTASK_LOGE("param is nullptr");
285         return nullptr;
286     }
287     napi_value resourceName;
288     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
289     napi_deferred deferred;
290     napi_value promise {nullptr};
291     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
292     asyncCallbackInfo->deferred = deferred;
293     if (!StartBackgroundRunningCheckParam(env, asyncCallbackInfo, isThrow) && isThrow) {
294         return nullptr;
295     }
296 
297     NAPI_CALL(env, napi_create_async_work(env,
298         nullptr,
299         resourceName,
300         StartBackgroundRunningExecuteCB,
301         PromiseCompletedCB,
302         static_cast<void *>(asyncCallbackInfo),
303         &asyncCallbackInfo->asyncWork));
304     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
305     return promise;
306 }
307 
GetBackgroundMode(const napi_env & env,const napi_value & value,uint32_t & bgMode)308 napi_value GetBackgroundMode(const napi_env &env, const napi_value &value, uint32_t &bgMode)
309 {
310     napi_valuetype valuetype = napi_undefined;
311     NAPI_CALL(env, napi_typeof(env, value, &valuetype));
312     if (valuetype != napi_number) {
313         Common::HandleParamErr(env, ERR_BGMODE_NULL_OR_TYPE_ERR, true);
314         return nullptr;
315     }
316     napi_get_value_uint32(env, value, &bgMode);
317 
318     BGTASK_LOGI("get bgmode info: %{public}u", bgMode);
319     return WrapVoidToJS(env);
320 }
321 
GetWantAgent(const napi_env & env,const napi_value & value,std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> & wantAgent)322 napi_value GetWantAgent(const napi_env &env, const napi_value &value,
323     std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> &wantAgent)
324 {
325     napi_valuetype valuetype = napi_undefined;
326     AbilityRuntime::WantAgent::WantAgent *wantAgentPtr = nullptr;
327     NAPI_CALL(env, napi_typeof(env, value, &valuetype));
328     if (valuetype != napi_object) {
329         Common::HandleParamErr(env, ERR_WANTAGENT_NULL_OR_TYPE_ERR, true);
330         return nullptr;
331     }
332     napi_unwrap(env, value, (void **)&wantAgentPtr);
333     wantAgent = std::make_shared<AbilityRuntime::WantAgent::WantAgent>(*wantAgentPtr);
334 
335     return WrapVoidToJS(env);
336 }
337 
StartBackgroundRunning(napi_env env,napi_callback_info info,bool isThrow)338 napi_value StartBackgroundRunning(napi_env env, napi_callback_info info, bool isThrow)
339 {
340 #ifdef SUPPORT_JSSTACK
341     HiviewDFX::ReportXPowerJsStackSysEvent(env, "CONTINUOUS_TASK_APPLY");
342 #endif
343     AsyncCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
344     if (asyncCallbackInfo == nullptr) {
345         BGTASK_LOGE("asyncCallbackInfo == nullpter");
346         return WrapVoidToJS(env);
347     }
348     std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
349 
350     size_t argc = MAX_START_BG_RUNNING_PARAMS;
351     napi_value argv[MAX_START_BG_RUNNING_PARAMS] = {nullptr};
352     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
353     if (argc > MAX_START_BG_RUNNING_PARAMS) {
354         BGTASK_LOGE("wrong param nums");
355         Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR, isThrow);
356         return WrapVoidToJS(env);
357     }
358 
359     // argv[0] : context : AbilityContext
360     if (GetAbilityContext(env, argv[0], asyncCallbackInfo->abilityContext) == nullptr) {
361         BGTASK_LOGE("Get ability context failed");
362         Common::HandleParamErr(env, ERR_CONTEXT_NULL_OR_TYPE_ERR, isThrow);
363         asyncCallbackInfo->errCode = ERR_CONTEXT_NULL_OR_TYPE_ERR;
364     }
365 
366     // argv[1] : bgMode : BackgroundMode
367     if (GetBackgroundMode(env, argv[1], asyncCallbackInfo->bgMode) == nullptr) {
368         BGTASK_LOGE("input bgmode param not number");
369         Common::HandleParamErr(env, ERR_BGMODE_NULL_OR_TYPE_ERR, isThrow);
370         asyncCallbackInfo->errCode = ERR_BGMODE_NULL_OR_TYPE_ERR;
371     }
372 
373     // argv[2] : wantAgent: WantAgent
374     if (GetWantAgent(env, argv[2], asyncCallbackInfo->wantAgent) == nullptr) {
375         BGTASK_LOGE("input wantAgent param is not object");
376         Common::HandleParamErr(env, ERR_WANTAGENT_NULL_OR_TYPE_ERR, isThrow);
377         asyncCallbackInfo->errCode = ERR_WANTAGENT_NULL_OR_TYPE_ERR;
378     }
379 
380     napi_value ret {nullptr};
381 
382     if (argc == MAX_START_BG_RUNNING_PARAMS) {
383         ret = StartBackgroundRunningAsync(env, argv, MAX_START_BG_RUNNING_PARAMS - 1, asyncCallbackInfo, isThrow);
384     } else {
385         ret = StartBackgroundRunningPromise(env, asyncCallbackInfo, isThrow);
386     }
387 
388     if (ret == nullptr) {
389         BGTASK_LOGE("ret is nullpter");
390         if (asyncCallbackInfo != nullptr) {
391             delete asyncCallbackInfo;
392             asyncCallbackInfo = nullptr;
393         }
394         ret = WrapVoidToJS(env);
395     }
396     callbackPtr.release();
397     return ret;
398 }
399 
StopBackgroundRunningCheckParam(napi_env env,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)400 bool StopBackgroundRunningCheckParam(napi_env env, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
401 {
402     if (asyncCallbackInfo == nullptr) {
403         BGTASK_LOGE("asyncCallbackInfo is nullptr");
404         return false;
405     }
406     if (asyncCallbackInfo->abilityContext == nullptr) {
407         BGTASK_LOGE("ability context is null");
408         Common::HandleParamErr(env, ERR_CONTEXT_NULL_OR_TYPE_ERR, isThrow);
409         asyncCallbackInfo->errCode = ERR_CONTEXT_NULL_OR_TYPE_ERR;
410         return false;
411     }
412     const std::shared_ptr<AppExecFwk::AbilityInfo> info = asyncCallbackInfo->abilityContext->GetAbilityInfo();
413     if (info == nullptr) {
414         BGTASK_LOGE("abilityInfo is null");
415         Common::HandleParamErr(env, ERR_ABILITY_INFO_EMPTY, isThrow);
416         asyncCallbackInfo->errCode = ERR_ABILITY_INFO_EMPTY;
417         return false;
418     }
419 
420     sptr<IRemoteObject> token = asyncCallbackInfo->abilityContext->GetToken();
421     if (!token) {
422         BGTASK_LOGE("get ability token info failed");
423         Common::HandleParamErr(env, ERR_GET_TOKEN_ERR, isThrow);
424         asyncCallbackInfo->errCode = ERR_GET_TOKEN_ERR;
425         return false;
426     }
427     return true;
428 }
429 
StopBackgroundRunningExecuteCB(napi_env env,void * data)430 void StopBackgroundRunningExecuteCB(napi_env env, void *data)
431 {
432     AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
433     if (asyncCallbackInfo == nullptr || asyncCallbackInfo->errCode != ERR_OK) {
434         BGTASK_LOGE("input param error");
435         return;
436     }
437     const std::shared_ptr<AppExecFwk::AbilityInfo> info = asyncCallbackInfo->abilityContext->GetAbilityInfo();
438     sptr<IRemoteObject> token = asyncCallbackInfo->abilityContext->GetToken();
439     asyncCallbackInfo->errCode = BackgroundTaskMgrHelper::RequestStopBackgroundRunning(info->name, token);
440 }
441 
StopBackgroundRunningAsync(napi_env env,napi_value * argv,const uint32_t argCallback,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)442 napi_value StopBackgroundRunningAsync(napi_env env, napi_value *argv,
443     const uint32_t argCallback, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
444 {
445     if (argv == nullptr || asyncCallbackInfo == nullptr) {
446         BGTASK_LOGE("param is nullptr");
447         return nullptr;
448     }
449     if (isThrow && asyncCallbackInfo->errCode != ERR_OK) {
450         return nullptr;
451     }
452     napi_value resourceName {nullptr};
453     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
454 
455     napi_valuetype valuetype = napi_undefined;
456     NAPI_CALL(env, napi_typeof(env, argv[argCallback], &valuetype));
457     if (valuetype == napi_function) {
458         NAPI_CALL(env, napi_create_reference(env, argv[argCallback], 1, &asyncCallbackInfo->callback));
459     }
460     if (!StopBackgroundRunningCheckParam(env, asyncCallbackInfo, isThrow) && isThrow) {
461         return nullptr;
462     }
463 
464     NAPI_CALL(env, napi_create_async_work(env,
465         nullptr,
466         resourceName,
467         StopBackgroundRunningExecuteCB,
468         CallbackCompletedCB,
469         static_cast<void *>(asyncCallbackInfo),
470         &asyncCallbackInfo->asyncWork));
471     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
472     return WrapVoidToJS(env);
473 }
474 
StopBackgroundRunningPromise(napi_env env,AsyncCallbackInfo * asyncCallbackInfo,bool isThrow)475 napi_value StopBackgroundRunningPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo, bool isThrow)
476 {
477     if (asyncCallbackInfo == nullptr) {
478         BGTASK_LOGE("param is nullptr");
479         return nullptr;
480     }
481     napi_value resourceName {nullptr};
482     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
483     napi_deferred deferred;
484     napi_value promise {nullptr};
485     napi_create_promise(env, &deferred, &promise);
486 
487     asyncCallbackInfo->deferred = deferred;
488     if (!StopBackgroundRunningCheckParam(env, asyncCallbackInfo, isThrow) && isThrow) {
489         return nullptr;
490     }
491 
492     napi_create_async_work(
493         env,
494         nullptr,
495         resourceName,
496         StopBackgroundRunningExecuteCB,
497         PromiseCompletedCB,
498         static_cast<void *>(asyncCallbackInfo),
499         &asyncCallbackInfo->asyncWork);
500     napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
501     return promise;
502 }
503 
StopBackgroundRunning(napi_env env,napi_callback_info info,bool isThrow)504 napi_value StopBackgroundRunning(napi_env env, napi_callback_info info, bool isThrow)
505 {
506 #ifdef SUPPORT_JSSTACK
507     HiviewDFX::ReportXPowerJsStackSysEvent(env, "CONTINUOUS_TASK_CANCEL");
508 #endif
509     AsyncCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
510     if (asyncCallbackInfo == nullptr) {
511         BGTASK_LOGE("asyncCallbackInfo is nullpter");
512         return WrapVoidToJS(env);
513     }
514     std::unique_ptr<AsyncCallbackInfo> callbackPtr {asyncCallbackInfo};
515 
516     size_t argc = MAX_STOP_BG_RUNNING_PARAMS;
517     napi_value argv[MAX_STOP_BG_RUNNING_PARAMS] = {nullptr};
518 
519     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
520     if (argc > MAX_STOP_BG_RUNNING_PARAMS) {
521         BGTASK_LOGE("wrong param nums");
522         Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR, isThrow);
523         return nullptr;
524     }
525 
526     // argv[0] : context : AbilityContext
527     if (GetAbilityContext(env, argv[0], asyncCallbackInfo->abilityContext) == nullptr) {
528         BGTASK_LOGE("Get ability context failed");
529         Common::HandleParamErr(env, ERR_CONTEXT_NULL_OR_TYPE_ERR, isThrow);
530         asyncCallbackInfo->errCode = ERR_CONTEXT_NULL_OR_TYPE_ERR;
531     }
532 
533     napi_value ret {nullptr};
534     if (argc == MAX_STOP_BG_RUNNING_PARAMS) {
535         ret = StopBackgroundRunningAsync(env, argv, MAX_STOP_BG_RUNNING_PARAMS - 1, asyncCallbackInfo, isThrow);
536     } else {
537         ret = StopBackgroundRunningPromise(env, asyncCallbackInfo, isThrow);
538     }
539 
540     if (ret == nullptr) {
541         BGTASK_LOGE("ret is nullpter");
542         if (asyncCallbackInfo != nullptr) {
543             delete asyncCallbackInfo;
544             asyncCallbackInfo = nullptr;
545         }
546         ret = WrapVoidToJS(env);
547     }
548     callbackPtr.release();
549     return ret;
550 }
551 
StartBackgroundRunning(napi_env env,napi_callback_info info)552 napi_value StartBackgroundRunning(napi_env env, napi_callback_info info)
553 {
554     return StartBackgroundRunning(env, info, false);
555 }
556 
StopBackgroundRunning(napi_env env,napi_callback_info info)557 napi_value StopBackgroundRunning(napi_env env, napi_callback_info info)
558 {
559     return StopBackgroundRunning(env, info, false);
560 }
561 
StartBackgroundRunningThrow(napi_env env,napi_callback_info info)562 napi_value StartBackgroundRunningThrow(napi_env env, napi_callback_info info)
563 {
564     return StartBackgroundRunning(env, info, true);
565 }
566 
StopBackgroundRunningThrow(napi_env env,napi_callback_info info)567 napi_value StopBackgroundRunningThrow(napi_env env, napi_callback_info info)
568 {
569     return StopBackgroundRunning(env, info, true);
570 }
571 }  // namespace BackgroundTaskMgr
572 }  // namespace OHOS