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