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