• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "work_scheduler_ffi.h"
17 #include "workscheduler_srv_client.h"
18 #include "work_sched_errors.h"
19 #include "work_scheduler_log.h"
20 #include "want_params_wrapper.h"
21 #include "bool_wrapper.h"
22 #include "double_wrapper.h"
23 #include "int_wrapper.h"
24 #include "string_wrapper.h"
25 
26 namespace OHOS {
27 namespace WorkScheduler {
28 
29 template <class T, class IT, class NativeT>
InnerWrapWantParamsT(const sptr<AAFwk::IInterface> iIt,CParameters * p)30 int32_t InnerWrapWantParamsT(const sptr<AAFwk::IInterface> iIt, CParameters *p)
31 {
32     NativeT natValue = T::Unbox(IT::Query(iIt));
33     NativeT *ptr = static_cast<NativeT *>(malloc(sizeof(NativeT)));
34     if (ptr == nullptr) {
35         LOGE("natValue ptr is nullptr, no memory.");
36         return ERR_NO_MEMORY;
37     }
38     *ptr = natValue;
39     p->value = static_cast<void*>(ptr);
40     p->size = sizeof(NativeT);
41     return 0;
42 }
43 
GetWorkInfoV2(RetWorkInfoV2 cwork,WorkInfo & workInfo)44 int32_t GetWorkInfoV2(RetWorkInfoV2 cwork, WorkInfo& workInfo)
45 {
46     auto ret = GetWorkInfo(cwork.v1, workInfo);
47     if (ret != 0) {
48         return ret;
49     }
50     return GetExtrasInfo(cwork, workInfo);
51 }
52 
ParseWorkInfoV2(std::shared_ptr<WorkInfo> workInfo,RetWorkInfoV2 & cwork)53 void ParseWorkInfoV2(std::shared_ptr<WorkInfo> workInfo, RetWorkInfoV2& cwork)
54 {
55     ParseWorkInfo(workInfo, cwork.v1);
56     ParseExtrasInfo(workInfo, cwork.parameters);
57 }
58 
59 extern "C" {
60     const int32_t BATTERY_LEVEL_MIN = 0;
61     const int32_t BATTERY_LEVEL_MAX = 100;
62 
63     const int8_t INT_TYPE = 0;
64     const int8_t F64_TYPE = 1;
65     const int8_t STRING_TYPE = 2;
66     const int8_t BOOL_TYPE = 3;
67     // need to be same as WantParams
68     enum {
69         VALUE_TYPE_NULL = -1,
70         VALUE_TYPE_BOOLEAN = 1,
71         VALUE_TYPE_INT = 5,
72         VALUE_TYPE_DOUBLE = 8,
73         VALUE_TYPE_STRING = 9,
74     };
75 
CJ_StartWork(RetWorkInfo work)76     int32_t CJ_StartWork(RetWorkInfo work)
77     {
78         WorkInfo workInfo = WorkInfo();
79         auto paraCode = GetWorkInfo(work, workInfo);
80         if (paraCode != SUCCESS_CODE) {
81             LOGE("WorkScheduler: CJ_StartWork parse parameter failed %{public}d", paraCode);
82             return paraCode;
83         }
84         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().StartWork(workInfo);
85         return errCode;
86     }
87 
CJ_StopWork(RetWorkInfo work,bool needCancel)88     int32_t CJ_StopWork(RetWorkInfo work, bool needCancel)
89     {
90         WorkInfo workInfo = WorkInfo();
91         ErrCode errCode;
92         auto paraCode = GetWorkInfo(work, workInfo);
93         if (paraCode != SUCCESS_CODE) {
94             LOGE("WorkScheduler: CJ_StopWork parse parameter failed %{public}d", paraCode);
95             return paraCode;
96         }
97         if (needCancel) {
98             errCode = WorkSchedulerSrvClient::GetInstance().StopAndCancelWork(workInfo);
99         } else {
100             errCode = WorkSchedulerSrvClient::GetInstance().StopWork(workInfo);
101         }
102         return errCode;
103     }
104 
CJ_GetWorkStatus(int32_t workId,RetWorkInfo & result)105     int32_t CJ_GetWorkStatus(int32_t workId, RetWorkInfo& result)
106     {
107         std::shared_ptr<WorkInfo> workInfo {nullptr};
108         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().GetWorkStatus(workId, workInfo);
109         if (errCode != ERR_OK) {
110             LOGE("WorkScheduler: CJ_GetWorkStatus failed %{public}d", errCode);
111             return errCode;
112         }
113         ParseWorkInfo(workInfo, result);
114         LOGI("WorkScheduler: CJ_GetWorkStatus success");
115         return errCode;
116     }
117 
CJ_ObtainAllWorks()118     RetArrRetWorkInfo CJ_ObtainAllWorks()
119     {
120         std::list<std::shared_ptr<WorkInfo>> workInfoList;
121         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().ObtainAllWorks(workInfoList);
122         RetArrRetWorkInfo ret = { .code = errCode, .size = 0, .data = nullptr};
123         if (errCode != ERR_OK) {
124             LOGE("WorkScheduler: CJ_ObtainAllWorks failed ");
125             return ret;
126         }
127         int64_t listSize = static_cast<int64_t>(workInfoList.size());
128         if (listSize < 0 || listSize > UINT_MAX) {
129             LOGE("Illegal listSize parameter");
130             return ret;
131         }
132         auto data = static_cast<RetWorkInfo*>(malloc(sizeof(RetWorkInfo) * listSize));
133         if (data == nullptr) {
134             return ret;
135         }
136         ret.size = listSize;
137         int index = 0;
138         for (auto workInfo: workInfoList) {
139             ParseWorkInfo(workInfo, data[index]);
140             index++;
141         }
142         ret.data = data;
143         return ret;
144     }
145 
CJ_IsLastWorkTimeOut(int32_t workId,bool & result)146     int32_t CJ_IsLastWorkTimeOut(int32_t workId, bool& result)
147     {
148         return WorkSchedulerSrvClient::GetInstance().IsLastWorkTimeout(workId, result);
149     }
150 
CJ_StopAndClearWorks()151     int32_t CJ_StopAndClearWorks()
152     {
153         return WorkSchedulerSrvClient::GetInstance().StopAndClearWorks();
154     }
155 
CJ_StartWorkV2(RetWorkInfoV2 work)156     int32_t CJ_StartWorkV2(RetWorkInfoV2 work)
157     {
158         WorkInfo workInfo = WorkInfo();
159         auto paraCode = GetWorkInfoV2(work, workInfo);
160         if (paraCode != SUCCESS_CODE) {
161             LOGE("WorkScheduler: CJ_StartWork parse parameter failed %{public}d", paraCode);
162             return paraCode;
163         }
164         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().StartWork(workInfo);
165         return errCode;
166     }
167 
CJ_StopWorkV2(RetWorkInfoV2 work,bool needCancel)168     int32_t CJ_StopWorkV2(RetWorkInfoV2 work, bool needCancel)
169     {
170         WorkInfo workInfo = WorkInfo();
171         ErrCode errCode;
172         auto paraCode = GetWorkInfoV2(work, workInfo);
173         if (paraCode != SUCCESS_CODE) {
174             LOGE("WorkScheduler: CJ_StopWork parse parameter failed %{public}d", paraCode);
175             return paraCode;
176         }
177         if (needCancel) {
178             errCode = WorkSchedulerSrvClient::GetInstance().StopAndCancelWork(workInfo);
179         } else {
180             errCode = WorkSchedulerSrvClient::GetInstance().StopWork(workInfo);
181         }
182         return errCode;
183     }
184 
CJ_GetWorkStatusV2(int32_t workId,RetWorkInfoV2 & result)185     int32_t CJ_GetWorkStatusV2(int32_t workId, RetWorkInfoV2& result)
186     {
187         std::shared_ptr<WorkInfo> workInfo {nullptr};
188         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().GetWorkStatus(workId, workInfo);
189         if (errCode != ERR_OK) {
190             LOGE("WorkScheduler: CJ_GetWorkStatus failed %{public}d", errCode);
191             return errCode;
192         }
193         ParseWorkInfoV2(workInfo, result);
194         LOGI("WorkScheduler: CJ_GetWorkStatus success");
195         return errCode;
196     }
197 
CJ_ObtainAllWorksV2()198     RetArrRetWorkInfoV2 CJ_ObtainAllWorksV2()
199     {
200         std::list<std::shared_ptr<WorkInfo>> workInfoList;
201         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().ObtainAllWorks(workInfoList);
202         RetArrRetWorkInfoV2 ret = { .code = errCode, .size = 0, .data = nullptr};
203         if (errCode != ERR_OK) {
204             LOGE("WorkScheduler: CJ_ObtainAllWorks failed ");
205             return ret;
206         }
207         int64_t listSize = static_cast<int64_t>(workInfoList.size());
208         if (listSize < 0 || listSize > UINT_MAX) {
209             LOGE("Illegal listSize parameter");
210             return ret;
211         }
212         auto data = static_cast<RetWorkInfoV2*>(malloc(sizeof(RetWorkInfoV2) * listSize));
213         if (data == nullptr) {
214             return ret;
215         }
216         ret.size = listSize;
217         int index = 0;
218         for (auto workInfo: workInfoList) {
219             ParseWorkInfoV2(workInfo, data[index]);
220             index++;
221         }
222         ret.data = data;
223         return ret;
224     }
225 
226     // extra is not set
GetWorkInfo(RetWorkInfo cwork,WorkInfo & workInfo)227     int32_t GetWorkInfo(RetWorkInfo cwork, WorkInfo& workInfo)
228     {
229         workInfo.SetWorkId(cwork.workId);
230         workInfo.SetElement(std::string(cwork.bundleName), std::string(cwork.abilityName));
231         workInfo.RequestPersisted(cwork.isPersisted);
232         bool hasConditions = false;
233         int32_t ret = GetNetWorkInfo(cwork, workInfo, hasConditions);
234         if (ret != 0) {
235             return ret;
236         }
237         ret = GetChargeInfo(cwork, workInfo, hasConditions);
238         if (ret != 0) {
239             return ret;
240         }
241         ret = GetBatteryInfo(cwork, workInfo, hasConditions);
242         if (ret != 0) {
243             return ret;
244         }
245         ret = GetStorageInfo(cwork, workInfo, hasConditions);
246         if (ret != 0) {
247             return ret;
248         }
249         ret = GetRepeatInfo(cwork, workInfo, hasConditions);
250         if (ret != 0) {
251             return ret;
252         }
253 
254         if (!hasConditions) {
255             LOGE("Set none conditions, so fail to init WorkInfo.");
256             return E_CONDITION_EMPTY;
257         }
258         return 0;
259     }
260 
GetExtrasInfo(RetWorkInfoV2 cwork,OHOS::WorkScheduler::WorkInfo & workInfo)261     int32_t GetExtrasInfo(RetWorkInfoV2 cwork, OHOS::WorkScheduler::WorkInfo& workInfo)
262     {
263         int32_t code = 0;
264         CArrParameters cArrP = cwork.parameters;
265         AAFwk::WantParams wants;
266         if (cArrP.size == 0) {
267             return code;
268         }
269         for (auto i = 0; i < cArrP.size; ++i) {
270             std::string key = std::string(cArrP.head[i].key);
271             switch (cArrP.head[i].valueType) {
272                 case INT_TYPE: {
273                     int32_t *intVal = static_cast<int32_t *>(cArrP.head[i].value);
274                     wants.SetParam(key, AAFwk::Integer::Box(*intVal));
275                     break;
276                 }
277                 case F64_TYPE: {
278                     double *doubleVal = static_cast<double *>(cArrP.head[i].value);
279                     wants.SetParam(key, AAFwk::Double::Box(*doubleVal));
280                     break;
281                 }
282                 case STRING_TYPE: {
283                     std::string strVal(static_cast<char *>(cArrP.head[i].value));
284                     wants.SetParam(key, AAFwk::String::Box(strVal));
285                     break;
286                 }
287                 case BOOL_TYPE: {
288                     bool *boolVal = static_cast<bool *>(cArrP.head[i].value);
289                     wants.SetParam(key, AAFwk::Boolean::Box(*boolVal));
290                     break;
291                 }
292                 default: {
293                     LOGE("parameters type error.");
294                     code = E_PARAMETERS_TYPE_ERR;
295                     return code;
296                 }
297             }
298         }
299         workInfo.RequestExtras(wants);
300         return code;
301     }
302 
GetNetWorkInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)303     int32_t GetNetWorkInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
304     {
305         int32_t code = 0;
306         if (cwork.netWorkType == UNSET_INT_PARAM) {
307             LOGI("Unset networkType.");
308         } else if (cwork.netWorkType >= WorkCondition::Network::NETWORK_TYPE_ANY &&
309             cwork.netWorkType <= WorkCondition::Network::NETWORK_TYPE_ETHERNET) {
310             workInfo.RequestNetworkType(WorkCondition::Network(cwork.netWorkType));
311             hasCondition = true;
312         } else {
313             LOGE("NetworkType set is invalid, just ignore set.");
314             code = E_NETWORK_TYPE_ERR;
315         }
316         return code;
317     }
318 
GetChargeInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)319     int32_t GetChargeInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
320     {
321         if (!cwork.isCharging) {
322             workInfo.RequestChargerType(false, WorkCondition::Charger::CHARGING_UNPLUGGED);
323         } else {
324             if (cwork.chargerType == UNSET_INT_PARAM) {
325                 workInfo.RequestChargerType(true, WorkCondition::Charger::CHARGING_PLUGGED_ANY);
326             } else if (cwork.chargerType >=  WorkCondition::Charger::CHARGING_PLUGGED_ANY &&
327                 cwork.chargerType <= WorkCondition::Charger::CHARGING_PLUGGED_WIRELESS) {
328                 workInfo.RequestChargerType(true, WorkCondition::Charger(cwork.chargerType));
329                 hasCondition = true;
330             } else {
331                 workInfo.RequestChargerType(true, WorkCondition::Charger::CHARGING_PLUGGED_ANY);
332                 LOGE("ChargeType info is invalid, just ignore set.");
333                 return E_CHARGER_TYPE_ERR;
334             }
335         }
336         return 0;
337     }
338 
GetBatteryInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)339     int32_t GetBatteryInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
340     {
341         if (cwork.batteryLevel == UNSET_INT_PARAM) {
342             LOGI("Unset batteryLevel.");
343         } else if (cwork.batteryLevel >= BATTERY_LEVEL_MIN && cwork.batteryLevel <= BATTERY_LEVEL_MAX) {
344             workInfo.RequestBatteryLevel(cwork.batteryLevel);
345         } else {
346             LOGE("BatteryLevel set is invalid, just ignore set.");
347             return E_BATTERY_LEVEL_ERR;
348         }
349 
350         if (cwork.batteryStatus == UNSET_INT_PARAM) {
351             LOGI("Unset batteryStatus.");
352         } else if (cwork.batteryStatus >= WorkCondition::BatteryStatus::BATTERY_STATUS_LOW &&
353             cwork.batteryStatus <= WorkCondition::BatteryStatus::BATTERY_STATUS_LOW_OR_OKAY) {
354             workInfo.RequestBatteryStatus(WorkCondition::BatteryStatus(cwork.batteryStatus));
355             hasCondition = true;
356         } else {
357             LOGE("BatteryStatus set is invalid, just ignore set.");
358             return E_BATTERY_STATUS_ERR;
359         }
360         return 0;
361     }
362 
GetStorageInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)363     int32_t GetStorageInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
364     {
365         if (cwork.storageRequest == UNSET_INT_PARAM) {
366             LOGI("Unset StorageRequest.");
367         } else if (cwork.storageRequest >= WorkCondition::Storage::STORAGE_LEVEL_LOW &&
368                 cwork.storageRequest <= WorkCondition::Storage::STORAGE_LEVEL_LOW_OR_OKAY) {
369             workInfo.RequestStorageLevel(WorkCondition::Storage(cwork.storageRequest));
370             hasCondition = true;
371         } else {
372             LOGE("StorageRequest set is invalid, just ignore set.");
373             return E_STORAGE_REQUEST_ERR;
374         }
375         return 0;
376     }
377 
GetRepeatInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)378     int32_t GetRepeatInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
379     {
380         if (cwork.repeatCycleTime == UNSET_INT_PARAM) {
381             LOGI("RepeatCycleTime not set, just ignore other repeat set.");
382             return 0;
383         }
384 
385         if (!cwork.isRepeat && cwork.repeatCount == UNSET_INT_PARAM) {
386             LOGI("Not set isRepeat or repeatCount, ignore.");
387             return 0;
388         }
389         if (cwork.isRepeat) {
390             if (cwork.repeatCount > 0) {
391                 LOGI("RepeatCount has been set , ignore isRepeat.");
392                 workInfo.RequestRepeatCycle(cwork.repeatCycleTime, cwork.repeatCount);
393             } else {
394                 workInfo.RequestRepeatCycle(cwork.repeatCycleTime);
395             }
396             hasCondition = true;
397             return 0;
398         } else {
399             if (cwork.repeatCount < 0) {
400                 LOGE("RepeatCount is invalid, ignore.");
401                 return E_REPEAT_COUNT_ERR;
402             }
403             workInfo.RequestRepeatCycle(cwork.repeatCycleTime, cwork.repeatCount);
404             hasCondition = true;
405             return 0;
406         }
407     }
408 
ParseWorkInfo(std::shared_ptr<WorkInfo> workInfo,RetWorkInfo & cwork)409     void ParseWorkInfo(std::shared_ptr<WorkInfo> workInfo, RetWorkInfo& cwork)
410     {
411         cwork.workId = workInfo->GetWorkId();
412         cwork.bundleName = MallocCString(workInfo->GetBundleName());
413         cwork.abilityName = MallocCString(workInfo->GetAbilityName());
414         cwork.isPersisted = workInfo->IsPersisted();
415         cwork.netWorkType = workInfo->GetNetworkType();
416         auto chargerType = workInfo->GetChargerType();
417         if (chargerType >= WorkCondition::Charger::CHARGING_UNPLUGGED) {
418             cwork.isCharging = false;
419             cwork.chargerType = -1;
420         } else {
421             cwork.isCharging = true;
422             cwork.chargerType = chargerType;
423         }
424         cwork.batteryLevel = workInfo->GetBatteryLevel();
425         cwork.batteryStatus = workInfo->GetBatteryStatus();
426         cwork.storageRequest = workInfo->GetStorageLevel();
427         cwork.isRepeat = workInfo->IsRepeat();
428         cwork.repeatCycleTime = static_cast<int32_t>(workInfo->GetTimeInterval());
429         cwork.repeatCount = workInfo->GetCycleCount();
430         cwork.isDeepIdle = -1;
431         cwork.idleWaitTime = -1;
432     }
433 
ConvertToCArrParameters(std::map<std::string,sptr<AAFwk::IInterface>> & extrasMap,CArrParameters & arrParam)434     void ConvertToCArrParameters(std::map<std::string, sptr<AAFwk::IInterface>>& extrasMap, CArrParameters& arrParam)
435     {
436         int typeId = VALUE_TYPE_NULL;
437         int i = 0;
438         int32_t mallocSize = static_cast<int32_t>(sizeof(CParameters) * arrParam.size);
439         arrParam.head = static_cast<CParameters *>(malloc(mallocSize));
440         if (!arrParam.head) {
441             arrParam.size = 0;
442             return;
443         }
444         for (auto it : extrasMap) {
445             typeId = AAFwk::WantParams::GetDataType(it.second);
446             arrParam.head[i].key = MallocCString(it.first);
447             switch (typeId) {
448                 case VALUE_TYPE_INT: {
449                     arrParam.head[i].valueType = INT_TYPE;
450                     InnerWrapWantParamsT<AAFwk::Integer, AAFwk::IInteger, int>(it.second, &arrParam.head[i]);
451                     break;
452                 }
453                 case VALUE_TYPE_DOUBLE: {
454                     arrParam.head[i].valueType = F64_TYPE;
455                     InnerWrapWantParamsT<AAFwk::Double, AAFwk::IDouble, double>(it.second, &arrParam.head[i]);
456                     break;
457                 }
458                 case VALUE_TYPE_BOOLEAN: {
459                     arrParam.head[i].valueType = BOOL_TYPE;
460                     InnerWrapWantParamsT<AAFwk::Boolean, AAFwk::IBoolean, bool>(it.second, &arrParam.head[i]);
461                     break;
462                 }
463                 case VALUE_TYPE_STRING: {
464                     arrParam.head[i].valueType = STRING_TYPE;
465                     InnerWrapWantParamsT<AAFwk::String, AAFwk::IString, std::string>(it.second, &arrParam.head[i]);
466                     break;
467                 }
468                 default: {
469                     LOGE("parameters type not supported.");
470                     break;
471                 }
472             }
473             ++i;
474         }
475     }
476 
ParseExtrasInfo(std::shared_ptr<WorkInfo> workInfo,CArrParameters & arrParam)477     void ParseExtrasInfo(std::shared_ptr<WorkInfo> workInfo, CArrParameters &arrParam)
478     {
479         // init arrParam
480         arrParam.size = 0;
481         arrParam.head = nullptr;
482         std::shared_ptr<AAFwk::WantParams> extras = workInfo->GetExtras();
483         if (extras.get() == nullptr) {
484             LOGI("extras map is not initialized.");
485             return;
486         }
487         auto extrasMap = extras->GetParams();
488         arrParam.size = static_cast<int64_t>(extrasMap.size());
489         if (extrasMap.size() == 0) {
490             LOGI("extras parameters is 0.");
491             return;
492         }
493         ConvertToCArrParameters(extrasMap, arrParam);
494     }
495 
MallocCString(const std::string & origin)496     char* MallocCString(const std::string& origin)
497     {
498         if (origin.empty()) {
499             return nullptr;
500         }
501         auto len = origin.length() + 1;
502         char* res = static_cast<char*>(malloc(sizeof(char) * len));
503         if (res == nullptr) {
504             return nullptr;
505         }
506         return std::char_traits<char>::copy(res, origin.c_str(), len);
507     }
508 }
509 } // WorkScheduler
510 } // OHOS