• 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 
27 namespace OHOS {
28 namespace WorkScheduler {
29 const int32_t INVALID_VALUE = -1;
30 
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)31 JsWorkSchedulerExtension* JsWorkSchedulerExtension::Create(const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
32 {
33     return new JsWorkSchedulerExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
34 }
35 
JsWorkSchedulerExtension(AbilityRuntime::JsRuntime & jsRuntime)36 JsWorkSchedulerExtension::JsWorkSchedulerExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsWorkSchedulerExtension()37 JsWorkSchedulerExtension::~JsWorkSchedulerExtension()
38 {
39     WS_HILOGD("Js WorkScheduler extension destructor.");
40     auto context = GetContext();
41     if (context) {
42         context->Unbind();
43     }
44 
45     jsRuntime_.FreeNativeReference(std::move(jsObj_));
46     jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
47 }
48 
AttachWorkSchedulerExtensionContext(NativeEngine * engine,void * value,void *)49 NativeValue *AttachWorkSchedulerExtensionContext(NativeEngine *engine, void *value, void *)
50 {
51     WS_HILOGI("AttachWorkSchedulerExtensionContext");
52     if (value == nullptr) {
53         WS_HILOGE("invalid parameter.");
54         return nullptr;
55     }
56     auto ptr = reinterpret_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(value)->lock();
57     if (ptr == nullptr) {
58         WS_HILOGE("invalid context.");
59         return nullptr;
60     }
61     NativeValue *object = CreateJsWorkSchedulerExtensionContext(*engine, ptr);
62     auto contextObj = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(engine,
63         "application.WorkSchedulerExtensionContext", &object, 1)->Get();
64     NativeObject *nObject = AbilityRuntime::ConvertNativeValueTo<NativeObject>(contextObj);
65     nObject->ConvertToNativeBindingObject(engine, AbilityRuntime::DetachCallbackFunc,
66         AttachWorkSchedulerExtensionContext, value, nullptr);
67     auto workContext = new (std::nothrow) std::weak_ptr<WorkSchedulerExtensionContext>(ptr);
68     nObject->SetNativePointer(workContext,
69         [](NativeEngine *, void *data, void *) {
70             WS_HILOGI("Finalizer for weak_ptr WorkSchedulerExtensionContext is called");
71             delete static_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(data);
72         }, nullptr);
73     return contextObj;
74 }
75 
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)76 void JsWorkSchedulerExtension::Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord>& record,
77     const std::shared_ptr<AppExecFwk::OHOSApplication>& application,
78     std::shared_ptr<AppExecFwk::AbilityHandler>& handler,
79     const sptr<IRemoteObject>& token)
80 {
81     WS_HILOGD("enter");
82     WorkSchedulerExtension::Init(record, application, handler, token);
83     std::string srcPath = "";
84     GetSrcPath(srcPath);
85     if (srcPath.empty()) {
86         WS_HILOGE("JsWorkSchedulerExtension Failed to get srcPath");
87         return;
88     }
89 
90     std::string moduleName(Extension::abilityInfo_->moduleName);
91     moduleName.append("::").append(abilityInfo_->name);
92     WS_HILOGD("moduleName:%{public}s, srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
93     AbilityRuntime::HandleScope handleScope(jsRuntime_);
94     auto& engine = jsRuntime_.GetNativeEngine();
95 
96     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
97         abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE);
98     if (jsObj_ == nullptr) {
99         WS_HILOGE("WorkSchedulerExtension Failed to get jsObj_");
100         return;
101     }
102     NativeObject* obj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(jsObj_->Get());
103     if (obj == nullptr) {
104         WS_HILOGE("WorkSchedulerExtension Failed to get JsWorkSchedulerExtension object");
105         return;
106     }
107     BindContext(engine, obj);
108 
109     WS_HILOGD("end.");
110 }
111 
BindContext(NativeEngine & engine,NativeObject * obj)112 void JsWorkSchedulerExtension::BindContext(NativeEngine& engine, NativeObject* obj)
113 {
114     auto context = GetContext();
115     if (context == nullptr) {
116         WS_HILOGE("WorkSchedulerExtension Failed to get context");
117         return;
118     }
119     NativeValue* contextObj = CreateJsWorkSchedulerExtensionContext(engine, context);
120     shellContextRef_ = jsRuntime_.LoadSystemModule("application.WorkSchedulerExtensionContext",
121         &contextObj, 1);
122     contextObj = shellContextRef_->Get();
123 
124     NativeObject* nativeObj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(contextObj);
125     if (nativeObj == nullptr) {
126         WS_HILOGE("Failed to get context native object");
127         return;
128     }
129     auto workContext = new (std::nothrow) std::weak_ptr<WorkSchedulerExtensionContext>(context);
130     nativeObj->ConvertToNativeBindingObject(&engine, AbilityRuntime::DetachCallbackFunc,
131         AttachWorkSchedulerExtensionContext, workContext, nullptr);
132     WS_HILOGI("JsWorkSchedulerExtension init bind and set property.");
133     context->Bind(jsRuntime_, shellContextRef_.get());
134     obj->SetProperty("context", contextObj);
135     WS_HILOGI("Set JsWorkSchedulerExtension context pointer is nullptr or not:%{public}d",
136         context.get() == nullptr);
137     nativeObj->SetNativePointer(workContext,
138         [](NativeEngine*, void* data, void*) {
139             WS_HILOGI("Finalizer for weak_ptr WorkSchedulerExtensionContext is called");
140             delete static_cast<std::weak_ptr<WorkSchedulerExtensionContext> *>(data);
141         }, nullptr);
142 }
143 
OnStart(const AAFwk::Want & want)144 void JsWorkSchedulerExtension::OnStart(const AAFwk::Want& want)
145 {
146     WS_HILOGD("begin");
147     AbilityRuntime::Extension::OnStart(want);
148 }
149 
OnStop()150 void JsWorkSchedulerExtension::OnStop()
151 {
152     AbilityRuntime::Extension::OnStop();
153     WS_HILOGD("end.");
154 }
155 
OnConnect(const AAFwk::Want & want)156 sptr<IRemoteObject> JsWorkSchedulerExtension::OnConnect(const AAFwk::Want& want)
157 {
158     AbilityRuntime::Extension::OnConnect(want);
159     WS_HILOGD("begin.");
160     sptr<WorkSchedulerStubImp> remoteObject = new (std::nothrow) WorkSchedulerStubImp(
161         std::static_pointer_cast<JsWorkSchedulerExtension>(shared_from_this()));
162     if (remoteObject == nullptr) {
163         WS_HILOGE("OnConnect get null");
164         return remoteObject;
165     }
166     WS_HILOGD("end.");
167     return remoteObject->AsObject();
168 }
169 
OnDisconnect(const AAFwk::Want & want)170 void JsWorkSchedulerExtension::OnDisconnect(const AAFwk::Want& want)
171 {
172     WS_HILOGD("begin.");
173     AbilityRuntime::Extension::OnDisconnect(want);
174 }
175 
OnWorkStart(WorkInfo & workInfo)176 void JsWorkSchedulerExtension::OnWorkStart(WorkInfo& workInfo)
177 {
178     if (handler_ == nullptr) {
179         return;
180     }
181     WS_HILOGD("begin.");
182     int32_t workId = workInfo.GetWorkId();
183     std::string bundleName = workInfo.GetBundleName();
184     std::string abilityName = workInfo.GetAbilityName();
185     bool isPersisted = workInfo.IsPersisted();
186     WorkCondition::Network networkType = workInfo.GetNetworkType();
187     WorkCondition::Charger charger = workInfo.GetChargerType();
188     int32_t batteryLevel = workInfo.GetBatteryLevel();
189     WorkCondition::BatteryStatus batteryStatus = workInfo.GetBatteryStatus();
190     WorkCondition::Storage storageLevel = workInfo.GetStorageLevel();
191     uint32_t timeInterval = workInfo.GetTimeInterval();
192     bool isRepeat = workInfo.IsRepeat();
193     int32_t cycleCount = workInfo.GetCycleCount();
194     std::string extrasStr;
195     bool getExtrasRet = GetExtrasJsonStr(workInfo, extrasStr);
196     WorkSchedulerExtension::OnWorkStart(workInfo);
197     auto task = [=]() {
198         AbilityRuntime::HandleScope handleScope(jsRuntime_);
199         NativeEngine& nativeEngine = jsRuntime_.GetNativeEngine();
200 
201         NativeValue* jworkInfoData = nativeEngine.CreateObject();
202         NativeObject* workInfoData = AbilityRuntime::ConvertNativeValueTo<NativeObject>(jworkInfoData);
203         workInfoData->SetProperty("workId", nativeEngine.CreateNumber(workId));
204 
205         workInfoData->SetProperty("bundleName", nativeEngine.CreateString(bundleName.c_str(), bundleName.size()));
206 
207         workInfoData->SetProperty("abilityName", nativeEngine.CreateString(abilityName.c_str(), abilityName.size()));
208 
209         if (getExtrasRet) {
210             workInfoData->SetProperty("parameters", nativeEngine.CreateString(extrasStr.c_str(), extrasStr.size()));
211         }
212 
213         workInfoData->SetProperty("isPersisted", nativeEngine.CreateBoolean(isPersisted));
214         if (networkType != WorkCondition::Network::NETWORK_UNKNOWN) {
215             workInfoData->SetProperty("networkType", nativeEngine.CreateNumber(networkType));
216         }
217         if (charger != WorkCondition::Charger::CHARGING_UNKNOWN) {
218             if (charger == WorkCondition::Charger::CHARGING_UNPLUGGED) {
219                 workInfoData->SetProperty("isCharging", nativeEngine.CreateBoolean(false));
220             } else {
221                 workInfoData->SetProperty("isCharging", nativeEngine.CreateBoolean(true));
222                 workInfoData->SetProperty("chargerType", nativeEngine.CreateNumber(charger));
223             }
224         }
225         if (batteryLevel != INVALID_VALUE) {
226             workInfoData->SetProperty("batteryLevel", nativeEngine.CreateNumber(batteryLevel));
227         }
228         if (batteryStatus != WorkCondition::BatteryStatus::BATTERY_UNKNOWN) {
229             workInfoData->SetProperty("batteryStatus", nativeEngine.CreateNumber(batteryStatus));
230         }
231         if (storageLevel != WorkCondition::Storage::STORAGE_UNKNOWN) {
232             workInfoData->SetProperty("storageRequest", nativeEngine.CreateNumber(storageLevel));
233         }
234 
235         if (timeInterval > 0) {
236             if (isRepeat) {
237                 workInfoData->SetProperty("isRepeat", nativeEngine.CreateBoolean(true));
238                 workInfoData->SetProperty("repeatCycleTime", nativeEngine.CreateNumber(timeInterval));
239             } else {
240                 workInfoData->SetProperty("repeatCycleTime", nativeEngine.CreateNumber(timeInterval));
241                 workInfoData->SetProperty("repeatCount", nativeEngine.CreateNumber(cycleCount));
242             }
243         }
244 
245         NativeValue* argv[] = {jworkInfoData};
246         if (!jsObj_) {
247             WS_HILOGE("WorkSchedulerExtension Not found js");
248             return;
249         }
250 
251         NativeValue* value = jsObj_->Get();
252         NativeObject* obj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(value);
253         if (obj == nullptr) {
254             WS_HILOGE("WorkSchedulerExtension Failed to get WorkSchedulerExtension object");
255             return;
256         }
257 
258         NativeValue* method = obj->GetProperty("onWorkStart");
259         if (method == nullptr) {
260             WS_HILOGE("WorkSchedulerExtension Failed to get onWorkStart from WorkSchedulerExtension object");
261             return;
262         }
263         nativeEngine.CallFunction(value, method, argv, 1);
264     };
265     handler_->PostTask(task);
266 }
267 
OnWorkStop(WorkInfo & workInfo)268 void JsWorkSchedulerExtension::OnWorkStop(WorkInfo& workInfo)
269 {
270     if (handler_ == nullptr) {
271         return;
272     }
273     WS_HILOGD("begin.");
274     int32_t workId = workInfo.GetWorkId();
275     std::string bundleName = workInfo.GetBundleName();
276     std::string abilityName = workInfo.GetAbilityName();
277     bool isPersisted = workInfo.IsPersisted();
278     WorkCondition::Network networkType = workInfo.GetNetworkType();
279     WorkCondition::Charger charger = workInfo.GetChargerType();
280     int32_t batteryLevel = workInfo.GetBatteryLevel();
281     WorkCondition::BatteryStatus batteryStatus = workInfo.GetBatteryStatus();
282     WorkCondition::Storage storageLevel = workInfo.GetStorageLevel();
283     uint32_t timeInterval = workInfo.GetTimeInterval();
284     bool isRepeat = workInfo.IsRepeat();
285     int32_t cycleCount = workInfo.GetCycleCount();
286     std::string extrasStr;
287     bool getExtrasRet = GetExtrasJsonStr(workInfo, extrasStr);
288     WorkSchedulerExtension::OnWorkStop(workInfo);
289     auto task = [=]() {
290         AbilityRuntime::HandleScope handleScope(jsRuntime_);
291         NativeEngine& nativeEngine = jsRuntime_.GetNativeEngine();
292 
293         NativeValue* jworkInfoData = nativeEngine.CreateObject();
294         NativeObject* workInfoData = AbilityRuntime::ConvertNativeValueTo<NativeObject>(jworkInfoData);
295         workInfoData->SetProperty("workId", nativeEngine.CreateNumber(workId));
296 
297         workInfoData->SetProperty("bundleName", nativeEngine.CreateString(bundleName.c_str(), bundleName.size()));
298 
299         workInfoData->SetProperty("abilityName", nativeEngine.CreateString(abilityName.c_str(), abilityName.size()));
300 
301         if (getExtrasRet) {
302             workInfoData->SetProperty("parameters", nativeEngine.CreateString(extrasStr.c_str(), extrasStr.size()));
303         }
304 
305         workInfoData->SetProperty("isPersisted", nativeEngine.CreateBoolean(isPersisted));
306         if (networkType != WorkCondition::Network::NETWORK_UNKNOWN) {
307             workInfoData->SetProperty("networkType", nativeEngine.CreateNumber(networkType));
308         }
309         if (charger != WorkCondition::Charger::CHARGING_UNKNOWN) {
310             if (charger == WorkCondition::Charger::CHARGING_UNPLUGGED) {
311                 workInfoData->SetProperty("isCharging", nativeEngine.CreateBoolean(false));
312             } else {
313                 workInfoData->SetProperty("isCharging", nativeEngine.CreateBoolean(true));
314                 workInfoData->SetProperty("chargerType", nativeEngine.CreateNumber(charger));
315             }
316         }
317         if (batteryLevel != INVALID_VALUE) {
318             workInfoData->SetProperty("batteryLevel", nativeEngine.CreateNumber(batteryLevel));
319         }
320         if (batteryStatus != WorkCondition::BatteryStatus::BATTERY_UNKNOWN) {
321             workInfoData->SetProperty("batteryStatus", nativeEngine.CreateNumber(batteryStatus));
322         }
323         if (storageLevel != WorkCondition::Storage::STORAGE_UNKNOWN) {
324             workInfoData->SetProperty("storageRequest", nativeEngine.CreateNumber(storageLevel));
325         }
326 
327         if (timeInterval > 0) {
328             if (isRepeat) {
329                 workInfoData->SetProperty("isRepeat", nativeEngine.CreateBoolean(true));
330                 workInfoData->SetProperty("repeatCycleTime", nativeEngine.CreateNumber(timeInterval));
331             } else {
332                 workInfoData->SetProperty("repeatCycleTime", nativeEngine.CreateNumber(timeInterval));
333                 workInfoData->SetProperty("repeatCount", nativeEngine.CreateNumber(cycleCount));
334             }
335         }
336 
337         NativeValue* argv[] = {jworkInfoData};
338         if (!jsObj_) {
339             WS_HILOGE("WorkSchedulerExtension Not found js");
340             return;
341         }
342 
343         NativeValue* value = jsObj_->Get();
344         NativeObject* obj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(value);
345         if (obj == nullptr) {
346             WS_HILOGE("WorkSchedulerExtension Failed to get object");
347             return;
348         }
349 
350         NativeValue* method = obj->GetProperty("onWorkStop");
351         if (method == nullptr) {
352             WS_HILOGE("WorkSchedulerExtension Failed to get onWorkStop from object");
353             return;
354         }
355         nativeEngine.CallFunction(value, method, argv, 1);
356     };
357     handler_->PostTask(task);
358 }
359 
GetSrcPath(std::string & srcPath)360 void JsWorkSchedulerExtension::GetSrcPath(std::string &srcPath)
361 {
362     if (!Extension::abilityInfo_->isStageBasedModel) {
363         /* temporary compatibility api8 + config.json */
364         srcPath.append(Extension::abilityInfo_->package);
365         srcPath.append("/assets/js/");
366         if (!Extension::abilityInfo_->srcPath.empty()) {
367             srcPath.append(Extension::abilityInfo_->srcPath);
368         }
369         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
370         return;
371     }
372 
373     if (!Extension::abilityInfo_->srcEntrance.empty()) {
374         srcPath.append(Extension::abilityInfo_->moduleName + "/");
375         srcPath.append(Extension::abilityInfo_->srcEntrance);
376         srcPath.erase(srcPath.rfind('.'));
377         srcPath.append(".abc");
378     }
379 }
380 
GetExtrasJsonStr(const WorkInfo & workInfo,std::string & extrasStr)381 bool JsWorkSchedulerExtension::GetExtrasJsonStr(const WorkInfo& workInfo, std::string& extrasStr)
382 {
383     std::shared_ptr<AAFwk::WantParams> extras = workInfo.GetExtras();
384     Json::Value extrasJson;
385     if (!extras) {
386         WS_HILOGI("parameter is null.");
387         return false;
388     }
389     auto extrasMap = extras->GetParams();
390     int typeId = INVALID_VALUE;
391     for (auto it : extrasMap) {
392         typeId = AAFwk::WantParams::GetDataType(it.second);
393         if (typeId != INVALID_VALUE) {
394             std::string value = AAFwk::WantParams::GetStringByType(it.second, typeId);
395             extrasJson[it.first] = value;
396         } else {
397             WS_HILOGE("parameters type not supported.");
398         }
399     }
400     Json::StreamWriterBuilder builder;
401     extrasStr = Json::writeString(builder, extrasJson);
402     return true;
403 }
404 } // namespace WorkScheduler
405 } // namespace OHOS
406