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