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 }
30
Init(const FuncContinuationCallback & contCallback)31 void DSchedContinuation::Init(const FuncContinuationCallback& contCallback)
32 {
33 auto runner = EventRunner::Create("dsched_continuation");
34 continuationHandler_ = std::make_shared<ContinuationHandler>(runner, shared_from_this(), contCallback);
35 }
36
PushAbilityToken(int32_t sessionId,const sptr<IRemoteObject> & abilityToken)37 bool DSchedContinuation::PushAbilityToken(int32_t sessionId, const sptr<IRemoteObject>& abilityToken)
38 {
39 if (abilityToken == nullptr) {
40 HILOGE("PushAbilityToken abilityToken null!");
41 return false;
42 }
43
44 if (sessionId <= 0) {
45 HILOGE("PushAbilityToken sessionId invalid!");
46 return false;
47 }
48
49 if (continuationHandler_ == nullptr) {
50 HILOGE("PushAbilityToken not initialized!");
51 return false;
52 }
53
54 std::lock_guard<std::mutex> autoLock(continuationLock_);
55 bool ret = true;
56 ret = continuationHandler_->SendEvent(sessionId, 0, CONTINUATION_DELAY_TIME);
57 if (!ret) {
58 HILOGE("PushAbilityToken SendEvent failed!");
59 return false;
60 }
61
62 auto iterSession = continuationMap_.find(sessionId);
63 if (iterSession != continuationMap_.end()) {
64 HILOGE("PushAbilityToken sessionId:%{public}d exist!", sessionId);
65 return false;
66 }
67 (void)continuationMap_.emplace(sessionId, abilityToken);
68 return true;
69 }
70
PopAbilityToken(int32_t sessionId)71 sptr<IRemoteObject> DSchedContinuation::PopAbilityToken(int32_t sessionId)
72 {
73 if (sessionId <= 0) {
74 HILOGE("PopAbilityToken sessionId invalid");
75 return nullptr;
76 }
77
78 std::lock_guard<std::mutex> autoLock(continuationLock_);
79 auto iter = continuationMap_.find(sessionId);
80 if (iter == continuationMap_.end()) {
81 HILOGW("PopAbilityToken not found sessionId:%{public}d", sessionId);
82 return nullptr;
83 }
84 sptr<IRemoteObject> abilityToken = iter->second;
85 (void)continuationMap_.erase(iter);
86 if (continuationHandler_ != nullptr) {
87 continuationHandler_->RemoveEvent(sessionId);
88 }
89 return abilityToken;
90 }
91
GenerateSessionId()92 int32_t DSchedContinuation::GenerateSessionId()
93 {
94 std::lock_guard<std::mutex> autoLock(continuationLock_);
95 int32_t currValue = currSessionId_;
96 if (++currSessionId_ <= 0) {
97 currSessionId_ = 1;
98 }
99 return currValue;
100 }
101
SetTimeOut(int32_t missionId,int32_t timeout)102 void DSchedContinuation::SetTimeOut(int32_t missionId, int32_t timeout)
103 {
104 if (continuationHandler_ == nullptr) {
105 HILOGE("continuationHandler not initialized!");
106 return;
107 }
108 continuationHandler_->SendEvent(missionId, 0, timeout);
109 }
110
RemoveTimeOut(int32_t missionId)111 void DSchedContinuation::RemoveTimeOut(int32_t missionId)
112 {
113 if (continuationHandler_ == nullptr) {
114 HILOGE("continuationHandler not initialized!");
115 return;
116 }
117 continuationHandler_->RemoveEvent(missionId);
118 }
119
IsFreeInstall(int32_t missionId)120 bool DSchedContinuation::IsFreeInstall(int32_t missionId)
121 {
122 std::lock_guard<std::mutex> autoLock(continuationLock_);
123 auto iter = freeInstall_.find(missionId);
124 if (iter != freeInstall_.end()) {
125 HILOGD("continue free install, missionId:%{public}d exist!", missionId);
126 return iter->second;
127 }
128 return false;
129 }
130
IsInContinuationProgress(int32_t missionId)131 bool DSchedContinuation::IsInContinuationProgress(int32_t missionId)
132 {
133 std::lock_guard<std::mutex> autoLock(continuationLock_);
134 auto iterSession = callbackMap_.find(missionId);
135 if (iterSession != callbackMap_.end()) {
136 HILOGE("Continuation in progress, missionId:%{public}d exist!", missionId);
137 return true;
138 }
139 return false;
140 }
141
GetTargetDevice(int32_t missionId)142 std::string DSchedContinuation::GetTargetDevice(int32_t missionId)
143 {
144 std::lock_guard<std::mutex> autoLock(continuationLock_);
145 auto iter = continuationDevices_.find(missionId);
146 if (iter != continuationDevices_.end()) {
147 HILOGD("missionId:%{public}d exist!", missionId);
148 return iter->second;
149 }
150 return "";
151 }
152
PushCallback(int32_t missionId,const sptr<IRemoteObject> & callback,std::string deviceId,bool isFreeInstall)153 bool DSchedContinuation::PushCallback(int32_t missionId, const sptr<IRemoteObject>& callback,
154 std::string deviceId, bool isFreeInstall)
155 {
156 HILOGI("DSchedContinuation PushCallback start!");
157 if (callback == nullptr) {
158 HILOGE("callback null!");
159 return false;
160 }
161
162 if (continuationHandler_ == nullptr) {
163 HILOGE("not initialized!");
164 return false;
165 }
166
167 std::lock_guard<std::mutex> autoLock(continuationLock_);
168 auto iterSession = callbackMap_.find(missionId);
169 if (iterSession != callbackMap_.end()) {
170 HILOGE("missionId:%{public}d exist!", missionId);
171 return false;
172 }
173 (void)callbackMap_.emplace(missionId, callback);
174 (void)continuationDevices_.emplace(missionId, deviceId);
175 if (isFreeInstall) {
176 freeInstall_[missionId] = isFreeInstall;
177 }
178 return true;
179 }
180
PopCallback(int32_t missionId)181 sptr<IRemoteObject> DSchedContinuation::PopCallback(int32_t missionId)
182 {
183 std::lock_guard<std::mutex> autoLock(continuationLock_);
184 auto iter = callbackMap_.find(missionId);
185 if (iter == callbackMap_.end()) {
186 HILOGW("PopCallback not found missionId:%{public}d", missionId);
187 return nullptr;
188 }
189 sptr<IRemoteObject> callback = iter->second;
190
191 auto iteration = continuationDevices_.find(missionId);
192 if (iteration != continuationDevices_.end()) {
193 HILOGD("%{public}d need pop from continuationDevices_", missionId);
194 (void)continuationDevices_.erase(iteration);
195 }
196
197 auto it = freeInstall_.find(missionId);
198 if (it != freeInstall_.end()) {
199 HILOGD("%{public}d need pop from freeInstall_", missionId);
200 (void)freeInstall_.erase(it);
201 }
202 (void)cleanMission_.erase(missionId);
203 (void)callbackMap_.erase(iter);
204 return callback;
205 }
206
NotifyMissionCenterResult(int32_t missionId,int32_t resultCode)207 int32_t DSchedContinuation::NotifyMissionCenterResult(int32_t missionId, int32_t resultCode)
208 {
209 sptr<IRemoteObject> callback = PopCallback(missionId);
210 RemoveTimeOut(missionId);
211 if (callback == nullptr) {
212 HILOGE("NotifyMissionCenterResult callback is null");
213 return INVALID_PARAMETERS_ERR;
214 }
215
216 MessageParcel data;
217 if (!data.WriteInterfaceToken(NAPI_MISSION_CENTER_INTERFACE_TOKEN)) {
218 HILOGE("NotifyMissionCenterResult write token failed");
219 return INVALID_PARAMETERS_ERR;
220 }
221 PARCEL_WRITE_HELPER_RET(data, Int32, resultCode, INVALID_PARAMETERS_ERR);
222 MessageParcel reply;
223 MessageOption option;
224 int32_t error = callback->SendRequest(NOTIFY_MISSION_CENTER_RESULT, data, reply, option);
225 HILOGI("NotifyMissionCenterResult transact result: %{public}d", error);
226 return error;
227 }
228
ProcessEvent(const InnerEvent::Pointer & event)229 void DSchedContinuation::ContinuationHandler::ProcessEvent(const InnerEvent::Pointer& event)
230 {
231 if (event == nullptr) {
232 HILOGE("ProcessEvent event nullptr!");
233 return;
234 }
235
236 auto eventId = event->GetInnerEventId();
237 int32_t sessionId = static_cast<int32_t>(eventId);
238 if (sessionId <= 0) {
239 HILOGW("ProcessEvent sessionId invalid!");
240 return;
241 }
242
243 if (contCallback_ != nullptr) {
244 contCallback_(sessionId);
245 }
246 }
247
SetCleanMissionFlag(int32_t missionId,bool isCleanMission)248 void DSchedContinuation::SetCleanMissionFlag(int32_t missionId, bool isCleanMission)
249 {
250 std::lock_guard<std::mutex> autoLock(continuationLock_);
251 cleanMission_.emplace(missionId, isCleanMission);
252 }
253
IsCleanMission(int32_t missionId)254 bool DSchedContinuation::IsCleanMission(int32_t missionId)
255 {
256 std::lock_guard<std::mutex> autoLock(continuationLock_);
257 auto iter = cleanMission_.find(missionId);
258 if (iter != cleanMission_.end()) {
259 HILOGD("Application need not exit after continue, missionId:%{public}d exist!", missionId);
260 return iter->second;
261 }
262 return true;
263 }
264 } // namespace DistributedSchedule
265 } // namespace OHOS
266