1 /*
2 * Copyright (c) 2022-2023 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 "js_continuation_manager.h"
17
18 #include <memory>
19
20 #include "base/continuationmgr_log.h"
21 #include "device_connect_status.h"
22 #include "distributed_ability_manager_client.h"
23 #include "js_runtime_utils.h"
24 #include "napi_common_util.h"
25 #include "napi_error_code.h"
26
27 namespace OHOS {
28 namespace DistributedSchedule {
29 using namespace OHOS::AbilityRuntime;
30 using namespace OHOS::AppExecFwk;
31 namespace {
32 const std::string TAG = "JsContinuationManager";
33 const std::string CODE_KEY_NAME = "code";
34 constexpr int32_t ERR_NOT_OK = -1;
35 constexpr int32_t ARG_COUNT_ONE = 1;
36 constexpr int32_t ARG_COUNT_TWO = 2;
37 constexpr int32_t ARG_COUNT_THREE = 3;
38 constexpr uint32_t MAX_JSPROCOUNT = 1000000;
39 constexpr int32_t ARG_COUNT_FOUR = 4;
40 }
41
Finalizer(NativeEngine * engine,void * data,void * hint)42 void JsContinuationManager::Finalizer(NativeEngine* engine, void* data, void* hint)
43 {
44 HILOGI("JsContinuationManager::Finalizer is called");
45 JsContinuationManager* jsContinuationManager = static_cast<JsContinuationManager*>(data);
46 if (jsContinuationManager != nullptr) {
47 delete jsContinuationManager;
48 jsContinuationManager = nullptr;
49 }
50 }
51
Register(NativeEngine * engine,NativeCallbackInfo * info)52 NativeValue* JsContinuationManager::Register(NativeEngine* engine, NativeCallbackInfo* info)
53 {
54 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
55 return (me != nullptr) ? me->OnRegister(*engine, *info) : nullptr;
56 }
57
Unregister(NativeEngine * engine,NativeCallbackInfo * info)58 NativeValue* JsContinuationManager::Unregister(NativeEngine* engine, NativeCallbackInfo* info)
59 {
60 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
61 return (me != nullptr) ? me->OnUnregister(*engine, *info) : nullptr;
62 }
63
RegisterDeviceSelectionCallback(NativeEngine * engine,NativeCallbackInfo * info)64 NativeValue* JsContinuationManager::RegisterDeviceSelectionCallback(NativeEngine* engine, NativeCallbackInfo* info)
65 {
66 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
67 return (me != nullptr) ? me->OnRegisterDeviceSelectionCallback(*engine, *info) : nullptr;
68 }
69
UnregisterDeviceSelectionCallback(NativeEngine * engine,NativeCallbackInfo * info)70 NativeValue* JsContinuationManager::UnregisterDeviceSelectionCallback(NativeEngine* engine, NativeCallbackInfo* info)
71 {
72 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
73 return (me != nullptr) ? me->OnUnregisterDeviceSelectionCallback(*engine, *info) : nullptr;
74 }
75
UpdateConnectStatus(NativeEngine * engine,NativeCallbackInfo * info)76 NativeValue *JsContinuationManager::UpdateConnectStatus(NativeEngine *engine, NativeCallbackInfo *info)
77 {
78 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
79 return (me != nullptr) ? me->OnUpdateConnectStatus(*engine, *info) : nullptr;
80 }
81
StartDeviceManager(NativeEngine * engine,NativeCallbackInfo * info)82 NativeValue *JsContinuationManager::StartDeviceManager(NativeEngine *engine, NativeCallbackInfo *info)
83 {
84 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
85 return (me != nullptr) ? me->OnStartDeviceManager(*engine, *info) : nullptr;
86 }
87
InitDeviceConnectStateObject(NativeEngine * engine,NativeCallbackInfo * info)88 NativeValue *JsContinuationManager::InitDeviceConnectStateObject(NativeEngine *engine, NativeCallbackInfo *info)
89 {
90 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
91 return (me != nullptr) ? me->OnInitDeviceConnectStateObject(*engine, *info) : nullptr;
92 }
93
InitContinuationModeObject(NativeEngine * engine,NativeCallbackInfo * info)94 NativeValue *JsContinuationManager::InitContinuationModeObject(NativeEngine *engine, NativeCallbackInfo *info)
95 {
96 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
97 return (me != nullptr) ? me->OnInitContinuationModeObject(*engine, *info) : nullptr;
98 }
99
RegisterContinuation(NativeEngine * engine,NativeCallbackInfo * info)100 NativeValue* JsContinuationManager::RegisterContinuation(NativeEngine* engine, NativeCallbackInfo* info)
101 {
102 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
103 return (me != nullptr) ? me->OnRegisterContinuation(*engine, *info) : nullptr;
104 }
105
UnregisterContinuation(NativeEngine * engine,NativeCallbackInfo * info)106 NativeValue* JsContinuationManager::UnregisterContinuation(NativeEngine* engine, NativeCallbackInfo* info)
107 {
108 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
109 return (me != nullptr) ? me->OnUnregisterContinuation(*engine, *info) : nullptr;
110 }
111
UpdateContinuationState(NativeEngine * engine,NativeCallbackInfo * info)112 NativeValue* JsContinuationManager::UpdateContinuationState(NativeEngine* engine, NativeCallbackInfo *info)
113 {
114 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
115 return (me != nullptr) ? me->OnUpdateContinuationState(*engine, *info) : nullptr;
116 }
117
StartContinuationDeviceManager(NativeEngine * engine,NativeCallbackInfo * info)118 NativeValue* JsContinuationManager::StartContinuationDeviceManager(NativeEngine* engine, NativeCallbackInfo *info)
119 {
120 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(engine, info);
121 return (me != nullptr) ? me->OnStartContinuationDeviceManager(*engine, *info) : nullptr;
122 }
123
OnRegister(NativeEngine & engine,NativeCallbackInfo & info)124 NativeValue* JsContinuationManager::OnRegister(NativeEngine &engine, NativeCallbackInfo &info)
125 {
126 HILOGD("called.");
127 int32_t errCode = 0;
128 decltype(info.argc) unwrapArgc = 0;
129 std::shared_ptr<ContinuationExtraParams> continuationExtraParams = std::make_shared<ContinuationExtraParams>();
130 if (info.argc > 0 && info.argv[0]->TypeOf() == NATIVE_OBJECT) {
131 HILOGI("register options is used.");
132 if (!UnWrapContinuationExtraParams(reinterpret_cast<napi_env>(&engine),
133 reinterpret_cast<napi_value>(info.argv[0]), continuationExtraParams)) {
134 HILOGE("Parse continuationExtraParams failed");
135 errCode = ERR_NOT_OK;
136 }
137 unwrapArgc++;
138 }
139 AsyncTask::CompleteCallback complete =
140 [continuationExtraParams, unwrapArgc, errCode](NativeEngine &engine, AsyncTask &task, int32_t status) {
141 napi_handle_scope scope = nullptr;
142 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
143 if (scope == nullptr) {
144 return;
145 }
146
147 if (errCode != 0) {
148 task.Reject(engine, CreateJsError(engine, errCode, "Invalidate params."));
149 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
150 return;
151 }
152 int32_t token = -1;
153 int32_t ret = (unwrapArgc == 0) ? DistributedAbilityManagerClient::GetInstance().Register(nullptr, token) :
154 DistributedAbilityManagerClient::GetInstance().Register(continuationExtraParams, token);
155 if (ret == ERR_OK) {
156 task.Resolve(engine, engine.CreateNumber(token));
157 } else {
158 task.Reject(engine, CreateJsError(engine, ret, "Register failed."));
159 }
160
161 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
162 };
163
164 NativeValue* lastParam = (info.argc <= unwrapArgc) ? nullptr : info.argv[unwrapArgc];
165 NativeValue* result = nullptr;
166 AsyncTask::Schedule("JsContinuationManager::OnRegister",
167 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
168 return result;
169 }
170
OnRegisterContinuation(NativeEngine & engine,NativeCallbackInfo & info)171 NativeValue* JsContinuationManager::OnRegisterContinuation(NativeEngine &engine, NativeCallbackInfo &info)
172 {
173 HILOGD("called.");
174 decltype(info.argc) unwrapArgc = 0;
175 std::shared_ptr<ContinuationExtraParams> continuationExtraParams;
176 std::string errInfo = [this, &engine, &info, &continuationExtraParams, &unwrapArgc]() -> std::string {
177 if (info.argc > ARG_COUNT_TWO) {
178 return "Parameter error. The type of \"number of parameters\" must be less than 3";
179 }
180 if (info.argc > 0 && info.argv[0]->TypeOf() == NATIVE_OBJECT) {
181 HILOGI("register options is used.");
182 continuationExtraParams = std::make_shared<ContinuationExtraParams>();
183 if (!UnWrapContinuationExtraParams(reinterpret_cast<napi_env>(&engine),
184 reinterpret_cast<napi_value>(info.argv[0]), continuationExtraParams)) {
185 return "Parameter error. The type of \"options\" must be ContinuationExtraParams";
186 }
187 unwrapArgc++;
188 }
189 return std::string();
190 } ();
191 if (!errInfo.empty()) {
192 HILOGE("%{public}s", errInfo.c_str());
193 napi_throw(reinterpret_cast<napi_env>(&engine),
194 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), PARAMETER_CHECK_FAILED, errInfo));
195 return engine.CreateUndefined();
196 }
197 AsyncTask::CompleteCallback complete =
198 [this, continuationExtraParams, unwrapArgc](NativeEngine &engine, AsyncTask &task, int32_t status) {
199 napi_handle_scope scope = nullptr;
200 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
201 if (scope == nullptr) {
202 return;
203 }
204
205 int32_t token = -1;
206 int32_t errCode = (unwrapArgc == 0) ? DistributedAbilityManagerClient::GetInstance().Register(nullptr, token) :
207 DistributedAbilityManagerClient::GetInstance().Register(continuationExtraParams, token);
208 if (errCode == ERR_OK) {
209 task.Resolve(engine, engine.CreateNumber(token));
210 } else {
211 errCode = ErrorCodeReturn(errCode);
212 task.Reject(engine, CreateJsError(engine, errCode, ErrorMessageReturn(errCode)));
213 }
214
215 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
216 };
217
218 NativeValue* lastParam = (info.argc <= unwrapArgc) ? nullptr : info.argv[unwrapArgc];
219 NativeValue* result = nullptr;
220 AsyncTask::Schedule("JsContinuationManager::OnRegisterContinuation",
221 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
222 return result;
223 }
224
OnUnregister(NativeEngine & engine,NativeCallbackInfo & info)225 NativeValue* JsContinuationManager::OnUnregister(NativeEngine &engine, NativeCallbackInfo &info)
226 {
227 HILOGD("called.");
228 int32_t errCode = 0;
229 if (info.argc == 0) {
230 HILOGE("Params not match");
231 errCode = ERR_NOT_OK;
232 }
233 int32_t token = -1;
234 if (!errCode && !ConvertFromJsValue(engine, info.argv[0], token)) {
235 HILOGE("Parse token failed");
236 errCode = ERR_NOT_OK;
237 }
238 AsyncTask::CompleteCallback complete =
239 [token, errCode](NativeEngine &engine, AsyncTask &task, int32_t status) {
240 napi_handle_scope scope = nullptr;
241 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
242 if (scope == nullptr) {
243 return;
244 }
245
246 if (errCode != 0) {
247 task.Reject(engine, CreateJsError(engine, errCode, "Invalidate params."));
248 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
249 return;
250 }
251 int32_t ret = DistributedAbilityManagerClient::GetInstance().Unregister(token);
252 if (ret == ERR_OK) {
253 task.Resolve(engine, engine.CreateUndefined());
254 } else {
255 task.Reject(engine, CreateJsError(engine, ret, "Unregister failed."));
256 }
257
258 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
259 };
260
261 NativeValue* lastParam = (info.argc <= ARG_COUNT_ONE) ? nullptr : info.argv[ARG_COUNT_ONE];
262 NativeValue* result = nullptr;
263 AsyncTask::Schedule("JsContinuationManager::OnUnregister",
264 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
265 return result;
266 }
267
OnUnregisterContinuation(NativeEngine & engine,NativeCallbackInfo & info)268 NativeValue* JsContinuationManager::OnUnregisterContinuation(NativeEngine &engine, NativeCallbackInfo &info)
269 {
270 HILOGD("called.");
271 int32_t token = -1;
272 std::string errInfo = [this, &engine, &info, &token]() -> std::string {
273 if (info.argc == 0 || info.argc > ARG_COUNT_TWO) {
274 return "Parameter error. The type of \"number of parameters\" must be greater than 0 and less than 3";
275 }
276 if (!ConvertFromJsValue(engine, info.argv[0], token)) {
277 return "Parameter error. The type of \"token\" must be number";
278 }
279 return std::string();
280 } ();
281 if (!errInfo.empty()) {
282 HILOGE("%{public}s", errInfo.c_str());
283 napi_throw(reinterpret_cast<napi_env>(&engine),
284 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), PARAMETER_CHECK_FAILED, errInfo));
285 return engine.CreateUndefined();
286 }
287 AsyncTask::CompleteCallback complete =
288 [this, token](NativeEngine &engine, AsyncTask &task, int32_t status) {
289 napi_handle_scope scope = nullptr;
290 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
291 if (scope == nullptr) {
292 return;
293 }
294
295 int32_t errCode = DistributedAbilityManagerClient::GetInstance().Unregister(token);
296 if (errCode == ERR_OK) {
297 task.Resolve(engine, engine.CreateNull());
298 } else {
299 errCode = ErrorCodeReturn(errCode);
300 task.Reject(engine, CreateJsError(engine, errCode, ErrorMessageReturn(errCode)));
301 }
302
303 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
304 };
305
306 NativeValue* lastParam = (info.argc == ARG_COUNT_ONE) ? nullptr : info.argv[ARG_COUNT_ONE];
307 NativeValue* result = nullptr;
308 AsyncTask::Schedule("JsContinuationManager::OnUnregisterContinuation",
309 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
310 return result;
311 }
312
OnRegisterDeviceSelectionCallbackParameterCheck(NativeEngine & engine,NativeCallbackInfo & info,std::string & cbType,int32_t & token,NativeValue ** jsListenerObj)313 std::string JsContinuationManager::OnRegisterDeviceSelectionCallbackParameterCheck(NativeEngine &engine,
314 NativeCallbackInfo &info, std::string &cbType, int32_t &token, NativeValue** jsListenerObj)
315 {
316 if (info.argc != ARG_COUNT_THREE) {
317 return "Parameter error. The type of \"number of parameters\" must be 3";
318 }
319 if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
320 return "Parameter error. The type of \"type\" must be string";
321 }
322 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
323 return "Parameter error. The type of \"type\" must be " +
324 std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
325 }
326 if (!ConvertFromJsValue(engine, info.argv[ARG_COUNT_ONE], token)) {
327 return "Parameter error. The type of \"token\" must be number";
328 }
329 *jsListenerObj = info.argv[ARG_COUNT_TWO];
330 if (!IsCallbackValid(*jsListenerObj)) {
331 return "Parameter error. The type of \"callback\" must be Callback<Array<ContinuationResult>>";
332 }
333 return std::string();
334 }
335
OnRegisterDeviceSelectionCallback(NativeEngine & engine,NativeCallbackInfo & info)336 NativeValue* JsContinuationManager::OnRegisterDeviceSelectionCallback(NativeEngine &engine, NativeCallbackInfo &info)
337 {
338 HILOGD("called.");
339 std::string cbType;
340 int32_t token = -1;
341 int32_t errCode = PARAMETER_CHECK_FAILED;
342 NativeValue* jsListenerObj = nullptr;
343 std::string errInfo = OnRegisterDeviceSelectionCallbackParameterCheck(engine, info, cbType, token, &jsListenerObj);
344 if (errInfo.empty()) {
345 errInfo = [this, &engine, &info, &cbType, &token, &jsListenerObj, &errCode]() -> std::string {
346 std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
347 if (IsCallbackRegistered(token, cbType)) {
348 errCode = REPEATED_REGISTRATION;
349 return ErrorMessageReturn(errCode);
350 }
351 std::unique_ptr<NativeReference> callbackRef;
352 callbackRef.reset(engine.CreateReference(jsListenerObj, 1));
353 sptr<JsDeviceSelectionListener> deviceSelectionListener = new JsDeviceSelectionListener(&engine);
354 if (deviceSelectionListener == nullptr) {
355 HILOGE("deviceSelectionListener is nullptr!");
356 errCode = SYSTEM_WORK_ABNORMALLY;
357 return ErrorMessageReturn(errCode);
358 }
359 errCode = DistributedAbilityManagerClient::GetInstance().RegisterDeviceSelectionCallback(
360 token, cbType, deviceSelectionListener);
361 if (errCode == ERR_OK) {
362 deviceSelectionListener->AddCallback(cbType, jsListenerObj);
363 CallbackPair callbackPair = std::make_pair(std::move(callbackRef), deviceSelectionListener);
364 jsCbMap_[token][cbType] = std::move(callbackPair); // move assignment
365 HILOGI("RegisterDeviceSelectionListener success");
366 } else {
367 deviceSelectionListener = nullptr;
368 errCode = ErrorCodeReturn(errCode);
369 return ErrorMessageReturn(errCode);
370 }
371 return std::string();
372 }();
373 }
374 if (!errInfo.empty()) {
375 HILOGE("%{public}s", errInfo.c_str());
376 napi_throw(reinterpret_cast<napi_env>(&engine),
377 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), errCode, errInfo));
378 }
379 return engine.CreateUndefined();
380 }
381
OnUnregisterDeviceSelectionCallback(NativeEngine & engine,NativeCallbackInfo & info)382 NativeValue* JsContinuationManager::OnUnregisterDeviceSelectionCallback(NativeEngine &engine, NativeCallbackInfo &info)
383 {
384 HILOGD("called.");
385 std::string cbType;
386 int32_t token = -1;
387 int32_t errCode = PARAMETER_CHECK_FAILED;
388 std::string errInfo = [this, &engine, &info, &cbType, &token, &errCode]() -> std::string {
389 if (info.argc != ARG_COUNT_TWO) {
390 return "Parameter error. The type of \"number of parameters\" must be 2";
391 }
392 if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
393 return "Parameter error. The type of \"type\" must be string";
394 }
395 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
396 return "Parameter error. The type of \"type\" must be " +
397 std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
398 }
399 if (!ConvertFromJsValue(engine, info.argv[ARG_COUNT_ONE], token)) {
400 return "Parameter error. The type of \"token\" must be number";
401 }
402 {
403 std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
404 if (!IsCallbackRegistered(token, cbType)) {
405 errCode = CALLBACK_TOKEN_UNREGISTERED;
406 return ErrorMessageReturn(errCode);
407 }
408 errCode = DistributedAbilityManagerClient::GetInstance().UnregisterDeviceSelectionCallback(token, cbType);
409 if (errCode == ERR_OK) {
410 CallbackPair& callbackPair = jsCbMap_[token][cbType];
411 callbackPair.second->RemoveCallback(cbType);
412 jsCbMap_[token].erase(cbType);
413 if (jsCbMap_[token].empty()) {
414 jsCbMap_.erase(token);
415 }
416 HILOGI("UnregisterDeviceSelectionCallback success");
417 } else {
418 errCode = ErrorCodeReturn(errCode);
419 return ErrorMessageReturn(errCode);
420 }
421 }
422 return std::string();
423 } ();
424 if (!errInfo.empty()) {
425 HILOGE("%{public}s", errInfo.c_str());
426 napi_throw(reinterpret_cast<napi_env>(&engine),
427 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), errCode, errInfo));
428 }
429 return engine.CreateUndefined();
430 }
431
OnUpdateConnectStatus(NativeEngine & engine,NativeCallbackInfo & info)432 NativeValue *JsContinuationManager::OnUpdateConnectStatus(NativeEngine &engine, NativeCallbackInfo &info)
433 {
434 HILOGD("called.");
435 int32_t errCode = 0;
436 if (info.argc < ARG_COUNT_THREE) {
437 HILOGE("Params not match");
438 errCode = ERR_NOT_OK;
439 }
440 int32_t token = -1;
441 if (!errCode && !ConvertFromJsValue(engine, info.argv[0], token)) {
442 HILOGE("Parse token failed");
443 errCode = ERR_NOT_OK;
444 }
445 std::string deviceId;
446 if (!errCode && !ConvertFromJsValue(engine, info.argv[ARG_COUNT_ONE], deviceId)) {
447 HILOGE("Parse deviceId failed");
448 errCode = ERR_NOT_OK;
449 }
450 DeviceConnectStatus deviceConnectStatus = DeviceConnectStatus::IDLE;
451 if (!errCode && !ConvertFromJsValue(engine, info.argv[ARG_COUNT_TWO], deviceConnectStatus)) {
452 HILOGE("Parse device connect status failed");
453 errCode = ERR_NOT_OK;
454 }
455 AsyncTask::CompleteCallback complete =
456 [token, deviceId, deviceConnectStatus, errCode](NativeEngine &engine, AsyncTask &task, int32_t status) {
457 napi_handle_scope scope = nullptr;
458 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
459 if (scope == nullptr) {
460 return;
461 }
462
463 if (errCode != 0) {
464 task.Reject(engine, CreateJsError(engine, errCode, "Invalidate params."));
465 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
466 return;
467 }
468 int32_t ret = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
469 token, deviceId, deviceConnectStatus);
470 if (ret == ERR_OK) {
471 task.Resolve(engine, engine.CreateUndefined());
472 } else {
473 task.Reject(engine, CreateJsError(engine, ret, "UpdateConnectStatus failed."));
474 }
475 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
476 };
477
478 NativeValue* lastParam = (info.argc <= ARG_COUNT_THREE) ? nullptr : info.argv[ARG_COUNT_THREE];
479 NativeValue* result = nullptr;
480 AsyncTask::Schedule("JsContinuationManager::OnUpdateConnectStatus",
481 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
482 return result;
483 }
484
OnUpdateContinuationState(NativeEngine & engine,NativeCallbackInfo & info)485 NativeValue* JsContinuationManager::OnUpdateContinuationState(NativeEngine &engine, NativeCallbackInfo &info)
486 {
487 HILOGD("called.");
488 int32_t token = -1;
489 std::string deviceId;
490 DeviceConnectStatus deviceConnectStatus;
491 std::string errInfo = [this, &engine, &info, &token, &deviceId, &deviceConnectStatus, &errInfo]() -> std::string {
492 if (info.argc != ARG_COUNT_THREE && info.argc != ARG_COUNT_FOUR) {
493 return "Parameter error. The type of \"number of parameters\" must be 3 or 4";
494 }
495 if (!ConvertFromJsValue(engine, info.argv[0], token)) {
496 return "Parameter error. The type of \"token\" must be number";
497 }
498 if (!ConvertFromJsValue(engine, info.argv[ARG_COUNT_ONE], deviceId) || deviceId.empty()) {
499 return "Parameter error. The type of \"deviceId\" must be string and not empty";
500 }
501 deviceConnectStatus = DeviceConnectStatus::IDLE;
502 if (!ConvertFromJsValue(engine, info.argv[ARG_COUNT_TWO], deviceConnectStatus)) {
503 return "Parameter error. The type of \"status\" must be DeviceConnectState";
504 }
505 if (static_cast<int32_t>(deviceConnectStatus) < static_cast<int32_t>(DeviceConnectStatus::IDLE) ||
506 static_cast<int32_t>(deviceConnectStatus) > static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)) {
507 HILOGE("deviceConnectStatus is invalid");
508 return "Parameter error. The type of \"status\" must be DeviceConnectState";
509 }
510 return std::string();
511 } ();
512 if (!errInfo.empty()) {
513 HILOGE("%{public}s", errInfo.c_str());
514 napi_throw(reinterpret_cast<napi_env>(&engine),
515 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), PARAMETER_CHECK_FAILED, errInfo));
516 return engine.CreateUndefined();
517 }
518 AsyncTask::CompleteCallback complete =
519 [this, token, deviceId, deviceConnectStatus](NativeEngine &engine, AsyncTask &task, int32_t status) {
520 napi_handle_scope scope = nullptr;
521 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
522 if (scope == nullptr) {
523 return;
524 }
525
526 int32_t errCode = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
527 token, deviceId, deviceConnectStatus);
528 if (errCode == ERR_OK) {
529 task.Resolve(engine, engine.CreateNull());
530 } else {
531 errCode = ErrorCodeReturn(errCode);
532 task.Reject(engine, CreateJsError(engine, errCode, ErrorMessageReturn(errCode)));
533 }
534
535 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
536 };
537
538 NativeValue* lastParam = (info.argc == ARG_COUNT_THREE) ? nullptr : info.argv[ARG_COUNT_THREE];
539 NativeValue* result = nullptr;
540 AsyncTask::Schedule("JsContinuationManager::OnUpdateContinuationState",
541 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
542 return result;
543 }
544
OnStartDeviceManager(NativeEngine & engine,NativeCallbackInfo & info)545 NativeValue *JsContinuationManager::OnStartDeviceManager(NativeEngine &engine, NativeCallbackInfo &info)
546 {
547 HILOGD("called.");
548 int32_t errCode = 0;
549 if (info.argc < ARG_COUNT_ONE) {
550 HILOGE("Params not match");
551 errCode = ERR_NOT_OK;
552 }
553 int32_t token = -1;
554 if (!errCode && !ConvertFromJsValue(engine, info.argv[0], token)) {
555 HILOGE("Parse token failed");
556 errCode = ERR_NOT_OK;
557 }
558 decltype(info.argc) unwrapArgc = ARG_COUNT_ONE;
559 std::shared_ptr<ContinuationExtraParams> continuationExtraParams = std::make_shared<ContinuationExtraParams>();
560 if (info.argc > ARG_COUNT_ONE && info.argv[ARG_COUNT_ONE]->TypeOf() == NATIVE_OBJECT) {
561 HILOGI("startDeviceManager options is used.");
562 if (!UnWrapContinuationExtraParams(reinterpret_cast<napi_env>(&engine),
563 reinterpret_cast<napi_value>(info.argv[ARG_COUNT_ONE]), continuationExtraParams)) {
564 HILOGE("Parse continuationExtraParams failed");
565 errCode = ERR_NOT_OK;
566 }
567 unwrapArgc++;
568 }
569 AsyncTask::CompleteCallback complete =
570 [token, continuationExtraParams, unwrapArgc, errCode](NativeEngine &engine, AsyncTask &task, int32_t status) {
571 napi_handle_scope scope = nullptr;
572 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
573 if (scope == nullptr) {
574 return;
575 }
576
577 if (errCode != 0) {
578 task.Reject(engine, CreateJsError(engine, errCode, "Invalidate params."));
579 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
580 return;
581 }
582 int32_t ret = (unwrapArgc == ARG_COUNT_ONE) ?
583 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token) :
584 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
585 if (ret == ERR_OK) {
586 task.Resolve(engine, engine.CreateUndefined());
587 } else {
588 task.Reject(engine, CreateJsError(engine, ret, "StartDeviceManager failed."));
589 }
590
591 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
592 };
593
594 NativeValue* lastParam = (info.argc <= unwrapArgc) ? nullptr : info.argv[unwrapArgc];
595 NativeValue* result = nullptr;
596 AsyncTask::Schedule("JsContinuationManager::OnStartDeviceManager",
597 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
598 return result;
599 }
600
OnStartContinuationDeviceManager(NativeEngine & engine,NativeCallbackInfo & info)601 NativeValue* JsContinuationManager::OnStartContinuationDeviceManager(NativeEngine &engine, NativeCallbackInfo &info)
602 {
603 HILOGD("called.");
604 int32_t token = -1;
605 decltype(info.argc) unwrapArgc = ARG_COUNT_ONE;
606 std::shared_ptr<ContinuationExtraParams> continuationExtraParams;
607 std::string errInfo = [this, &engine, &info, &token, & unwrapArgc, &continuationExtraParams]() -> std::string {
608 if (info.argc < ARG_COUNT_ONE || info.argc > ARG_COUNT_THREE) {
609 return "Parameter error. The type of \"number of parameters\" must be greater than 1 and less than 4";
610 }
611 if (!ConvertFromJsValue(engine, info.argv[0], token)) {
612 return "Parameter error. The type of \"token\" must be number";
613 }
614 continuationExtraParams = std::make_shared<ContinuationExtraParams>();
615 if (info.argc > ARG_COUNT_ONE && info.argv[ARG_COUNT_ONE]->TypeOf() == NATIVE_OBJECT) {
616 HILOGI("StartContinuationDeviceManager options is used.");
617 if (!UnWrapContinuationExtraParams(reinterpret_cast<napi_env>(&engine),
618 reinterpret_cast<napi_value>(info.argv[ARG_COUNT_ONE]), continuationExtraParams)) {
619 return "Parameter error. The type of \"options\" must be ContinuationExtraParams";
620 }
621 unwrapArgc++;
622 }
623 return std::string();
624 } ();
625 if (!errInfo.empty()) {
626 HILOGE("%{public}s", errInfo.c_str());
627 napi_throw(reinterpret_cast<napi_env>(&engine),
628 GenerateBusinessError(reinterpret_cast<napi_env>(&engine), PARAMETER_CHECK_FAILED, errInfo));
629 return engine.CreateUndefined();
630 }
631 AsyncTask::CompleteCallback complete =
632 [this, token, continuationExtraParams, unwrapArgc](NativeEngine &engine, AsyncTask &task, int32_t status) {
633 napi_handle_scope scope = nullptr;
634 napi_open_handle_scope(reinterpret_cast<napi_env>(&engine), &scope);
635 if (scope == nullptr) {
636 return;
637 }
638
639 int32_t errCode = (unwrapArgc == ARG_COUNT_ONE) ?
640 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token) :
641 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
642 if (errCode == ERR_OK) {
643 task.Resolve(engine, engine.CreateNull());
644 } else {
645 errCode = ErrorCodeReturn(errCode);
646 task.Reject(engine, CreateJsError(engine, errCode, ErrorMessageReturn(errCode)));
647 }
648
649 napi_close_handle_scope(reinterpret_cast<napi_env>(&engine), scope);
650 };
651
652 NativeValue* lastParam = (info.argc <= unwrapArgc) ? nullptr : info.argv[unwrapArgc];
653 NativeValue* result = nullptr;
654 AsyncTask::Schedule("JsContinuationManager::OnStartContinuationDeviceManager",
655 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
656 return result;
657 }
658
OnInitDeviceConnectStateObject(NativeEngine & engine,NativeCallbackInfo & info)659 NativeValue *JsContinuationManager::OnInitDeviceConnectStateObject(NativeEngine &engine, NativeCallbackInfo &info)
660 {
661 napi_value object;
662 napi_env env = reinterpret_cast<napi_env>(&engine);
663 NAPI_CALL(env, napi_create_object(env, &object));
664
665 NAPI_CALL(env, SetEnumItem(env, object, "IDLE",
666 static_cast<int32_t>(DeviceConnectStatus::IDLE)));
667 NAPI_CALL(env, SetEnumItem(env, object, "CONNECTING",
668 static_cast<int32_t>(DeviceConnectStatus::CONNECTING)));
669 NAPI_CALL(env, SetEnumItem(env, object, "CONNECTED",
670 static_cast<int32_t>(DeviceConnectStatus::CONNECTED)));
671 NAPI_CALL(env, SetEnumItem(env, object, "DISCONNECTING",
672 static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)));
673
674 return reinterpret_cast<NativeValue*>(object);
675 }
676
OnInitContinuationModeObject(NativeEngine & engine,NativeCallbackInfo & info)677 NativeValue *JsContinuationManager::OnInitContinuationModeObject(NativeEngine &engine, NativeCallbackInfo &info)
678 {
679 napi_value object;
680 napi_env env = reinterpret_cast<napi_env>(&engine);
681 NAPI_CALL(env, napi_create_object(env, &object));
682
683 NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_SINGLE",
684 static_cast<int32_t>(ContinuationMode::COLLABORATION_SINGLE)));
685 NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_MULTIPLE",
686 static_cast<int32_t>(ContinuationMode::COLLABORATION_MUTIPLE)));
687
688 return reinterpret_cast<NativeValue*>(object);
689 }
690
SetEnumItem(const napi_env & env,napi_value object,const char * name,int32_t value)691 napi_status JsContinuationManager::SetEnumItem(const napi_env& env, napi_value object, const char* name, int32_t value)
692 {
693 napi_status status;
694 napi_value itemName;
695 napi_value itemValue;
696
697 NAPI_CALL_BASE(env, status = napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName), status);
698 NAPI_CALL_BASE(env, status = napi_create_int32(env, value, &itemValue), status);
699 NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemName, itemValue), status);
700 NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemValue, itemName), status);
701
702 return napi_ok;
703 }
704
IsCallbackValid(NativeValue * listenerObj)705 bool JsContinuationManager::IsCallbackValid(NativeValue* listenerObj)
706 {
707 if (listenerObj == nullptr) {
708 HILOGE("listenerObj is nullptr");
709 return false;
710 }
711 if (!listenerObj->IsCallable()) {
712 HILOGE("listenerObj is not callable");
713 return false;
714 }
715 return true;
716 }
717
IsCallbackRegistered(int32_t token,const std::string & cbType)718 bool JsContinuationManager::IsCallbackRegistered(int32_t token, const std::string& cbType)
719 {
720 if (jsCbMap_.empty() || jsCbMap_.find(token) == jsCbMap_.end()) {
721 HILOGE("token %{public}d not registered callback!", token);
722 return false;
723 }
724 if (jsCbMap_[token].empty() || jsCbMap_[token].find(cbType) == jsCbMap_[token].end()) {
725 HILOGE("cbType %{public}s not registered callback!", cbType.c_str());
726 return false;
727 }
728 HILOGI("callback already registered, token: %{public}d, cbType %{public}s", token, cbType.c_str());
729 return true;
730 }
731
UnWrapContinuationExtraParams(const napi_env & env,const napi_value & options,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)732 bool JsContinuationManager::UnWrapContinuationExtraParams(const napi_env& env, const napi_value& options,
733 std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
734 {
735 HILOGD("called.");
736 if (!IsTypeForNapiValue(env, options, napi_object)) {
737 HILOGE("options is invalid.");
738 return false;
739 }
740 std::vector<std::string> deviceTypes;
741 if (UnwrapStringArrayByPropertyName(env, options, "deviceType", deviceTypes)) {
742 continuationExtraParams->SetDeviceType(deviceTypes);
743 }
744 std::string targetBundle("");
745 if (UnwrapStringByPropertyName(env, options, "targetBundle", targetBundle)) {
746 continuationExtraParams->SetTargetBundle(targetBundle);
747 }
748 std::string description("");
749 if (UnwrapStringByPropertyName(env, options, "description", description)) {
750 continuationExtraParams->SetDescription(description);
751 }
752 nlohmann::json filter;
753 if (!UnwrapJsonByPropertyName(env, options, "filter", filter)) {
754 return false;
755 }
756 continuationExtraParams->SetFilter(filter.dump());
757 int32_t continuationMode = 0;
758 if (UnwrapInt32ByPropertyName(env, options, "continuationMode", continuationMode)) {
759 continuationExtraParams->SetContinuationMode(static_cast<ContinuationMode>(continuationMode));
760 }
761 nlohmann::json authInfo;
762 if (UnwrapJsonByPropertyName(env, options, "authInfo", authInfo)) {
763 continuationExtraParams->SetAuthInfo(authInfo.dump());
764 }
765 return true;
766 }
767
UnwrapJsonByPropertyName(const napi_env & env,const napi_value & param,const std::string & field,nlohmann::json & jsonObj)768 bool JsContinuationManager::UnwrapJsonByPropertyName(const napi_env& env, const napi_value& param,
769 const std::string& field, nlohmann::json& jsonObj)
770 {
771 HILOGD("called.");
772 if (!IsTypeForNapiValue(env, param, napi_object)) {
773 HILOGE("param is invalid.");
774 return false;
775 }
776 napi_value jsonField = nullptr;
777 napi_get_named_property(env, param, field.c_str(), &jsonField);
778 napi_valuetype jsonFieldType = napi_undefined;
779 napi_typeof(env, jsonField, &jsonFieldType);
780 if (jsonFieldType != napi_object && jsonFieldType != napi_undefined) {
781 HILOGE("field: %{public}s is invalid json.", field.c_str());
782 return false;
783 }
784 napi_value jsProNameList = nullptr;
785 uint32_t jsProCount = 0;
786 napi_get_property_names(env, jsonField, &jsProNameList);
787 napi_get_array_length(env, jsProNameList, &jsProCount);
788 if (!PraseJson(env, jsonField, jsProNameList, jsProCount, jsonObj)) {
789 HILOGE("PraseJson failed.");
790 return false;
791 }
792 return true;
793 }
794
PraseJson(const napi_env & env,const napi_value & jsonField,const napi_value & jsProNameList,uint32_t jsProCount,nlohmann::json & jsonObj)795 bool JsContinuationManager::PraseJson(const napi_env& env, const napi_value& jsonField,
796 const napi_value& jsProNameList, uint32_t jsProCount, nlohmann::json& jsonObj)
797 {
798 napi_value jsProName = nullptr;
799 napi_value jsProValue = nullptr;
800 napi_valuetype jsValueType = napi_undefined;
801 if (jsProCount > MAX_JSPROCOUNT) {
802 HILOGE("value of jsProCount is larger than MAX_JSPROCOUNT");
803 return false;
804 }
805 for (uint32_t index = 0; index < jsProCount; index++) {
806 napi_get_element(env, jsProNameList, index, &jsProName);
807 std::string strProName = UnwrapStringFromJS(env, jsProName);
808 napi_get_named_property(env, jsonField, strProName.c_str(), &jsProValue);
809 napi_typeof(env, jsProValue, &jsValueType);
810 switch (jsValueType) {
811 case napi_string: {
812 std::string elementValue = UnwrapStringFromJS(env, jsProValue);
813 HILOGI("Property name=%{public}s, string, value=%{public}s", strProName.c_str(), elementValue.c_str());
814 jsonObj[strProName] = elementValue;
815 break;
816 }
817 case napi_boolean: {
818 bool elementValue = false;
819 napi_get_value_bool(env, jsProValue, &elementValue);
820 HILOGI("Property name=%{public}s, boolean, value=%{public}d.", strProName.c_str(), elementValue);
821 jsonObj[strProName] = elementValue;
822 break;
823 }
824 case napi_number: {
825 int32_t elementValue = 0;
826 if (napi_get_value_int32(env, jsProValue, &elementValue) != napi_ok) {
827 HILOGE("Property name=%{public}s, Property int32_t parse error", strProName.c_str());
828 } else {
829 HILOGI("Property name=%{public}s, number, value=%{public}d.", strProName.c_str(), elementValue);
830 jsonObj[strProName] = elementValue;
831 }
832 break;
833 }
834 default: {
835 HILOGE("Property name=%{public}s, value type not support.", strProName.c_str());
836 break;
837 }
838 }
839 }
840 return true;
841 }
842
ErrorCodeReturn(int32_t code)843 int32_t JsContinuationManager::ErrorCodeReturn(int32_t code)
844 {
845 switch (code) {
846 case DMS_PERMISSION_DENIED:
847 return PERMISSION_DENIED;
848 case ERR_NULL_OBJECT:
849 return SYSTEM_WORK_ABNORMALLY;
850 case ERR_FLATTEN_OBJECT:
851 return SYSTEM_WORK_ABNORMALLY;
852 case CONNECT_ABILITY_FAILED:
853 return SYSTEM_WORK_ABNORMALLY;
854 case INVALID_CONTINUATION_MODE:
855 return PARAMETER_CHECK_FAILED;
856 case UNKNOWN_CALLBACK_TYPE:
857 return PARAMETER_CHECK_FAILED;
858 case INVALID_CONNECT_STATUS:
859 return PARAMETER_CHECK_FAILED;
860 case CALLBACK_HAS_NOT_REGISTERED:
861 return CALLBACK_TOKEN_UNREGISTERED;
862 case TOKEN_HAS_NOT_REGISTERED:
863 return CALLBACK_TOKEN_UNREGISTERED;
864 case REGISTER_EXCEED_MAX_TIMES:
865 return OVER_MAX_REGISTERED_TIMES;
866 case CALLBACK_HAS_REGISTERED:
867 return REPEATED_REGISTRATION;
868 default:
869 return SYSTEM_WORK_ABNORMALLY;
870 };
871 }
872
ErrorMessageReturn(int32_t code)873 std::string JsContinuationManager::ErrorMessageReturn(int32_t code)
874 {
875 switch (code) {
876 case PARAMETER_CHECK_FAILED:
877 return "The parameter check failed.";
878 case SYSTEM_WORK_ABNORMALLY:
879 return "The system ability works abnormally.";
880 case CALLBACK_TOKEN_UNREGISTERED:
881 return "The specified token or callback is not registered.";
882 case OVER_MAX_REGISTERED_TIMES:
883 return "The number of token registration times has reached the upper limit.";
884 case REPEATED_REGISTRATION:
885 return "The specified callback has been registered.";
886 default:
887 return "The system ability works abnormally.";
888 };
889 }
890
GenerateBusinessError(const napi_env & env,int32_t errCode,const std::string & errMsg)891 napi_value JsContinuationManager::GenerateBusinessError(const napi_env &env, int32_t errCode, const std::string &errMsg)
892 {
893 napi_value code = nullptr;
894 napi_create_int32(env, errCode, &code);
895 napi_value msg = nullptr;
896 napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msg);
897 napi_value businessError = nullptr;
898 napi_create_error(env, nullptr, msg, &businessError);
899 napi_set_named_property(env, businessError, CODE_KEY_NAME.c_str(), code);
900 return businessError;
901 }
902
JsContinuationManagerInit(NativeEngine * engine,NativeValue * exportObj)903 NativeValue* JsContinuationManagerInit(NativeEngine* engine, NativeValue* exportObj)
904 {
905 HILOGD("called.");
906 if (engine == nullptr || exportObj == nullptr) {
907 HILOGE("Invalid input parameters");
908 return nullptr;
909 }
910
911 NativeObject* object = ConvertNativeValueTo<NativeObject>(exportObj);
912 if (object == nullptr) {
913 HILOGE("convertNativeValueTo result is nullptr.");
914 return nullptr;
915 }
916
917 JsContinuationManager* jsContinuationManager = new JsContinuationManager();
918 object->SetNativePointer(jsContinuationManager, JsContinuationManager::Finalizer, nullptr);
919
920 const char *moduleName = "JsContinuationManager";
921 BindNativeFunction(*engine, *object, "register", moduleName, JsContinuationManager::Register);
922 BindNativeFunction(*engine, *object, "unregister", moduleName, JsContinuationManager::Unregister);
923 BindNativeFunction(*engine, *object, "on", moduleName, JsContinuationManager::RegisterDeviceSelectionCallback);
924 BindNativeFunction(*engine, *object, "off", moduleName, JsContinuationManager::UnregisterDeviceSelectionCallback);
925 BindNativeFunction(*engine, *object, "updateConnectStatus", moduleName, JsContinuationManager::UpdateConnectStatus);
926 BindNativeFunction(*engine, *object, "startDeviceManager", moduleName, JsContinuationManager::StartDeviceManager);
927 BindNativeProperty(*object, "DeviceConnectState", JsContinuationManager::InitDeviceConnectStateObject);
928 BindNativeProperty(*object, "ContinuationMode", JsContinuationManager::InitContinuationModeObject);
929 BindNativeFunction(*engine, *object, "registerContinuation", moduleName,
930 JsContinuationManager::RegisterContinuation);
931 BindNativeFunction(*engine, *object, "unregisterContinuation", moduleName,
932 JsContinuationManager::UnregisterContinuation);
933 BindNativeFunction(*engine, *object, "updateContinuationState", moduleName,
934 JsContinuationManager::UpdateContinuationState);
935 BindNativeFunction(*engine, *object, "startContinuationDeviceManager", moduleName,
936 JsContinuationManager::StartContinuationDeviceManager);
937
938 return engine->CreateUndefined();
939 }
940 } // namespace DistributedSchedule
941 } // namespace OHOS