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 
21 namespace OHOS {
22 namespace WorkScheduler {
23 
24 extern "C" {
25     const int32_t BATTERY_LEVEL_MIN = 0;
26     const int32_t BATTERY_LEVEL_MAX = 100;
27 
CJ_StartWork(RetWorkInfo work)28     int32_t CJ_StartWork(RetWorkInfo work)
29     {
30         WorkInfo workInfo = WorkInfo();
31         auto paraCode = GetWorkInfo(work, workInfo);
32         if (paraCode != SUCCESS_CODE) {
33             LOGE("WorkScheduler: CJ_StartWork parse parameter failed %{public}d", paraCode);
34             return paraCode;
35         }
36         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().StartWork(workInfo);
37         return errCode;
38     }
39 
CJ_StopWork(RetWorkInfo work,bool needCancel)40     int32_t CJ_StopWork(RetWorkInfo work, bool needCancel)
41     {
42         WorkInfo workInfo = WorkInfo();
43         auto paraCode = GetWorkInfo(work, workInfo);
44         if (paraCode != SUCCESS_CODE) {
45             LOGE("WorkScheduler: CJ_StopWork parse parameter failed %{public}d", paraCode);
46             return paraCode;
47         }
48         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().StopWork(workInfo);
49         return errCode;
50     }
51 
CJ_GetWorkStatus(int32_t workId,RetWorkInfo & result)52     int32_t CJ_GetWorkStatus(int32_t workId, RetWorkInfo& result)
53     {
54         std::shared_ptr<WorkInfo> workInfo {nullptr};
55         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().GetWorkStatus(workId, workInfo);
56         if (errCode != ERR_OK) {
57             LOGE("WorkScheduler: CJ_GetWorkStatus failed %{public}d", errCode);
58             return errCode;
59         }
60         ParseWorkInfo(workInfo, result);
61         LOGI("WorkScheduler: CJ_GetWorkStatus success");
62         return errCode;
63     }
64 
CJ_ObtainAllWorks()65     RetArrRetWorkInfo CJ_ObtainAllWorks()
66     {
67         std::list<std::shared_ptr<WorkInfo>> workInfoList;
68         ErrCode errCode = WorkSchedulerSrvClient::GetInstance().ObtainAllWorks(workInfoList);
69         RetArrRetWorkInfo ret = { .code = errCode, .size = 0, .data = nullptr};
70         if (errCode != ERR_OK) {
71             LOGE("WorkScheduler: CJ_ObtainAllWorks failed ");
72             return ret;
73         }
74         int64_t listSize = static_cast<int64_t>(workInfoList.size());
75         if (listSize < 0 || listSize > UINT_MAX) {
76             LOGE("Illegal listSize parameter");
77             return ret;
78         }
79         auto data = static_cast<RetWorkInfo*>(malloc(sizeof(RetWorkInfo) * listSize));
80         if (data == nullptr) {
81             return ret;
82         }
83         ret.size = listSize;
84         int index = 0;
85         for (auto workInfo: workInfoList) {
86             ParseWorkInfo(workInfo, data[index]);
87             index++;
88         }
89         ret.data = data;
90         return ret;
91     }
92 
CJ_IsLastWorkTimeOut(int32_t workId,bool & result)93     int32_t CJ_IsLastWorkTimeOut(int32_t workId, bool& result)
94     {
95         return WorkSchedulerSrvClient::GetInstance().IsLastWorkTimeout(workId, result);
96     }
97 
98     // extra is not set
GetWorkInfo(RetWorkInfo cwork,WorkInfo & workInfo)99     int32_t GetWorkInfo(RetWorkInfo cwork, WorkInfo& workInfo)
100     {
101         workInfo.SetWorkId(cwork.workId);
102         workInfo.SetElement(std::string(cwork.bundleName), std::string(cwork.abilityName));
103         workInfo.RequestPersisted(cwork.isPersisted);
104         bool hasConditions = false;
105         int32_t ret = GetNetWorkInfo(cwork, workInfo, hasConditions);
106         if (ret != 0) {
107             return ret;
108         }
109         ret = GetChargeInfo(cwork, workInfo, hasConditions);
110         if (ret != 0) {
111             return ret;
112         }
113         ret = GetBatteryInfo(cwork, workInfo, hasConditions);
114         if (ret != 0) {
115             return ret;
116         }
117         ret = GetStorageInfo(cwork, workInfo, hasConditions);
118         if (ret != 0) {
119             return ret;
120         }
121         ret = GetRepeatInfo(cwork, workInfo, hasConditions);
122         if (ret != 0) {
123             return ret;
124         }
125 
126         if (!hasConditions) {
127             LOGE("Set none conditions, so fail to init WorkInfo.");
128             return E_CONDITION_EMPTY;
129         }
130         return 0;
131     }
132 
GetNetWorkInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)133     int32_t GetNetWorkInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
134     {
135         int32_t code = 0;
136         if (cwork.netWorkType == UNSET_INT_PARAM) {
137             LOGI("Unset networkType.");
138         } else if (cwork.netWorkType >= WorkCondition::Network::NETWORK_TYPE_ANY &&
139             cwork.netWorkType <= WorkCondition::Network::NETWORK_TYPE_ETHERNET) {
140             workInfo.RequestNetworkType(WorkCondition::Network(cwork.netWorkType));
141             hasCondition = true;
142         } else {
143             LOGE("NetworkType set is invalid, just ignore set.");
144             code = E_NETWORK_TYPE_ERR;
145         }
146         return code;
147     }
148 
GetChargeInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)149     int32_t GetChargeInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
150     {
151         if (!cwork.isCharging) {
152             workInfo.RequestChargerType(false, WorkCondition::Charger::CHARGING_UNPLUGGED);
153         } else {
154             if (cwork.chargerType == UNSET_INT_PARAM) {
155                 workInfo.RequestChargerType(true, WorkCondition::Charger::CHARGING_PLUGGED_ANY);
156             } else if (cwork.chargerType >=  WorkCondition::Charger::CHARGING_PLUGGED_ANY &&
157                 cwork.chargerType <= WorkCondition::Charger::CHARGING_PLUGGED_WIRELESS) {
158                 workInfo.RequestChargerType(true, WorkCondition::Charger(cwork.chargerType));
159                 hasCondition = true;
160             } else {
161                 workInfo.RequestChargerType(true, WorkCondition::Charger::CHARGING_PLUGGED_ANY);
162                 LOGE("ChargeType info is invalid, just ignore set.");
163                 return E_CHARGER_TYPE_ERR;
164             }
165         }
166         return 0;
167     }
168 
GetBatteryInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)169     int32_t GetBatteryInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
170     {
171         if (cwork.batteryLevel == UNSET_INT_PARAM) {
172             LOGI("Unset batteryLevel.");
173         } else if (cwork.batteryLevel >= BATTERY_LEVEL_MIN && cwork.batteryLevel <= BATTERY_LEVEL_MAX) {
174             workInfo.RequestBatteryLevel(cwork.batteryLevel);
175         } else {
176             LOGE("BatteryLevel set is invalid, just ignore set.");
177             return E_BATTERY_LEVEL_ERR;
178         }
179 
180         if (cwork.batteryStatus == UNSET_INT_PARAM) {
181             LOGI("Unset batteryStatus.");
182         } else if (cwork.batteryStatus >= WorkCondition::BatteryStatus::BATTERY_STATUS_LOW &&
183             cwork.batteryStatus <= WorkCondition::BatteryStatus::BATTERY_STATUS_LOW_OR_OKAY) {
184             workInfo.RequestBatteryStatus(WorkCondition::BatteryStatus(cwork.batteryStatus));
185             hasCondition = true;
186         } else {
187             LOGE("BatteryStatus set is invalid, just ignore set.");
188             return E_BATTERY_STATUS_ERR;
189         }
190         return 0;
191     }
192 
GetStorageInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)193     int32_t GetStorageInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
194     {
195         if (cwork.storageRequest == UNSET_INT_PARAM) {
196             LOGI("Unset StorageRequest.");
197         } else if (cwork.storageRequest >= WorkCondition::Storage::STORAGE_LEVEL_LOW &&
198                 cwork.storageRequest <= WorkCondition::Storage::STORAGE_LEVEL_LOW_OR_OKAY) {
199             workInfo.RequestStorageLevel(WorkCondition::Storage(cwork.storageRequest));
200             hasCondition = true;
201         } else {
202             LOGE("StorageRequest set is invalid, just ignore set.");
203             return E_STORAGE_REQUEST_ERR;
204         }
205         return 0;
206     }
207 
GetRepeatInfo(RetWorkInfo cwork,WorkInfo & workInfo,bool & hasCondition)208     int32_t GetRepeatInfo(RetWorkInfo cwork, WorkInfo& workInfo, bool& hasCondition)
209     {
210         if (cwork.repeatCycleTime == UNSET_INT_PARAM) {
211             LOGI("RepeatCycleTime not set, just ignore other repeat set.");
212             return 0;
213         }
214 
215         if (!cwork.isRepeat && cwork.repeatCount == UNSET_INT_PARAM) {
216             LOGI("Not set isRepeat or repeatCount, ignore.");
217             return 0;
218         }
219         if (cwork.isRepeat) {
220             if (cwork.repeatCount > 0) {
221                 LOGI("RepeatCount has been set , ignore isRepeat.");
222                 workInfo.RequestRepeatCycle(cwork.repeatCycleTime, cwork.repeatCount);
223             } else {
224                 workInfo.RequestRepeatCycle(cwork.repeatCycleTime);
225             }
226             hasCondition = true;
227             return 0;
228         } else {
229             if (cwork.repeatCount < 0) {
230                 LOGE("RepeatCount is invalid, ignore.");
231                 return E_REPEAT_COUNT_ERR;
232             }
233             workInfo.RequestRepeatCycle(cwork.repeatCycleTime, cwork.repeatCount);
234             hasCondition = true;
235             return 0;
236         }
237     }
238 
ParseWorkInfo(std::shared_ptr<WorkInfo> workInfo,RetWorkInfo & cwork)239     void ParseWorkInfo(std::shared_ptr<WorkInfo> workInfo, RetWorkInfo& cwork)
240     {
241         cwork.workId = workInfo->GetWorkId();
242         cwork.bundleName = MallocCString(workInfo->GetBundleName());
243         cwork.abilityName = MallocCString(workInfo->GetAbilityName());
244         cwork.isPersisted = workInfo->IsPersisted();
245         cwork.netWorkType = workInfo->GetNetworkType();
246         auto chargerType = workInfo->GetChargerType();
247         if (chargerType >= WorkCondition::Charger::CHARGING_UNPLUGGED) {
248             cwork.isCharging = false;
249             cwork.chargerType = -1;
250         } else {
251             cwork.isCharging = true;
252             cwork.chargerType = chargerType;
253         }
254         cwork.batteryLevel = workInfo->GetBatteryLevel();
255         cwork.batteryStatus = workInfo->GetBatteryStatus();
256         cwork.storageRequest = workInfo->GetStorageLevel();
257         cwork.isRepeat = workInfo->IsRepeat();
258         cwork.repeatCycleTime = static_cast<int32_t>(workInfo->GetTimeInterval());
259         cwork.repeatCount = workInfo->GetCycleCount();
260         cwork.isDeepIdle = -1;
261         cwork.idleWaitTime = -1;
262     }
263 
MallocCString(const std::string & origin)264     char* MallocCString(const std::string& origin)
265     {
266         if (origin.empty()) {
267             return nullptr;
268         }
269         auto len = origin.length() + 1;
270         char* res = static_cast<char*>(malloc(sizeof(char) * len));
271         if (res == nullptr) {
272             return nullptr;
273         }
274         return std::char_traits<char>::copy(res, origin.c_str(), len);
275     }
276 }
277 } // WorkScheduler
278 } // OHOS