1 /*
2 * Copyright (c) 2021 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)callbackMap_.erase(iter);
203 return callback;
204 }
205
NotifyMissionCenterResult(int32_t missionId,int32_t resultCode)206 int32_t DSchedContinuation::NotifyMissionCenterResult(int32_t missionId, int32_t resultCode)
207 {
208 sptr<IRemoteObject> callback = PopCallback(missionId);
209 RemoveTimeOut(missionId);
210 if (callback == nullptr) {
211 HILOGE("NotifyMissionCenterResult callback is null");
212 return INVALID_PARAMETERS_ERR;
213 }
214
215 MessageParcel data;
216 if (!data.WriteInterfaceToken(NAPI_MISSION_CENTER_INTERFACE_TOKEN)) {
217 HILOGE("NotifyMissionCenterResult write token failed");
218 return INVALID_PARAMETERS_ERR;
219 }
220 PARCEL_WRITE_HELPER_RET(data, Int32, resultCode, INVALID_PARAMETERS_ERR);
221 MessageParcel reply;
222 MessageOption option;
223 int32_t error = callback->SendRequest(NOTIFY_MISSION_CENTER_RESULT, data, reply, option);
224 HILOGI("NotifyMissionCenterResult transact result: %{public}d", error);
225 return error;
226 }
227
ProcessEvent(const InnerEvent::Pointer & event)228 void DSchedContinuation::ContinuationHandler::ProcessEvent(const InnerEvent::Pointer& event)
229 {
230 if (event == nullptr) {
231 HILOGE("ProcessEvent event nullptr!");
232 return;
233 }
234
235 auto eventId = event->GetInnerEventId();
236 int32_t sessionId = static_cast<int32_t>(eventId);
237 if (sessionId <= 0) {
238 HILOGW("ProcessEvent sessionId invalid!");
239 return;
240 }
241
242 if (contCallback_ != nullptr) {
243 contCallback_(sessionId);
244 }
245 }
246 } // namespace DistributedSchedule
247 } // namespace OHOS
248