• 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 "js_work_scheduler_extension.h"
17 
18 #include <string>
19 
20 #include "runtime.h"
21 #include "js_runtime.h"
22 #include "js_runtime_utils.h"
23 #include "work_scheduler_extension.h"
24 #include "js_work_scheduler_extension_context.h"
25 #include "work_scheduler_stub_imp.h"
26 #include "hitrace_meter.h"
27 
28 namespace OHOS {
29 namespace WorkScheduler {
30 const int32_t INVALID_VALUE = -1;
31 
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)32 JsWorkSchedulerExtension* JsWorkSchedulerExtension::Create(const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
33 {
34     return new JsWorkSchedulerExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
35 }
36 
JsWorkSchedulerExtension(AbilityRuntime::JsRuntime & jsRuntime)37 JsWorkSchedulerExtension::JsWorkSchedulerExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsWorkSchedulerExtension()38 JsWorkSchedulerExtension::~JsWorkSchedulerExtension()
39 {
40     WS_HILOGD("Js WorkScheduler extension destructor.");
41     auto context = GetContext();
42     if (context) {
43         context->Unbind();
44     }
45 
46     jsRuntime_.FreeNativeReference(std::move(jsObj_));
47     jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
48 }
49 
DetachCallbackFunc(napi_env env,void * value,void *)50 inline void *DetachCallbackFunc(napi_env env, void *value, void *)
51 {
52     return value;
53 }
54 
AttachWorkSchedulerExtensionContext(napi_env env,void * value,void *)55 napi_value AttachWorkSchedulerExtensionContext(napi_env env, void *value, void *)
56 {
57     WS_HILOGI("AttachWorkSchedulerExtensionContext");
58     if (value == nullptr) {
59         WS_HILOGE("invalid parameter.");
60         return nullptr;
61     }
62     auto ptr = reinterpret_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(value)->lock();
63     if (ptr == nullptr) {
64         WS_HILOGE("invalid context.");
65         return nullptr;
66     }
67     napi_value object = CreateJsWorkSchedulerExtensionContext(env, ptr);
68     auto loadObject = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env,
69         "application.WorkSchedulerExtensionContext", &object, 1);
70     if (loadObject == nullptr) {
71         return nullptr;
72     }
73     napi_value contextObj = loadObject->GetNapiValue();
74     napi_coerce_to_native_binding_object(env, contextObj, DetachCallbackFunc,
75         AttachWorkSchedulerExtensionContext, value, nullptr);
76     auto workContext = new (std::nothrow) std::weak_ptr<WorkSchedulerExtensionContext>(ptr);
77     if (workContext == nullptr) {
78         WS_HILOGE("init WorkSchedulerExtensionContext failed.");
79         return nullptr;
80     }
81     napi_status status = napi_wrap(env, contextObj, workContext,
82         [](napi_env env, void *data, void *) {
83             WS_HILOGI("Finalizer for weak_ptr WorkSchedulerExtensionContext is called");
84             delete static_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(data);
85         }, nullptr, nullptr);
86     if (status != napi_ok) {
87         WS_HILOGE("WorkSchedulerExtension failed to wrap the context");
88         delete workContext;
89         workContext = nullptr;
90         return nullptr;
91     }
92 
93     return contextObj;
94 }
95 
Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord> & record,const std::shared_ptr<AppExecFwk::OHOSApplication> & application,std::shared_ptr<AppExecFwk::AbilityHandler> & handler,const sptr<IRemoteObject> & token)96 void JsWorkSchedulerExtension::Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord>& record,
97     const std::shared_ptr<AppExecFwk::OHOSApplication>& application,
98     std::shared_ptr<AppExecFwk::AbilityHandler>& handler,
99     const sptr<IRemoteObject>& token)
100 {
101     WS_HILOGD("enter");
102     WorkSchedulerExtension::Init(record, application, handler, token);
103     std::string srcPath = "";
104     GetSrcPath(srcPath);
105     if (srcPath.empty()) {
106         WS_HILOGE("JsWorkSchedulerExtension Failed to get srcPath");
107         return;
108     }
109 
110     std::string moduleName(Extension::abilityInfo_->moduleName);
111     moduleName.append("::").append(abilityInfo_->name);
112     WS_HILOGD("moduleName:%{public}s, srcPath:%{private}s.", moduleName.c_str(), srcPath.c_str());
113     AbilityRuntime::HandleScope handleScope(jsRuntime_);
114     napi_env env = jsRuntime_.GetNapiEnv();
115 
116     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
117         abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE, false, abilityInfo_->srcEntrance);
118     if (jsObj_ == nullptr) {
119         WS_HILOGE("WorkSchedulerExtension Failed to get jsObj_");
120         return;
121     }
122     napi_value obj = jsObj_->GetNapiValue();
123     if (obj == nullptr) {
124         WS_HILOGE("WorkSchedulerExtension Failed to get JsWorkSchedulerExtension object");
125         return;
126     }
127     BindContext(env, obj);
128 
129     WS_HILOGD("end.");
130 }
131 
BindContext(napi_env env,napi_value obj)132 void JsWorkSchedulerExtension::BindContext(napi_env env, napi_value obj)
133 {
134     auto context = GetContext();
135     if (context == nullptr) {
136         WS_HILOGE("WorkSchedulerExtension Failed to get context");
137         return;
138     }
139     napi_value contextObj = CreateJsWorkSchedulerExtensionContext(env, context);
140     shellContextRef_ = jsRuntime_.LoadSystemModule("application.WorkSchedulerExtensionContext",
141         &contextObj, 1);
142     if (shellContextRef_ == nullptr) {
143         WS_HILOGE("WorkSchedulerExtension Failed to get shellContextRef_");
144         return;
145     }
146     contextObj = shellContextRef_->GetNapiValue();
147 
148     auto workContext = new (std::nothrow) std::weak_ptr<WorkSchedulerExtensionContext>(context);
149     if (workContext == nullptr) {
150         WS_HILOGE("init WorkSchedulerExtensionContext failed.");
151         return;
152     }
153     napi_coerce_to_native_binding_object(env, contextObj, DetachCallbackFunc,
154         AttachWorkSchedulerExtensionContext, workContext, nullptr);
155     WS_HILOGI("JsWorkSchedulerExtension init bind and set property.");
156     context->Bind(jsRuntime_, shellContextRef_.get());
157     napi_set_named_property(env, obj, "context", contextObj);
158     WS_HILOGI("Set JsWorkSchedulerExtension context pointer is nullptr or not:%{public}d",
159         context.get() == nullptr);
160 
161     napi_status status = napi_wrap(env, contextObj, workContext,
162         [](napi_env env, void* data, void*) {
163             WS_HILOGI("Finalizer for weak_ptr WorkSchedulerExtensionContext is called");
164             delete static_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(data);
165         }, nullptr, nullptr);
166     if (status != napi_ok) {
167         WS_HILOGE("WorkSchedulerExtension failed to wrap the context");
168         delete workContext;
169         workContext = nullptr;
170     }
171 }
172 
OnStart(const AAFwk::Want & want)173 void JsWorkSchedulerExtension::OnStart(const AAFwk::Want& want)
174 {
175     WS_HILOGD("begin");
176     AbilityRuntime::Extension::OnStart(want);
177 }
178 
OnStop()179 void JsWorkSchedulerExtension::OnStop()
180 {
181     AbilityRuntime::Extension::OnStop();
182     WS_HILOGD("end.");
183 }
184 
OnConnect(const AAFwk::Want & want)185 __attribute__((no_sanitize("cfi"))) sptr<IRemoteObject> JsWorkSchedulerExtension::OnConnect(const AAFwk::Want& want)
186 {
187     AbilityRuntime::Extension::OnConnect(want);
188     WS_HILOGD("begin.");
189     sptr<WorkSchedulerStubImp> remoteObject = new (std::nothrow) WorkSchedulerStubImp(
190         std::static_pointer_cast<JsWorkSchedulerExtension>(shared_from_this()));
191     if (remoteObject == nullptr) {
192         WS_HILOGE("OnConnect get null");
193         return remoteObject;
194     }
195     WS_HILOGD("end.");
196     return remoteObject->AsObject();
197 }
198 
OnDisconnect(const AAFwk::Want & want)199 void JsWorkSchedulerExtension::OnDisconnect(const AAFwk::Want& want)
200 {
201     WS_HILOGD("begin.");
202     AbilityRuntime::Extension::OnDisconnect(want);
203 }
204 
SetCommonInfo(napi_env env,napi_value workInfoData,int32_t workId,const std::string & bundleName,const std::string & abilityName)205 void SetCommonInfo(napi_env env, napi_value workInfoData, int32_t workId,
206     const std::string& bundleName, const std::string& abilityName)
207 {
208     napi_value workIdValue;
209     napi_create_int32(env, workId, &workIdValue);
210     napi_set_named_property(env, workInfoData, "workId", workIdValue);
211 
212     napi_value bundleNameValue;
213     napi_create_string_utf8(env, bundleName.c_str(), bundleName.size(), &bundleNameValue);
214     napi_set_named_property(env, workInfoData, "bundleName", bundleNameValue);
215 
216     napi_value abilityNameValue;
217     napi_create_string_utf8(env, abilityName.c_str(), abilityName.size(), &abilityNameValue);
218     napi_set_named_property(env, workInfoData, "abilityName", abilityNameValue);
219 }
220 
SetPersistedInfo(napi_env env,napi_value workInfoData,bool isPersisted)221 void SetPersistedInfo(napi_env env, napi_value workInfoData, bool isPersisted)
222 {
223     napi_value isPersistedValue;
224     napi_get_boolean(env, isPersisted, &isPersistedValue);
225     napi_set_named_property(env, workInfoData, "isPersisted", isPersistedValue);
226 }
227 
SetExtrasInfo(napi_env env,napi_value workInfoData,bool getExtrasRet,const std::string & extrasStr)228 void SetExtrasInfo(napi_env env, napi_value workInfoData, bool getExtrasRet, const std::string& extrasStr)
229 {
230     if (getExtrasRet) {
231         napi_value parametersValue;
232         napi_create_string_utf8(env, extrasStr.c_str(), extrasStr.size(), &parametersValue);
233         napi_set_named_property(env, workInfoData, "parameters", parametersValue);
234     }
235 }
236 
SetNetWorkInfo(napi_env env,napi_value workInfoData,WorkCondition::Network networkType)237 void SetNetWorkInfo(napi_env env, napi_value workInfoData, WorkCondition::Network networkType)
238 {
239     if (networkType != WorkCondition::Network::NETWORK_UNKNOWN) {
240         napi_value networkTypeValue;
241         napi_create_int32(env, networkType, &networkTypeValue);
242         napi_set_named_property(env, workInfoData, "networkType", networkTypeValue);
243     }
244 }
245 
SetChargerTypeInfo(napi_env env,napi_value workInfoData,WorkCondition::Charger charger)246 void SetChargerTypeInfo(napi_env env, napi_value workInfoData, WorkCondition::Charger charger)
247 {
248     if (charger != WorkCondition::Charger::CHARGING_UNKNOWN) {
249         if (charger == WorkCondition::Charger::CHARGING_UNPLUGGED) {
250             napi_value isChargingValue;
251             napi_get_boolean(env, false, &isChargingValue);
252             napi_set_named_property(env, workInfoData, "isCharging", isChargingValue);
253         } else {
254             napi_value isChargingValue;
255             napi_get_boolean(env, true, &isChargingValue);
256             napi_set_named_property(env, workInfoData, "isCharging", isChargingValue);
257 
258             napi_value chargerTypeValue;
259             napi_create_int32(env, charger, &chargerTypeValue);
260             napi_set_named_property(env, workInfoData, "chargerType", chargerTypeValue);
261         }
262     }
263 }
264 
SetBatteryInfo(napi_env env,napi_value workInfoData,int32_t batteryLevel,WorkCondition::BatteryStatus batteryStatus)265 void SetBatteryInfo(napi_env env, napi_value workInfoData, int32_t batteryLevel,
266     WorkCondition::BatteryStatus batteryStatus)
267 {
268     if (batteryLevel != INVALID_VALUE) {
269         napi_value batteryLevelValue;
270         napi_create_int32(env, batteryLevel, &batteryLevelValue);
271         napi_set_named_property(env, workInfoData, "batteryLevel", batteryLevelValue);
272     }
273     if (batteryStatus != WorkCondition::BatteryStatus::BATTERY_UNKNOWN) {
274         napi_value batteryStatusValue;
275         napi_create_int32(env, batteryStatus, &batteryStatusValue);
276         napi_set_named_property(env, workInfoData, "batteryStatus", batteryStatusValue);
277     }
278 }
279 
SetStorageInfo(napi_env env,napi_value workInfoData,WorkCondition::Storage storageLevel)280 void SetStorageInfo(napi_env env, napi_value workInfoData, WorkCondition::Storage storageLevel)
281 {
282     if (storageLevel != WorkCondition::Storage::STORAGE_UNKNOWN) {
283         napi_value storageLevelValue;
284         napi_create_int32(env, storageLevel, &storageLevelValue);
285         napi_set_named_property(env, workInfoData, "storageRequest", storageLevelValue);
286     }
287 }
288 
SetRepeatInfo(napi_env env,napi_value workInfoData,bool isRepeat,uint32_t timeInterval,int32_t cycleCount)289 void SetRepeatInfo(napi_env env, napi_value workInfoData, bool isRepeat,
290     uint32_t timeInterval, int32_t cycleCount)
291 {
292     if (isRepeat) {
293         napi_value isRepeatValue;
294         napi_get_boolean(env, true, &isRepeatValue);
295         napi_set_named_property(env, workInfoData, "isRepeat", isRepeatValue);
296 
297         napi_value repeatCycleTimeValue;
298         napi_create_uint32(env, timeInterval, &repeatCycleTimeValue);
299         napi_set_named_property(env, workInfoData, "repeatCycleTime", repeatCycleTimeValue);
300     } else {
301         napi_value repeatCycleTimeValue;
302         napi_create_uint32(env, timeInterval, &repeatCycleTimeValue);
303         napi_set_named_property(env, workInfoData, "repeatCycleTime", repeatCycleTimeValue);
304 
305         napi_value repeatCountValue;
306         napi_create_int32(env, cycleCount, &repeatCountValue);
307         napi_set_named_property(env, workInfoData, "repeatCount", repeatCountValue);
308     }
309 }
310 
SetDeepIdleInfo(napi_env env,napi_value workInfoData,WorkCondition::DeepIdle value)311 void SetDeepIdleInfo(napi_env env, napi_value workInfoData, WorkCondition::DeepIdle value)
312 {
313     if (value == WorkCondition::DeepIdle::DEEP_IDLE_UNKNOWN) {
314         return;
315     }
316     napi_value isDeepIdle;
317     napi_get_boolean(env, (value == WorkCondition::DeepIdle::DEEP_IDLE_IN), &isDeepIdle);
318     napi_set_named_property(env, workInfoData, "isDeepIdle", isDeepIdle);
319 }
320 
CallFuncation(napi_env env,napi_value workInfoData,std::unique_ptr<NativeReference> & jsObj_,const char * functionName)321 bool CallFuncation(napi_env env, napi_value workInfoData,
322     std::unique_ptr<NativeReference> &jsObj_, const char* functionName)
323 {
324     napi_value argv[] = {workInfoData};
325     if (!jsObj_) {
326         WS_HILOGE("WorkSchedulerExtension Not found js");
327         return false;
328     }
329 
330     napi_value value = jsObj_->GetNapiValue();
331     if (value == nullptr) {
332         WS_HILOGE("WorkSchedulerExtension Failed to get WorkSchedulerExtension object");
333         return false;
334     }
335 
336     napi_value method;
337     napi_get_named_property(env, value, functionName, &method);
338     if (method == nullptr) {
339         WS_HILOGE("WorkSchedulerExtension call function %{public}s error, method name is nullptr", functionName);
340         return false;
341     }
342 
343     napi_value callFunctionResult;
344     if (napi_call_function(env, value, method, 1, argv, &callFunctionResult) != napi_ok) {
345         WS_HILOGE("WorkSchedulerExtension call function %{public}s error", functionName);
346         return false;
347     }
348 
349     return true;
350 }
351 
OnWorkStart(WorkInfo & workInfo)352 void JsWorkSchedulerExtension::OnWorkStart(WorkInfo& workInfo)
353 {
354     if (handler_ == nullptr) {
355         return;
356     }
357     WS_HILOGD("begin.");
358     int32_t workId = workInfo.GetWorkId();
359     std::string bundleName = workInfo.GetBundleName();
360     std::string abilityName = workInfo.GetAbilityName();
361     bool isPersisted = workInfo.IsPersisted();
362     WorkCondition::Network networkType = workInfo.GetNetworkType();
363     WorkCondition::Charger charger = workInfo.GetChargerType();
364     int32_t batteryLevel = workInfo.GetBatteryLevel();
365     WorkCondition::BatteryStatus batteryStatus = workInfo.GetBatteryStatus();
366     WorkCondition::Storage storageLevel = workInfo.GetStorageLevel();
367     uint32_t timeInterval = workInfo.GetTimeInterval();
368     bool isRepeat = workInfo.IsRepeat();
369     int32_t cycleCount = workInfo.GetCycleCount();
370     WorkCondition::DeepIdle deepIdleValue = workInfo.GetDeepIdle();
371     std::string extrasStr;
372     bool getExtrasRet = GetExtrasJsonStr(workInfo, extrasStr);
373     WorkSchedulerExtension::OnWorkStart(workInfo);
374     auto task = [=]() {
375         AbilityRuntime::HandleScope handleScope(jsRuntime_);
376         napi_env env = jsRuntime_.GetNapiEnv();
377 
378         napi_value workInfoData;
379         if (napi_create_object(env, &workInfoData) != napi_ok) {
380             WS_HILOGE("WorkSchedulerExtension failed to create workInfoData OnWorkStart");
381             return;
382         }
383 
384         SetCommonInfo(env, workInfoData, workId, bundleName, abilityName);
385         SetExtrasInfo(env, workInfoData, getExtrasRet, extrasStr);
386         SetPersistedInfo(env, workInfoData, isPersisted);
387         SetNetWorkInfo(env, workInfoData, networkType);
388         SetChargerTypeInfo(env, workInfoData, charger);
389         SetBatteryInfo(env, workInfoData, batteryLevel, batteryStatus);
390         SetStorageInfo(env, workInfoData, storageLevel);
391         SetDeepIdleInfo(env, workInfoData, deepIdleValue);
392 
393         if (timeInterval > 0) {
394             SetRepeatInfo(env, workInfoData, isRepeat, timeInterval, cycleCount);
395         }
396 
397         HitraceScoped traceScoped(HITRACE_TAG_OHOS, "JsWorkSchedulerExtension::onWorkStart");
398         if (!CallFuncation(env, workInfoData, jsObj_, "onWorkStart")) {
399             return;
400         }
401     };
402     handler_->PostTask(task);
403 }
404 
OnWorkStop(WorkInfo & workInfo)405 void JsWorkSchedulerExtension::OnWorkStop(WorkInfo& workInfo)
406 {
407     if (handler_ == nullptr) {
408         return;
409     }
410     WS_HILOGD("begin.");
411     int32_t workId = workInfo.GetWorkId();
412     std::string bundleName = workInfo.GetBundleName();
413     std::string abilityName = workInfo.GetAbilityName();
414     bool isPersisted = workInfo.IsPersisted();
415     WorkCondition::Network networkType = workInfo.GetNetworkType();
416     WorkCondition::Charger charger = workInfo.GetChargerType();
417     int32_t batteryLevel = workInfo.GetBatteryLevel();
418     WorkCondition::BatteryStatus batteryStatus = workInfo.GetBatteryStatus();
419     WorkCondition::Storage storageLevel = workInfo.GetStorageLevel();
420     uint32_t timeInterval = workInfo.GetTimeInterval();
421     bool isRepeat = workInfo.IsRepeat();
422     int32_t cycleCount = workInfo.GetCycleCount();
423     WorkCondition::DeepIdle deepIdleValue = workInfo.GetDeepIdle();
424     std::string extrasStr;
425     bool getExtrasRet = GetExtrasJsonStr(workInfo, extrasStr);
426     WorkSchedulerExtension::OnWorkStop(workInfo);
427     auto task = [=]() {
428         AbilityRuntime::HandleScope handleScope(jsRuntime_);
429         napi_env env = jsRuntime_.GetNapiEnv();
430 
431         napi_value workInfoData;
432         if (napi_create_object(env, &workInfoData) != napi_ok) {
433             WS_HILOGE("WorkSchedulerExtension failed to create workInfoData OnWorkStop");
434             return;
435         }
436 
437         SetCommonInfo(env, workInfoData, workId, bundleName, abilityName);
438         SetExtrasInfo(env, workInfoData, getExtrasRet, extrasStr);
439         SetPersistedInfo(env, workInfoData, isPersisted);
440         SetNetWorkInfo(env, workInfoData, networkType);
441         SetChargerTypeInfo(env, workInfoData, charger);
442         SetBatteryInfo(env, workInfoData, batteryLevel, batteryStatus);
443         SetStorageInfo(env, workInfoData, storageLevel);
444         SetDeepIdleInfo(env, workInfoData, deepIdleValue);
445 
446         if (timeInterval > 0) {
447             SetRepeatInfo(env, workInfoData, isRepeat, timeInterval, cycleCount);
448         }
449 
450         HitraceScoped traceScoped(HITRACE_TAG_OHOS, "JsWorkSchedulerExtension::onWorkStop");
451         if (!CallFuncation(env, workInfoData, jsObj_, "onWorkStop")) {
452             return;
453         }
454     };
455     handler_->PostTask(task);
456 }
457 
GetSrcPath(std::string & srcPath)458 void JsWorkSchedulerExtension::GetSrcPath(std::string &srcPath)
459 {
460     if (!Extension::abilityInfo_->isStageBasedModel) {
461         /* temporary compatibility api8 + config.json */
462         srcPath.append(Extension::abilityInfo_->package);
463         srcPath.append("/assets/js/");
464         if (!Extension::abilityInfo_->srcPath.empty()) {
465             srcPath.append(Extension::abilityInfo_->srcPath);
466         }
467         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
468         return;
469     }
470 
471     if (!Extension::abilityInfo_->srcEntrance.empty()) {
472         srcPath.append(Extension::abilityInfo_->moduleName + "/");
473         srcPath.append(Extension::abilityInfo_->srcEntrance);
474         srcPath.erase(srcPath.rfind('.'));
475         srcPath.append(".abc");
476     }
477 }
478 
GetExtrasJsonStr(const WorkInfo & workInfo,std::string & extrasStr)479 bool JsWorkSchedulerExtension::GetExtrasJsonStr(const WorkInfo& workInfo, std::string& extrasStr)
480 {
481     std::shared_ptr<AAFwk::WantParams> extras = workInfo.GetExtras();
482     Json::Value extrasJson;
483     if (!extras) {
484         WS_HILOGD("parameter is null.");
485         return false;
486     }
487     auto extrasMap = extras->GetParams();
488     int typeId = INVALID_VALUE;
489     for (auto it : extrasMap) {
490         typeId = AAFwk::WantParams::GetDataType(it.second);
491         if (typeId != INVALID_VALUE) {
492             std::string value = AAFwk::WantParams::GetStringByType(it.second, typeId);
493             extrasJson[it.first] = value;
494         } else {
495             WS_HILOGE("parameters type not supported.");
496         }
497     }
498     Json::StreamWriterBuilder builder;
499     extrasStr = Json::writeString(builder, extrasJson);
500     return true;
501 }
502 } // namespace WorkScheduler
503 } // namespace OHOS
504