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 #include "work_sched_service_stub.h"
16 
17 #include <message_parcel.h>
18 #include <string_ex.h>
19 
20 #include "work_sched_common.h"
21 #include "work_sched_errors.h"
22 
23 #ifdef HICOLLIE_ENABLE
24 #include "xcollie/xcollie.h"
25 #include "xcollie/xcollie_define.h"
26 #define XCOLLIE_TIMEOUT_SECONDS 10
27 #endif
28 
29 namespace OHOS {
30 namespace WorkScheduler {
HandleObtainAllWorksRequest(MessageParcel & data,MessageParcel & reply)31 int32_t WorkSchedServiceStub::HandleObtainAllWorksRequest(MessageParcel &data, MessageParcel &reply)
32 {
33     std::list<std::shared_ptr<WorkInfo>> workInfos;
34     int32_t ret = ObtainAllWorksStub(data, workInfos);
35     uint32_t worksize = workInfos.size();
36     reply.WriteInt32(ret);
37     reply.WriteInt32(worksize);
38     for (auto workInfo : workInfos) {
39         reply.WriteParcelable(&*workInfo);
40     }
41     return ERR_OK;
42 }
43 
HandleGetWorkStatusRequest(MessageParcel & data,MessageParcel & reply)44 int32_t WorkSchedServiceStub::HandleGetWorkStatusRequest(MessageParcel &data, MessageParcel &reply)
45 {
46     WS_HILOGI("call GetWorkStatus");
47     std::shared_ptr<WorkInfo> workInfo;
48     int32_t ret = GetWorkStatusStub(data, workInfo);
49     reply.WriteInt32(ret);
50     reply.WriteParcelable(&*workInfo);
51     return ERR_OK;
52 }
53 
HandleGetAllRunningWorksRequest(MessageParcel & reply)54 int32_t WorkSchedServiceStub::HandleGetAllRunningWorksRequest(MessageParcel &reply)
55 {
56     std::list<std::shared_ptr<WorkInfo>> workInfos;
57     int32_t ret = GetAllRunningWorksStub(workInfos);
58     uint32_t worksize = workInfos.size();
59     reply.WriteInt32(ret);
60     reply.WriteInt32(worksize);
61     for (auto workInfo : workInfos) {
62         reply.WriteParcelable(&*workInfo);
63     }
64     return ERR_OK;
65 }
66 
HandleIsLastWorkTimeOutRequest(MessageParcel & data,MessageParcel & reply)67 int32_t WorkSchedServiceStub::HandleIsLastWorkTimeOutRequest(MessageParcel &data, MessageParcel &reply)
68 {
69     bool isLastWorkTimeout;
70     int32_t ret = IsLastWorkTimeoutStub(data, isLastWorkTimeout);
71     if (!reply.WriteInt32(ret)) {
72         WS_HILOGE("Handle IsLastWorkTimeOut request failed, write result error");
73         return E_PARCEL_OPERATION_FAILED;
74     }
75 
76     if (!reply.WriteBool(isLastWorkTimeout)) {
77         WS_HILOGE("Handle IsLastWorkTimeOut request failed, write result error");
78         return E_PARCEL_OPERATION_FAILED;
79     }
80     return ret;
81 }
82 
HandleSetWorkSchedulerConfig(MessageParcel & data,MessageParcel & reply)83 int32_t WorkSchedServiceStub::HandleSetWorkSchedulerConfig(MessageParcel &data, MessageParcel &reply)
84 {
85     std::string configData;
86     if (!data.ReadString(configData)) {
87         WS_HILOGE("HandleSetWorkSchedulerConfig read parce configData error");
88         return E_PARCEL_OPERATION_FAILED;
89     }
90     int32_t sourceType;
91     if (!data.ReadInt32(sourceType)) {
92         WS_HILOGE("HandleSetWorkSchedulerConfig read parce sourceType error");
93         return E_PARCEL_OPERATION_FAILED;
94     }
95     int32_t ret = SetWorkSchedulerConfig(configData, sourceType);
96     if (!reply.WriteInt32(ret)) {
97         WS_HILOGE("HandleSetWorkSchedulerConfig write result failed, Errcode=%{public}d", ret);
98         return E_PARCEL_OPERATION_FAILED;
99     }
100     return ret;
101 }
102 
HandleRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)103 int32_t WorkSchedServiceStub::HandleRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
104     MessageOption &option)
105 {
106     switch (code) {
107         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::START_WORK): {
108             int32_t ret = StartWorkStub(data);
109             reply.WriteInt32(ret);
110             return ret;
111         }
112         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::STOP_WORK): {
113             int32_t ret = StopWorkStub(data);
114             reply.WriteInt32(ret);
115             return ret;
116         }
117         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::STOP_AND_CANCEL_WORK): {
118             int32_t ret = StopAndCancelWorkStub(data);
119             reply.WriteInt32(ret);
120             return ret;
121         }
122         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::STOP_AND_CLEAR_WORKS): {
123             int32_t ret = StopAndClearWorksStub(data);
124             reply.WriteInt32(ret);
125             return ret;
126         }
127         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::IS_LAST_WORK_TIMEOUT): {
128             return HandleIsLastWorkTimeOutRequest(data, reply);
129         }
130         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::OBTAIN_ALL_WORKS): {
131             return HandleObtainAllWorksRequest(data, reply);
132         }
133         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::GET_WORK_STATUS): {
134             return HandleGetWorkStatusRequest(data, reply);
135         }
136         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::GET_ALL_RUNNING_WORKS): {
137             return HandleGetAllRunningWorksRequest(reply);
138         }
139         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::PAUSE_RUNNING_WORKS): {
140             return PauseRunningWorksStub(data, reply);
141         }
142         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::RESUME_PAUSED_WORKS): {
143             return ResumePausedWorksStub(data, reply);
144         }
145         case static_cast<int32_t>(IWorkSchedServiceInterfaceCode::SET_WORK_SCHEDULER_CONFIG): {
146             return HandleSetWorkSchedulerConfig(data, reply);
147         }
148         default: {
149             WS_HILOGD("OnRemoteRequest switch default, code: %{public}u", code);
150             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
151         }
152     }
153     return ERR_OK;
154 }
155 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)156 int32_t WorkSchedServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
157     MessageOption &option)
158 {
159     WS_HILOGD("cmd = %{public}u, flags = %{public}d", code, option.GetFlags());
160     std::u16string descriptor = WorkSchedServiceStub::GetDescriptor();
161     std::u16string remoteDescriptor = data.ReadInterfaceToken();
162     if (descriptor != remoteDescriptor) {
163         WS_HILOGE("failed, descriptor is not matched!");
164         return E_PARCEL_OPERATION_FAILED;
165     }
166     int32_t idTimer = SetTimer(code);
167     int32_t result = HandleRequest(code, data, reply, option);
168     CancelTimer(idTimer);
169     return result;
170 }
171 
StartWorkStub(MessageParcel & data)172 int32_t WorkSchedServiceStub::StartWorkStub(MessageParcel& data)
173 {
174     sptr<WorkInfo> workInfo = data.ReadStrongParcelable<WorkInfo>();
175     if (workInfo == nullptr) {
176         WS_HILOGD("workInfo is nullptr");
177         return E_PARCEL_OPERATION_FAILED;
178     }
179     return StartWork(*workInfo);
180 }
181 
StopWorkStub(MessageParcel & data)182 int32_t WorkSchedServiceStub::StopWorkStub(MessageParcel& data)
183 {
184     sptr<WorkInfo> workInfo = data.ReadStrongParcelable<WorkInfo>();
185     if (workInfo == nullptr) {
186         WS_HILOGD("workInfo is nullptr");
187         return E_PARCEL_OPERATION_FAILED;
188     }
189     return StopWork(*workInfo);
190 }
191 
StopAndCancelWorkStub(MessageParcel & data)192 int32_t WorkSchedServiceStub::StopAndCancelWorkStub(MessageParcel& data)
193 {
194     sptr<WorkInfo> workInfo = data.ReadStrongParcelable<WorkInfo>();
195     if (workInfo == nullptr) {
196         WS_HILOGD("workInfo is nullptr");
197         return E_PARCEL_OPERATION_FAILED;
198     }
199     return StopAndCancelWork(*workInfo);
200 }
201 
StopAndClearWorksStub(MessageParcel & data)202 int32_t WorkSchedServiceStub::StopAndClearWorksStub(MessageParcel& data)
203 {
204     return StopAndClearWorks();
205 }
206 
IsLastWorkTimeoutStub(MessageParcel & data,bool & result)207 int32_t WorkSchedServiceStub::IsLastWorkTimeoutStub(MessageParcel& data, bool &result)
208 {
209     int32_t workId = data.ReadInt32();
210     return IsLastWorkTimeout(workId, result);
211 }
212 
ObtainAllWorksStub(MessageParcel & data,std::list<std::shared_ptr<WorkInfo>> & workInfos)213 int32_t WorkSchedServiceStub::ObtainAllWorksStub(MessageParcel& data, std::list<std::shared_ptr<WorkInfo>>& workInfos)
214 {
215     return ObtainAllWorks(workInfos);
216 }
217 
GetWorkStatusStub(MessageParcel & data,std::shared_ptr<WorkInfo> & workInfo)218 int32_t WorkSchedServiceStub::GetWorkStatusStub(MessageParcel& data, std::shared_ptr<WorkInfo>& workInfo)
219 {
220     int32_t workId;
221     READ_PARCEL_WITHOUT_RET(data, Int32, workId);
222     return GetWorkStatus(workId, workInfo);
223 }
224 
GetAllRunningWorksStub(std::list<std::shared_ptr<WorkInfo>> & workInfos)225 int32_t WorkSchedServiceStub::GetAllRunningWorksStub(std::list<std::shared_ptr<WorkInfo>>& workInfos)
226 {
227     return GetAllRunningWorks(workInfos);
228 }
229 
PauseRunningWorksStub(MessageParcel & data,MessageParcel & reply)230 int32_t WorkSchedServiceStub::PauseRunningWorksStub(MessageParcel& data, MessageParcel& reply)
231 {
232     int32_t uid = -1;
233     if (!data.ReadInt32(uid)) {
234         WS_HILOGE("PauseRunningWorksStub failed, read uid error");
235         return E_PARCEL_OPERATION_FAILED;
236     }
237     int32_t ret = PauseRunningWorks(uid);
238     if (!reply.WriteInt32(ret)) {
239         WS_HILOGE("PauseRunningWorksStub failed, write result error");
240         return E_PARCEL_OPERATION_FAILED;
241     }
242     return ret;
243 }
244 
ResumePausedWorksStub(MessageParcel & data,MessageParcel & reply)245 int32_t WorkSchedServiceStub::ResumePausedWorksStub(MessageParcel& data, MessageParcel& reply)
246 {
247     int32_t uid = -1;
248     if (!data.ReadInt32(uid)) {
249         WS_HILOGE("ResumePausedWorksStub failed, read uid error");
250         return E_PARCEL_OPERATION_FAILED;
251     }
252     int32_t ret = ResumePausedWorks(uid);
253     if (!reply.WriteInt32(ret)) {
254         WS_HILOGE("ResumePausedWorksStub failed, write result error");
255         return E_PARCEL_OPERATION_FAILED;
256     }
257     return ret;
258 }
259 
SetTimer(uint32_t code)260 int32_t WorkSchedServiceStub::SetTimer(uint32_t code)
261 {
262 #ifdef HICOLLIE_ENABLE
263     int32_t idTimer = HiviewDFX::INVALID_ID;
264     std::map<uint32_t, std::string>::iterator itCollieId = collieCodeStringMap_.find(code);
265     if (itCollieId != collieCodeStringMap_.end()) {
266         std::string collieStr = itCollieId->second;
267         std::string collieName = "WorkSchedulerServiceStub:" + collieStr;
268         unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY;
269         auto TimerCallback = [collieStr](void *) {
270             WS_HILOGE("OnRemoteRequest timeout func: %{public}s", collieStr.c_str());
271         };
272         idTimer = HiviewDFX::XCollie::GetInstance().SetTimer(
273             collieName, XCOLLIE_TIMEOUT_SECONDS, TimerCallback, nullptr, flag);
274         WS_HILOGD("SetTimer id: %{public}d, name: %{public}s.", idTimer, collieName.c_str());
275     }
276     return idTimer;
277 #else
278     WS_HILOGD("No HICOLLIE_ENABLE");
279     return -1;
280 #endif
281 }
282 
CancelTimer(int32_t id)283 void WorkSchedServiceStub::CancelTimer(int32_t id)
284 {
285 #ifdef HICOLLIE_ENABLE
286     if (id == HiviewDFX::INVALID_ID) {
287         return;
288     }
289     WS_HILOGD("CancelTimer id: %{public}d.", id);
290     HiviewDFX::XCollie::GetInstance().CancelTimer(id);
291 #else
292     return;
293 #endif
294 }
295 } // namespace WorkScheduler
296 } // namespace OHOS