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