• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "distributed_sched_continuation.h"
17 #include "dtbschedmgr_log.h"
18 #include "parcel_helper.h"
19 
20 using namespace OHOS::AppExecFwk;
21 
22 namespace OHOS {
23 namespace DistributedSchedule {
24 namespace {
25 constexpr int64_t CONTINUATION_DELAY_TIME = 20000;
26 const std::string TAG = "DSchedContinuation";
27 const std::u16string NAPI_MISSION_CENTER_INTERFACE_TOKEN = u"ohos.DistributedSchedule.IMissionCallback";
28 constexpr int32_t NOTIFY_MISSION_CENTER_RESULT = 4;
29 const std::u16string DSCHED_EVENT_TOKEN = u"ohos.distributedSchedule.dschedeventlistener";
30 constexpr int32_t DSCHED_EVENT_CALLBACK = 0;
31 }
32 
Init(const FuncContinuationCallback & contCallback)33 void DSchedContinuation::Init(const FuncContinuationCallback& contCallback)
34 {
35     auto runner = EventRunner::Create("dsched_continuation");
36     continuationHandler_ = std::make_shared<ContinuationHandler>(runner, shared_from_this(), contCallback);
37     diedListener_ = new DistributedEventDiedListener();
38 }
39 
PushAbilityToken(int32_t sessionId,const sptr<IRemoteObject> & abilityToken)40 bool DSchedContinuation::PushAbilityToken(int32_t sessionId, const sptr<IRemoteObject>& abilityToken)
41 {
42     if (abilityToken == nullptr) {
43         HILOGE("PushAbilityToken abilityToken null!");
44         return false;
45     }
46 
47     if (sessionId <= 0) {
48         HILOGE("PushAbilityToken sessionId invalid!");
49         return false;
50     }
51 
52     if (continuationHandler_ == nullptr) {
53         HILOGE("PushAbilityToken not initialized!");
54         return false;
55     }
56 
57     std::lock_guard<std::mutex> autoLock(continuationLock_);
58     bool ret = true;
59     ret = continuationHandler_->SendEvent(sessionId, 0, CONTINUATION_DELAY_TIME);
60     if (!ret) {
61         HILOGE("PushAbilityToken SendEvent failed!");
62         return false;
63     }
64 
65     auto iterSession = continuationMap_.find(sessionId);
66     if (iterSession != continuationMap_.end()) {
67         HILOGE("PushAbilityToken sessionId:%{public}d exist!", sessionId);
68         return false;
69     }
70     (void)continuationMap_.emplace(sessionId, abilityToken);
71     return true;
72 }
73 
PopAbilityToken(int32_t sessionId)74 sptr<IRemoteObject> DSchedContinuation::PopAbilityToken(int32_t sessionId)
75 {
76     if (sessionId <= 0) {
77         HILOGE("PopAbilityToken sessionId invalid");
78         return nullptr;
79     }
80 
81     std::lock_guard<std::mutex> autoLock(continuationLock_);
82     auto iter = continuationMap_.find(sessionId);
83     if (iter == continuationMap_.end()) {
84         HILOGW("PopAbilityToken not found sessionId:%{public}d", sessionId);
85         return nullptr;
86     }
87     sptr<IRemoteObject> abilityToken = iter->second;
88     (void)continuationMap_.erase(iter);
89     if (continuationHandler_ != nullptr) {
90         continuationHandler_->RemoveEvent(sessionId);
91     }
92     return abilityToken;
93 }
94 
GenerateSessionId()95 int32_t DSchedContinuation::GenerateSessionId()
96 {
97     std::lock_guard<std::mutex> autoLock(continuationLock_);
98     int32_t currValue = currSessionId_;
99     if (++currSessionId_ <= 0) {
100         currSessionId_ = 1;
101     }
102     return currValue;
103 }
104 
SetTimeOut(int32_t missionId,int32_t timeout)105 void DSchedContinuation::SetTimeOut(int32_t missionId, int32_t timeout)
106 {
107     if (continuationHandler_ == nullptr) {
108         HILOGE("continuationHandler not initialized!");
109         return;
110     }
111     continuationHandler_->SendEvent(missionId, 0, timeout);
112 }
113 
RemoveTimeOut(int32_t missionId)114 void DSchedContinuation::RemoveTimeOut(int32_t missionId)
115 {
116     if (continuationHandler_ == nullptr) {
117         HILOGE("continuationHandler not initialized!");
118         return;
119     }
120     continuationHandler_->RemoveEvent(missionId);
121 }
122 
IsFreeInstall(int32_t missionId)123 bool DSchedContinuation::IsFreeInstall(int32_t missionId)
124 {
125     std::lock_guard<std::mutex> autoLock(continuationLock_);
126     auto iter = freeInstall_.find(missionId);
127     if (iter != freeInstall_.end()) {
128         HILOGD("continue free install, missionId:%{public}d exist!", missionId);
129         return iter->second;
130     }
131     return false;
132 }
133 
IsInContinuationProgress(int32_t missionId)134 bool DSchedContinuation::IsInContinuationProgress(int32_t missionId)
135 {
136     std::lock_guard<std::mutex> autoLock(continuationLock_);
137     auto iterSession = callbackMap_.find(missionId);
138     if (iterSession != callbackMap_.end()) {
139         HILOGD("Continuation in progress, missionId:%{public}d exist!", missionId);
140         return true;
141     }
142     return false;
143 }
144 
GetTargetDevice(int32_t missionId)145 std::string DSchedContinuation::GetTargetDevice(int32_t missionId)
146 {
147     std::lock_guard<std::mutex> autoLock(continuationLock_);
148     auto iter = continuationDevices_.find(missionId);
149     if (iter != continuationDevices_.end()) {
150         HILOGD("missionId:%{public}d exist!", missionId);
151         return iter->second;
152     }
153     return "";
154 }
155 
PushCallback(const std::string & type,const sptr<IRemoteObject> & callback)156 bool DSchedContinuation::PushCallback(const std::string& type, const sptr<IRemoteObject>& callback)
157 {
158     if (continuationHandler_ == nullptr) {
159         HILOGE("not initialized!");
160         return false;
161     }
162     HILOGI("DSchedContinuation PushCallback start!");
163     if (callback == nullptr) {
164         HILOGE("callback null!");
165         return false;
166     }
167     std::lock_guard<std::mutex> autoLock(continuationLock_);
168     std::vector<sptr<IRemoteObject>> vecCallback = continuationCallbackMap_[type];
169     for (auto ele = vecCallback.begin(); ele != vecCallback.end(); ++ele) {
170         if ((*ele) == callback) {
171             HILOGE("type:%{public}s, callback already  exists!", type.c_str());
172             return false;
173         }
174     }
175     vecCallback.push_back(callback);
176     continuationCallbackMap_[type] = vecCallback;
177     callback->AddDeathRecipient(diedListener_);
178     return true;
179 }
180 
PushCallback(int32_t missionId,const sptr<IRemoteObject> & callback,std::string deviceId,bool isFreeInstall)181 bool DSchedContinuation::PushCallback(int32_t missionId, const sptr<IRemoteObject>& callback,
182     std::string deviceId, bool isFreeInstall)
183 {
184     HILOGI("DSchedContinuation PushCallback start!");
185     if (callback == nullptr) {
186         HILOGE("callback null!");
187         return false;
188     }
189 
190     if (continuationHandler_ == nullptr) {
191         HILOGE("not initialized!");
192         return false;
193     }
194 
195     std::lock_guard<std::mutex> autoLock(continuationLock_);
196     auto iterSession = callbackMap_.find(missionId);
197     if (iterSession != callbackMap_.end()) {
198         HILOGE("missionId:%{public}d exist!", missionId);
199         return false;
200     }
201     (void)callbackMap_.emplace(missionId, callback);
202     (void)continuationDevices_.emplace(missionId, deviceId);
203     if (isFreeInstall) {
204         freeInstall_[missionId] = isFreeInstall;
205     }
206     return true;
207 }
208 
GetCallback(const std::string & type)209 std::vector<sptr<IRemoteObject>> DSchedContinuation::GetCallback(const std::string& type)
210 {
211     std::lock_guard<std::mutex> autoLock(continuationLock_);
212     return continuationCallbackMap_[type];
213 }
214 
CleanupCallback(const std::string & type,const sptr<IRemoteObject> & callback)215 bool DSchedContinuation::CleanupCallback(const std::string& type, const sptr<IRemoteObject>& callback)
216 {
217     std::lock_guard<std::mutex> autoLock(continuationLock_);
218     std::vector<sptr<IRemoteObject>> vecCallback = continuationCallbackMap_[type];
219     if (vecCallback.empty()) {
220         HILOGE("PopCallback not found, type:%{public}s", type.c_str());
221         return false;
222     }
223     for (auto ele = vecCallback.begin(); ele != vecCallback.end(); ++ele) {
224         if ((*ele) == callback) {
225             vecCallback.erase(ele);
226             continuationCallbackMap_[type] = vecCallback;
227             HILOGI("type:%{public}s, callback is exists, cleared successfully.", type.c_str());
228             return true;
229         }
230     }
231     HILOGI("type:%{public}s, callback is not exists!", type.c_str());
232     return false;
233 }
234 
PopCallback(int32_t missionId)235 sptr<IRemoteObject> DSchedContinuation::PopCallback(int32_t missionId)
236 {
237     std::lock_guard<std::mutex> autoLock(continuationLock_);
238     auto iter = callbackMap_.find(missionId);
239     if (iter == callbackMap_.end()) {
240         HILOGW("PopCallback not found missionId:%{public}d", missionId);
241         return nullptr;
242     }
243     sptr<IRemoteObject> callback = iter->second;
244 
245     auto iteration = continuationDevices_.find(missionId);
246     if (iteration != continuationDevices_.end()) {
247         HILOGD("%{public}d need pop from continuationDevices_", missionId);
248         (void)continuationDevices_.erase(iteration);
249     }
250 
251     auto it = freeInstall_.find(missionId);
252     if (it != freeInstall_.end()) {
253         HILOGD("%{public}d need pop from freeInstall_", missionId);
254         (void)freeInstall_.erase(it);
255     }
256     (void)cleanMission_.erase(missionId);
257     (void)callbackMap_.erase(iter);
258     return callback;
259 }
260 
NotifyDSchedEventResult(const std::string & type,int32_t resultCode)261 int32_t DSchedContinuation::NotifyDSchedEventResult(const std::string& type, int32_t resultCode)
262 {
263     HILOGI("GetCallback IDSchedEventListener");
264     std::vector<sptr<IRemoteObject>> vecCallback = GetCallback(type);
265     if (vecCallback.empty()) {
266         HILOGD("No listening has been registered, no need to report events");
267         return INVALID_PARAMETERS_ERR;
268     }
269     int32_t error = -1;
270     for (auto callback = vecCallback.begin(); callback != vecCallback.end(); ++callback) {
271         MessageParcel data;
272         if (!data.WriteInterfaceToken(DSCHED_EVENT_TOKEN)) {
273             HILOGE("NotifyMissionCenterResult write token failed");
274             return INVALID_PARAMETERS_ERR;
275         }
276         PARCEL_WRITE_HELPER_RET(data, Int32, resultCode, false);
277         PARCEL_WRITE_HELPER_RET(data, String, continueEvent_.srcNetworkId, false);
278         PARCEL_WRITE_HELPER_RET(data, String, continueEvent_.dstNetworkId, false);
279         PARCEL_WRITE_HELPER_RET(data, String, continueEvent_.bundleName, false);
280         PARCEL_WRITE_HELPER_RET(data, String, continueEvent_.moduleName, false);
281         PARCEL_WRITE_HELPER_RET(data, String, continueEvent_.abilityName, false);
282         MessageParcel reply;
283         MessageOption option;
284         error = (*callback)->SendRequest(DSCHED_EVENT_CALLBACK, data, reply, option);
285         HILOGI("NotifyDSchedEventListenerResult transact result: %{public}d", error);
286     }
287     return error;
288 }
289 
NotifyMissionCenterResult(int32_t missionId,int32_t resultCode)290 int32_t DSchedContinuation::NotifyMissionCenterResult(int32_t missionId, int32_t resultCode)
291 {
292     sptr<IRemoteObject> callback = PopCallback(missionId);
293     RemoveTimeOut(missionId);
294     if (callback == nullptr) {
295         HILOGE("NotifyMissionCenterResult callback is null");
296         return INVALID_PARAMETERS_ERR;
297     }
298 
299     MessageParcel data;
300     if (!data.WriteInterfaceToken(NAPI_MISSION_CENTER_INTERFACE_TOKEN)) {
301         HILOGE("NotifyMissionCenterResult write token failed");
302         return INVALID_PARAMETERS_ERR;
303     }
304     PARCEL_WRITE_HELPER_RET(data, Int32, resultCode, INVALID_PARAMETERS_ERR);
305     MessageParcel reply;
306     MessageOption option;
307     int32_t error = callback->SendRequest(NOTIFY_MISSION_CENTER_RESULT, data, reply, option);
308     HILOGI("NotifyMissionCenterResult transact result: %{public}d", error);
309     return error;
310 }
311 
ProcessEvent(const InnerEvent::Pointer & event)312 void DSchedContinuation::ContinuationHandler::ProcessEvent(const InnerEvent::Pointer& event)
313 {
314     if (event == nullptr) {
315         HILOGE("ProcessEvent event nullptr!");
316         return;
317     }
318 
319     auto eventId = event->GetInnerEventId();
320     int32_t sessionId = static_cast<int32_t>(eventId);
321     if (sessionId <= 0) {
322         HILOGW("ProcessEvent sessionId invalid!");
323         return;
324     }
325 
326     if (contCallback_ != nullptr) {
327         contCallback_(sessionId);
328     }
329 }
330 
SetCleanMissionFlag(int32_t missionId,bool isCleanMission)331 void DSchedContinuation::SetCleanMissionFlag(int32_t missionId, bool isCleanMission)
332 {
333     std::lock_guard<std::mutex> autoLock(continuationLock_);
334     cleanMission_.emplace(missionId, isCleanMission);
335 }
336 
IsCleanMission(int32_t missionId)337 bool DSchedContinuation::IsCleanMission(int32_t missionId)
338 {
339     std::lock_guard<std::mutex> autoLock(continuationLock_);
340     auto iter = cleanMission_.find(missionId);
341     if (iter != cleanMission_.end()) {
342         HILOGD("Application need not exit after continue, missionId:%{public}d exist!", missionId);
343         return iter->second;
344     }
345     return true;
346 }
347 } // namespace DistributedSchedule
348 } // namespace OHOS
349