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