1 /*
2 * Copyright (c) 2023-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 "continuation_handler_stage.h"
17
18 #include "ability_manager_client.h"
19 #include "context/application_context.h"
20 #include "distributed_errors.h"
21 #include "element_name.h"
22 #include "hilog_tag_wrapper.h"
23
24 using OHOS::AAFwk::WantParams;
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 const std::string ORIGINAL_DEVICE_ID("deviceId");
29 const std::string VERSION_CODE_KEY = "version";
30 }
31
ContinuationHandlerStage(const std::weak_ptr<ContinuationManagerStage> & continuationManager,const std::weak_ptr<AbilityRuntime::UIAbility> & uiAbility)32 ContinuationHandlerStage::ContinuationHandlerStage(
33 const std::weak_ptr<ContinuationManagerStage> &continuationManager,
34 const std::weak_ptr<AbilityRuntime::UIAbility> &uiAbility)
35 : ability_(uiAbility), continuationManager_(continuationManager) {}
36
HandleStartContinuationWithStack(const sptr<IRemoteObject> & token,const std::string & deviceId,uint32_t versionCode)37 bool ContinuationHandlerStage::HandleStartContinuationWithStack(
38 const sptr<IRemoteObject> &token, const std::string &deviceId, uint32_t versionCode)
39 {
40 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
41 if (token == nullptr) {
42 TAG_LOGE(AAFwkTag::CONTINUATION, "Token is null");
43 return false;
44 }
45 if (abilityInfo_ == nullptr) {
46 TAG_LOGE(AAFwkTag::CONTINUATION, "AbilityInfo is null");
47 return false;
48 }
49
50 abilityInfo_->deviceId = deviceId;
51
52 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
53 continuationManagerTmp = continuationManager_.lock();
54 if (continuationManagerTmp == nullptr) {
55 TAG_LOGE(AAFwkTag::CONTINUATION, "ContinuationManagerTmp is nullptr");
56 return false;
57 }
58
59 // decided to start continuation. Callback to ability.
60 Want want;
61 want.SetParam(VERSION_CODE_KEY, static_cast<int32_t>(versionCode));
62 want.SetParam("targetDevice", deviceId);
63 WantParams wantParams = want.GetParams();
64 int32_t status = continuationManagerTmp->OnContinue(wantParams);
65 if (status != ERR_OK) {
66 TAG_LOGE(AAFwkTag::CONTINUATION,
67 "OnContinue failed, BundleName = %{public}s, ClassName= %{public}s, status: %{public}d",
68 abilityInfo_->bundleName.c_str(), abilityInfo_->name.c_str(), status);
69 }
70
71 want.SetParams(wantParams);
72 want.AddFlags(want.FLAG_ABILITY_CONTINUATION);
73 want.SetElementName(deviceId, abilityInfo_->bundleName, abilityInfo_->name, abilityInfo_->moduleName);
74
75 int result = AAFwk::AbilityManagerClient::GetInstance()->StartContinuation(want, token, status);
76 if (result != ERR_OK) {
77 TAG_LOGE(AAFwkTag::CONTINUATION, "StartContinuation failed");
78 return false;
79 }
80 return true;
81 }
82
HandleStartContinuation(const sptr<IRemoteObject> & token,const std::string & deviceId)83 bool ContinuationHandlerStage::HandleStartContinuation(const sptr<IRemoteObject> &token, const std::string &deviceId)
84 {
85 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
86 if (token == nullptr) {
87 TAG_LOGE(AAFwkTag::CONTINUATION, "Token is null");
88 return false;
89 }
90 if (abilityInfo_ == nullptr) {
91 TAG_LOGE(AAFwkTag::CONTINUATION, "AbilityInfo is null");
92 return false;
93 }
94
95 abilityInfo_->deviceId = deviceId;
96
97 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
98 continuationManagerTmp = continuationManager_.lock();
99 if (continuationManagerTmp == nullptr) {
100 TAG_LOGE(AAFwkTag::CONTINUATION, "continuationManagerTmp is nullptr");
101 return false;
102 }
103
104 // DMS decided to start continuation. Callback to ability.
105 if (!continuationManagerTmp->StartContinuation()) {
106 TAG_LOGE(AAFwkTag::CONTINUATION, "Ability rejected, BundleName = %{public}s, ClassName= %{public}s",
107 abilityInfo_->bundleName.c_str(), abilityInfo_->name.c_str());
108 return false;
109 }
110
111 WantParams wantParams;
112 if (!continuationManagerTmp->SaveData(wantParams)) {
113 TAG_LOGE(AAFwkTag::CONTINUATION, "ScheduleSaveData failed, BundleName = %{public}s, ClassName= %{public}s",
114 abilityInfo_->bundleName.c_str(), abilityInfo_->name.c_str());
115 return false;
116 }
117
118 Want want = SetWantParams(wantParams);
119 want.SetElementName(deviceId, abilityInfo_->bundleName, abilityInfo_->name, abilityInfo_->moduleName);
120
121 int result = AAFwk::AbilityManagerClient::GetInstance()->StartContinuation(want, token, 0);
122 if (result != 0) {
123 TAG_LOGE(AAFwkTag::CONTINUATION, "startContinuation failed");
124 return false;
125 }
126 return true;
127 }
128
HandleReceiveRemoteScheduler(const sptr<IRemoteObject> & remoteReplica)129 void ContinuationHandlerStage::HandleReceiveRemoteScheduler(const sptr<IRemoteObject> &remoteReplica)
130 {
131 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
132 if (remoteReplica == nullptr) {
133 TAG_LOGE(AAFwkTag::CONTINUATION, "scheduler is nullptr");
134 return;
135 }
136
137 if (remoteReplicaProxy_ != nullptr && schedulerDeathRecipient_ != nullptr) {
138 auto schedulerObjectTmp = remoteReplicaProxy_->AsObject();
139 if (schedulerObjectTmp != nullptr) {
140 schedulerObjectTmp->RemoveDeathRecipient(schedulerDeathRecipient_);
141 }
142 }
143
144 if (schedulerDeathRecipient_ == nullptr) {
145 schedulerDeathRecipient_ = new (std::nothrow) ReverseContinuationSchedulerRecipient(
146 [this](const wptr<IRemoteObject> &arg) {
147 this->OnReplicaDied(arg);
148 });
149 }
150
151 remoteReplicaProxy_ = iface_cast<IReverseContinuationSchedulerReplica>(remoteReplica);
152 auto schedulerObject = remoteReplicaProxy_->AsObject();
153 if (schedulerObject == nullptr || !schedulerObject->AddDeathRecipient(schedulerDeathRecipient_)) {
154 TAG_LOGE(AAFwkTag::CONTINUATION, "AddDeathRcipient failed");
155 }
156
157 remoteReplicaProxy_->PassPrimary(remotePrimaryStub_);
158 }
159
HandleCompleteContinuation(int result)160 void ContinuationHandlerStage::HandleCompleteContinuation(int result)
161 {
162 TAG_LOGD(AAFwkTag::CONTINUATION, "begin");
163 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
164 continuationManagerTmp = continuationManager_.lock();
165 if (continuationManagerTmp == nullptr) {
166 TAG_LOGE(AAFwkTag::CONTINUATION, "ContinuationManagerTmp is nullptr.");
167 return;
168 }
169
170 continuationManagerTmp->CompleteContinuation(result);
171 }
172
SetReversible(bool reversible)173 void ContinuationHandlerStage::SetReversible(bool reversible)
174 {
175 reversible_ = reversible;
176 }
177
SetAbilityInfo(std::shared_ptr<AbilityInfo> & abilityInfo)178 void ContinuationHandlerStage::SetAbilityInfo(std::shared_ptr<AbilityInfo> &abilityInfo)
179 {
180 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
181 abilityInfo_ = std::make_shared<AbilityInfo>(*(abilityInfo.get()));
182 ClearDeviceInfo(abilityInfo_);
183 }
184
SetPrimaryStub(const sptr<IRemoteObject> & Primary)185 void ContinuationHandlerStage::SetPrimaryStub(const sptr<IRemoteObject> &Primary)
186 {
187 remotePrimaryStub_ = Primary;
188 }
189
ClearDeviceInfo(std::shared_ptr<AbilityInfo> & abilityInfo)190 void ContinuationHandlerStage::ClearDeviceInfo(std::shared_ptr<AbilityInfo> &abilityInfo)
191 {
192 abilityInfo->deviceId = "";
193 abilityInfo->deviceTypes.clear();
194 }
195
OnReplicaDied(const wptr<IRemoteObject> & remote)196 void ContinuationHandlerStage::OnReplicaDied(const wptr<IRemoteObject> &remote)
197 {
198 TAG_LOGD(AAFwkTag::CONTINUATION, "begin");
199 if (remoteReplicaProxy_ == nullptr) {
200 TAG_LOGE(AAFwkTag::CONTINUATION, "RemoteReplicaProxy_ is nullptr.");
201 return;
202 }
203
204 auto object = remote.promote();
205 if (!object) {
206 TAG_LOGE(AAFwkTag::CONTINUATION, "Object is null");
207 return;
208 }
209
210 if (object != remoteReplicaProxy_->AsObject()) {
211 TAG_LOGE(AAFwkTag::CONTINUATION, "RemoteReplica is not matches with remote");
212 return;
213 }
214
215 if (remoteReplicaProxy_ != nullptr && schedulerDeathRecipient_ != nullptr) {
216 auto schedulerObject = remoteReplicaProxy_->AsObject();
217 if (schedulerObject != nullptr) {
218 schedulerObject->RemoveDeathRecipient(schedulerDeathRecipient_);
219 }
220 }
221 remoteReplicaProxy_.clear();
222
223 NotifyReplicaTerminated();
224 }
225
NotifyReplicaTerminated()226 void ContinuationHandlerStage::NotifyReplicaTerminated()
227 {
228 CleanUpAfterReverse();
229
230 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
231 continuationManagerTmp = continuationManager_.lock();
232 if (continuationManagerTmp == nullptr) {
233 TAG_LOGE(AAFwkTag::CONTINUATION, "continuationManagerTmp is nullptr");
234 return;
235 }
236 continuationManagerTmp->NotifyRemoteTerminated();
237 }
238
SetWantParams(const WantParams & wantParams)239 Want ContinuationHandlerStage::SetWantParams(const WantParams &wantParams)
240 {
241 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
242 Want want;
243 want.SetParams(wantParams);
244 want.AddFlags(want.FLAG_ABILITY_CONTINUATION);
245 if (abilityInfo_->launchMode != LaunchMode::STANDARD) {
246 TAG_LOGD(AAFwkTag::CONTINUATION, "Clear task");
247 }
248 if (reversible_) {
249 TAG_LOGD(AAFwkTag::CONTINUATION, "Reversible");
250 want.AddFlags(Want::FLAG_ABILITY_CONTINUATION_REVERSIBLE);
251 }
252 ElementName element("", abilityInfo_->bundleName, abilityInfo_->name, abilityInfo_->moduleName);
253 want.SetElement(element);
254 return want;
255 }
256
CleanUpAfterReverse()257 void ContinuationHandlerStage::CleanUpAfterReverse()
258 {
259 remoteReplicaProxy_ = nullptr;
260 }
261
PassPrimary(const sptr<IRemoteObject> & Primary)262 void ContinuationHandlerStage::PassPrimary(const sptr<IRemoteObject> &Primary)
263 {
264 remotePrimaryProxy_ = iface_cast<IReverseContinuationSchedulerPrimary>(Primary);
265 }
266
ReverseContinuation()267 bool ContinuationHandlerStage::ReverseContinuation()
268 {
269 if (remotePrimaryProxy_ == nullptr) {
270 TAG_LOGE(AAFwkTag::CONTINUATION, "RemotePrimaryProxy_ is nullptr");
271 return false;
272 }
273
274 if (abilityInfo_ == nullptr) {
275 TAG_LOGE(AAFwkTag::CONTINUATION, "AbilityInfo is null");
276 return false;
277 }
278
279 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
280 continuationManagerTmp = continuationManager_.lock();
281 if (continuationManagerTmp == nullptr) {
282 TAG_LOGE(AAFwkTag::CONTINUATION, "ContinuationManagerTmp is nullptr");
283 return false;
284 }
285
286 if (!continuationManagerTmp->StartContinuation()) {
287 TAG_LOGE(AAFwkTag::CONTINUATION, "Ability rejected, BundleName = %{public}s, ClassName= %{public}s",
288 abilityInfo_->bundleName.c_str(), abilityInfo_->name.c_str());
289 return false;
290 }
291
292 WantParams wantParams;
293 if (!continuationManagerTmp->SaveData(wantParams)) {
294 TAG_LOGE(AAFwkTag::CONTINUATION,
295 "SaveData failed, BundleName = %{public}s, ClassName= %{public}s", abilityInfo_->bundleName.c_str(),
296 abilityInfo_->name.c_str());
297 return false;
298 }
299
300 Want want;
301 want.SetParams(wantParams);
302 if (remotePrimaryProxy_->ContinuationBack(want)) {
303 TAG_LOGE(AAFwkTag::CONTINUATION, "ContinuationBack send failed");
304 return false;
305 }
306 return true;
307 }
308
NotifyReverseResult(int reverseResult)309 void ContinuationHandlerStage::NotifyReverseResult(int reverseResult)
310 {
311 TAG_LOGD(AAFwkTag::CONTINUATION, "Start result = %{public}d", reverseResult);
312 if (reverseResult == 0) {
313 std::shared_ptr<AbilityRuntime::UIAbility> ability = nullptr;
314 ability = ability_.lock();
315 if (ability == nullptr) {
316 TAG_LOGE(AAFwkTag::CONTINUATION, "Ability is nullptr");
317 return;
318 }
319 ability->TerminateAbility();
320 }
321 }
322
ContinuationBack(const Want & want)323 bool ContinuationHandlerStage::ContinuationBack(const Want &want)
324 {
325 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
326 std::shared_ptr<ContinuationManagerStage> continuationManagerTmp = nullptr;
327 continuationManagerTmp = continuationManager_.lock();
328 if (continuationManagerTmp == nullptr) {
329 TAG_LOGE(AAFwkTag::CONTINUATION, "ContinuationManagerTmp is nullptr");
330 return false;
331 }
332
333 int result = 0;
334 if (!continuationManagerTmp->RestoreFromRemote(want.GetParams())) {
335 TAG_LOGE(AAFwkTag::CONTINUATION, "RestoreFromRemote failed");
336 result = ABILITY_FAILED_RESTORE_DATA;
337 }
338
339 remoteReplicaProxy_->NotifyReverseResult(result);
340 if (result == 0) {
341 CleanUpAfterReverse();
342 }
343 return true;
344 }
345
NotifyTerminationToPrimary()346 void ContinuationHandlerStage::NotifyTerminationToPrimary()
347 {
348 TAG_LOGD(AAFwkTag::CONTINUATION, "begin");
349 if (remotePrimaryProxy_ == nullptr) {
350 TAG_LOGE(AAFwkTag::CONTINUATION, "RemotePrimaryProxy is nullptr");
351 return;
352 }
353
354 remotePrimaryProxy_->NotifyReplicaTerminated();
355 }
356
ReverseContinueAbility()357 bool ContinuationHandlerStage::ReverseContinueAbility()
358 {
359 TAG_LOGD(AAFwkTag::CONTINUATION, "Begin");
360 if (remoteReplicaProxy_ == nullptr) {
361 TAG_LOGE(AAFwkTag::CONTINUATION, "RemoteReplicaProxy is nullptr");
362 return false;
363 }
364
365 bool requestSendSuccess = remoteReplicaProxy_->ReverseContinuation();
366 return requestSendSuccess;
367 }
368 } // namespace AppExecFwk
369 } // namespace OHOS
370