1 /*
2 * Copyright (c) 2021-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 "connection_record.h"
17
18 #include "ability_manager_service.h"
19 #include "ability_util.h"
20 #include "connection_state_manager.h"
21 #include "freeze_util.h"
22 #include "ui_service_extension_connection_constants.h"
23
24 namespace OHOS {
25 namespace AAFwk {
26 int64_t ConnectionRecord::connectRecordId = 0;
27 #ifdef SUPPORT_ASAN
28 const int DISCONNECT_TIMEOUT_MULTIPLE = 75;
29 #else
30 const int DISCONNECT_TIMEOUT_MULTIPLE = 1;
31 #endif
32
ConnectionRecord(const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AbilityRecord> & targetService,const sptr<IAbilityConnection> & connCallback,std::shared_ptr<AbilityConnectManager> abilityConnectManager)33 ConnectionRecord::ConnectionRecord(const sptr<IRemoteObject> &callerToken,
34 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback,
35 std::shared_ptr<AbilityConnectManager> abilityConnectManager)
36 : state_(ConnectionState::INIT),
37 callerToken_(callerToken),
38 targetService_(targetService),
39 connCallback_(connCallback),
40 abilityConnectManager_(abilityConnectManager)
41 {
42 recordId_ = connectRecordId++;
43 }
44
~ConnectionRecord()45 ConnectionRecord::~ConnectionRecord()
46 {}
47
CreateConnectionRecord(const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AbilityRecord> & targetService,const sptr<IAbilityConnection> & connCallback,std::shared_ptr<AbilityConnectManager> abilityConnectManager)48 std::shared_ptr<ConnectionRecord> ConnectionRecord::CreateConnectionRecord(const sptr<IRemoteObject> &callerToken,
49 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback,
50 std::shared_ptr<AbilityConnectManager> abilityConnectManager)
51 {
52 auto connRecord = std::make_shared<ConnectionRecord>(
53 callerToken, targetService, connCallback, abilityConnectManager);
54 CHECK_POINTER_AND_RETURN(connRecord, nullptr);
55 connRecord->SetConnectState(ConnectionState::INIT);
56 return connRecord;
57 }
58
SetConnectState(const ConnectionState & state)59 void ConnectionRecord::SetConnectState(const ConnectionState &state)
60 {
61 state_ = state;
62 }
63
GetConnectState() const64 ConnectionState ConnectionRecord::GetConnectState() const
65 {
66 return state_;
67 }
68
GetToken() const69 sptr<IRemoteObject> ConnectionRecord::GetToken() const
70 {
71 return callerToken_;
72 }
73
GetAbilityRecord() const74 std::shared_ptr<AbilityRecord> ConnectionRecord::GetAbilityRecord() const
75 {
76 return targetService_;
77 }
78
GetAbilityConnectCallback() const79 sptr<IAbilityConnection> ConnectionRecord::GetAbilityConnectCallback() const
80 {
81 std::lock_guard lock(callbackMutex_);
82 return connCallback_;
83 }
84
ClearConnCallBack()85 void ConnectionRecord::ClearConnCallBack()
86 {
87 std::lock_guard lock(callbackMutex_);
88 if (connCallback_) {
89 connCallback_.clear();
90 }
91 }
92
DisconnectAbility()93 int ConnectionRecord::DisconnectAbility()
94 {
95 if (state_ != ConnectionState::CONNECTED) {
96 TAG_LOGE(AAFwkTag::CONNECTION, "connection not established, state: %{public}d",
97 static_cast<int32_t>(state_));
98 return INVALID_CONNECTION_STATE;
99 }
100
101 /* set state to Disconnecting */
102 SetConnectState(ConnectionState::DISCONNECTING);
103 CHECK_POINTER_AND_RETURN(targetService_, ERR_INVALID_VALUE);
104 std::size_t connectNums = targetService_->GetConnectRecordList().size();
105 AppExecFwk::ExtensionAbilityType extAbilityType = targetService_->GetAbilityInfo().extensionAbilityType;
106 bool isAbilityUIServiceExt = (extAbilityType == AppExecFwk::ExtensionAbilityType::UI_SERVICE);
107 if (connectNums == 1 || isAbilityUIServiceExt) {
108 /* post timeout task to taskhandler */
109 auto disconnectTask = [thisWeakPtr = weak_from_this()]() {
110 auto connectionRecord = thisWeakPtr.lock();
111 if (connectionRecord == nullptr) {
112 TAG_LOGE(AAFwkTag::CONNECTION, "null connectionRecord");
113 return;
114 }
115 TAG_LOGE(AAFwkTag::CONNECTION, "Disconnect timeout");
116 connectionRecord->DisconnectTimeout();
117 };
118 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
119 if (handler == nullptr) {
120 TAG_LOGE(AAFwkTag::CONNECTION, "null handler");
121 } else {
122 std::string taskName("DisconnectTimeout_");
123 taskName += std::to_string(recordId_);
124 int disconnectTimeout =
125 AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * DISCONNECT_TIMEOUT_MULTIPLE;
126 handler->SubmitTask(disconnectTask, taskName, disconnectTimeout);
127 }
128 /* schedule disconnect to target ability */
129 if (isAbilityUIServiceExt) {
130 TAG_LOGI(AAFwkTag::CONNECTION, "Disconnect UIServiceExtension ability, set correct want");
131 targetService_->DisconnectAbilityWithWant(GetConnectWant());
132 } else {
133 TAG_LOGI(AAFwkTag::CONNECTION, "DisconnectAbility %{public}s called",
134 targetService_->GetAbilityInfo().name.c_str());
135 targetService_->DisconnectAbility();
136 }
137 } else {
138 TAG_LOGI(AAFwkTag::CONNECTION,
139 "current connection count: %{public}zu, %{public}s:%{public}s no need disconnect, just remove",
140 connectNums, targetService_->GetAbilityInfo().bundleName.c_str(),
141 targetService_->GetAbilityInfo().name.c_str());
142 targetService_->RemoveConnectRecordFromList(shared_from_this());
143 SetConnectState(ConnectionState::DISCONNECTED);
144 }
145
146 return ERR_OK;
147 }
148
CompleteConnect()149 void ConnectionRecord::CompleteConnect()
150 {
151 SetConnectState(ConnectionState::CONNECTED);
152 CHECK_POINTER(targetService_);
153 targetService_->SetAbilityState(AbilityState::ACTIVE);
154 TAG_LOGI(AAFwkTag::ABILITYMGR, "Connect,%{public}s", targetService_->GetAbilityInfo().name.c_str());
155 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
156 AppExecFwk::ElementName element(targetService_->GetWant().GetDeviceId(), abilityInfo.bundleName,
157 abilityInfo.name, abilityInfo.moduleName);
158 auto remoteObject = targetService_->GetConnRemoteObject();
159 auto callback = GetAbilityConnectCallback();
160 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
161 if (remoteObject == nullptr) {
162 TAG_LOGW(AAFwkTag::CONNECTION, "null remoteObject: %{public}s", element.GetURI().c_str());
163 if (handler) {
164 SetConnectState(ConnectionState::DISCONNECTING);
165 handler->SubmitTask([service = targetService_]() {
166 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(
167 service->GetToken());
168 });
169 }
170 return;
171 }
172
173 if (callback && handler) {
174 handler->SubmitTask([callback, element, remoteObject, weakConnectionRecord = weak_from_this(),
175 weakConnectManager = abilityConnectManager_] {
176 TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityConnectDone");
177 auto ret = ConnectionRecord::CallOnAbilityConnectDone(callback, element, remoteObject, ERR_OK);
178 if (ret != ERR_OK) {
179 TAG_LOGE(AAFwkTag::CONNECTION, "OnAbilityConnectDone failed");
180 auto connectionRecord = weakConnectionRecord.lock();
181 CHECK_POINTER(connectionRecord);
182 auto abilityConnectManager = weakConnectManager.lock();
183 CHECK_POINTER(abilityConnectManager);
184 abilityConnectManager->HandleExtensionDisconnectTask(connectionRecord);
185 }
186 });
187 }
188 DelayedSingleton<ConnectionStateManager>::GetInstance()->AddConnection(shared_from_this());
189 TAG_LOGI(AAFwkTag::CONNECTION, "connectState:%{public}d", state_);
190 }
191
CompleteConnectAndOnlyCallConnectDone()192 void ConnectionRecord::CompleteConnectAndOnlyCallConnectDone()
193 {
194 if (GetConnectState() != ConnectionState::CONNECTED) {
195 TAG_LOGI(AAFwkTag::ABILITYMGR, "Connect state is %{public}d, not connected state", GetConnectState());
196 return;
197 }
198 CHECK_POINTER(targetService_);
199 TAG_LOGI(AAFwkTag::ABILITYMGR, "CompleteConnect,%{public}s", targetService_->GetAbilityInfo().name.c_str());
200 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
201 AppExecFwk::ElementName element(targetService_->GetWant().GetDeviceId(), abilityInfo.bundleName,
202 abilityInfo.name, abilityInfo.moduleName);
203 auto remoteObject = targetService_->GetConnRemoteObject();
204 auto callback = GetAbilityConnectCallback();
205 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
206 if (remoteObject == nullptr) {
207 TAG_LOGW(AAFwkTag::CONNECTION, "Complete null remoteObject: %{public}s", element.GetURI().c_str());
208 return;
209 }
210
211 if (callback && handler) {
212 handler->SubmitTask([callback, element, remoteObject] {
213 TAG_LOGD(AAFwkTag::CONNECTION, "CallOnAbilityConnectDone");
214 auto ret = ConnectionRecord::CallOnAbilityConnectDone(callback, element, remoteObject, ERR_OK);
215 if (ret != ERR_OK) {
216 TAG_LOGE(AAFwkTag::CONNECTION, "CallOnAbilityConnectDone failed");
217 }
218 });
219 }
220 TAG_LOGI(AAFwkTag::CONNECTION, "Complete connectState:%{public}d", state_);
221 }
222
CallOnAbilityConnectDone(sptr<IAbilityConnection> callback,const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)223 int32_t ConnectionRecord::CallOnAbilityConnectDone(sptr<IAbilityConnection> callback,
224 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
225 {
226 CHECK_POINTER_AND_RETURN(callback, ERR_INVALID_VALUE);
227 sptr<IRemoteObject> obj = callback->AsObject();
228 CHECK_POINTER_AND_RETURN(obj, ERR_INVALID_VALUE);
229 if (!obj->IsProxyObject()) {
230 callback->OnAbilityConnectDone(element, remoteObject, ERR_OK);
231 return ERR_OK;
232 }
233 MessageParcel data;
234 MessageParcel reply;
235 MessageOption option(MessageOption::TF_ASYNC);
236
237 if (!data.WriteInterfaceToken(IAbilityConnection::GetDescriptor())) {
238 TAG_LOGE(AAFwkTag::ABILITYMGR, "WriteInterfaceToken fail");
239 return ERR_FLATTEN_OBJECT;
240 }
241
242 if (!data.WriteParcelable(&element)) {
243 TAG_LOGE(AAFwkTag::ABILITYMGR, "element error");
244 return ERR_FLATTEN_OBJECT;
245 }
246
247 if (!data.WriteRemoteObject(remoteObject)) {
248 TAG_LOGE(AAFwkTag::ABILITYMGR, "remoteObject error");
249 return ERR_FLATTEN_OBJECT;
250 }
251
252 if (!data.WriteInt32(resultCode)) {
253 TAG_LOGE(AAFwkTag::ABILITYMGR, "resultCode error");
254 return ERR_FLATTEN_OBJECT;
255 }
256
257 int32_t ret = obj->SendRequest(IAbilityConnection::ON_ABILITY_CONNECT_DONE, data, reply, option);
258 if (ret != ERR_OK) {
259 TAG_LOGE(AAFwkTag::ABILITYMGR, "fail. ret: %{public}d", ret);
260 }
261 return ret;
262 }
263
CompleteDisconnect(int resultCode,bool isCallerDied,bool isTargetDied)264 void ConnectionRecord::CompleteDisconnect(int resultCode, bool isCallerDied, bool isTargetDied)
265 {
266 if (resultCode == ERR_OK) {
267 SetConnectState(ConnectionState::DISCONNECTED);
268 }
269 CHECK_POINTER(targetService_);
270 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
271 AppExecFwk::ElementName element(targetService_->GetWant().GetDeviceId(), abilityInfo.bundleName,
272 abilityInfo.name, abilityInfo.moduleName);
273 auto code = isTargetDied ? (resultCode - 1) : resultCode;
274 auto onDisconnectDoneTask = [connCallback = GetAbilityConnectCallback(), element, code]() {
275 TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityDisconnectDone");
276 if (!connCallback) {
277 TAG_LOGD(AAFwkTag::CONNECTION, "null connCallback");
278 return;
279 }
280 connCallback->OnAbilityDisconnectDone(element, code);
281 };
282 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
283 if (handler == nullptr) {
284 TAG_LOGE(AAFwkTag::CONNECTION, "null handler");
285 return;
286 }
287 handler->SubmitTask(onDisconnectDoneTask);
288 DelayedSingleton<ConnectionStateManager>::GetInstance()->RemoveConnection(shared_from_this(), isCallerDied);
289 TAG_LOGD(AAFwkTag::CONNECTION, "result: %{public}d, connectState:%{public}d", resultCode, state_);
290 }
291
ScheduleDisconnectAbilityDone()292 void ConnectionRecord::ScheduleDisconnectAbilityDone()
293 {
294 if (state_ != ConnectionState::DISCONNECTING) {
295 TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not disconnecting");
296 return;
297 }
298
299 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
300 if (handler == nullptr) {
301 TAG_LOGE(AAFwkTag::CONNECTION, "fail to get AbilityTaskHandler");
302 } else {
303 std::string taskName = std::string("DisconnectTimeout_") + std::to_string(recordId_);
304 handler->CancelTask(taskName);
305 }
306
307 CompleteDisconnect(ERR_OK, GetAbilityConnectCallback() == nullptr);
308 }
309
ScheduleConnectAbilityDone()310 void ConnectionRecord::ScheduleConnectAbilityDone()
311 {
312 if (state_ != ConnectionState::CONNECTING) {
313 TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not connecting");
314 return;
315 }
316
317 sptr<IRemoteObject> hostproxy = nullptr;
318 if (connectWant_.HasParameter(UISERVICEHOSTPROXY_KEY)) {
319 hostproxy = connectWant_.GetRemoteObject(UISERVICEHOSTPROXY_KEY);
320 }
321 auto element = connectWant_.GetElement();
322 Want::ClearWant(&connectWant_);
323 connectWant_.SetElement(element);
324 if (hostproxy != nullptr) {
325 connectWant_.SetParam(UISERVICEHOSTPROXY_KEY, hostproxy);
326 }
327
328 CancelConnectTimeoutTask();
329
330 CompleteConnect();
331 }
332
CancelConnectTimeoutTask()333 void ConnectionRecord::CancelConnectTimeoutTask()
334 {
335 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
336 CHECK_POINTER(handler);
337 std::string taskName = std::to_string(recordId_);
338 TAG_LOGI(AAFwkTag::ABILITYMGR, "CancelConnectTimeoutTask taskName:%{public}s", taskName.c_str());
339 handler->RemoveEvent(AbilityManagerService::CONNECT_TIMEOUT_MSG, taskName);
340 handler->RemoveEvent(AbilityManagerService::CONNECT_HALF_TIMEOUT_MSG, taskName);
341 auto targetToken = GetTargetToken();
342 CHECK_POINTER(targetToken);
343 AbilityRuntime::FreezeUtil::GetInstance().DeleteLifecycleEvent(targetToken);
344 }
345
DisconnectTimeout()346 void ConnectionRecord::DisconnectTimeout()
347 {
348 CHECK_POINTER(targetService_);
349 /* force to disconnect */
350 /* so scheduler target service disconnect done */
351 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(targetService_->GetToken());
352 }
353
ConvertConnectionState(const ConnectionState & state) const354 std::string ConnectionRecord::ConvertConnectionState(const ConnectionState &state) const
355 {
356 switch (state) {
357 case ConnectionState::INIT:
358 return "INIT";
359 case ConnectionState::CONNECTING:
360 return "CONNECTING";
361 case ConnectionState::CONNECTED:
362 return "CONNECTED";
363 case ConnectionState::DISCONNECTING:
364 return "DISCONNECTING";
365 case ConnectionState::DISCONNECTED:
366 return "DISCONNECTED";
367 default:
368 return "INVALIDSTATE";
369 }
370 }
371
Dump(std::vector<std::string> & info) const372 void ConnectionRecord::Dump(std::vector<std::string> &info) const
373 {
374 auto abilityRecord = GetAbilityRecord();
375 CHECK_POINTER(abilityRecord);
376 info.emplace_back(" > " + abilityRecord->GetAbilityInfo().bundleName + "/" +
377 abilityRecord->GetAbilityInfo().name + " connectionState #" +
378 ConvertConnectionState(GetConnectState()));
379 }
380
AttachCallerInfo()381 void ConnectionRecord::AttachCallerInfo()
382 {
383 callerTokenId_ = IPCSkeleton::GetCallingTokenID(); // tokenId identifies the real caller
384 auto targetRecord = Token::GetAbilityRecordByToken(callerToken_);
385 if (targetRecord) {
386 callerUid_ = targetRecord->GetUid();
387 callerPid_ = targetRecord->GetPid();
388 callerName_ = targetRecord->GetAbilityInfo().bundleName;
389 return;
390 }
391
392 callerUid_ = static_cast<int32_t>(IPCSkeleton::GetCallingUid());
393 callerPid_ = static_cast<int32_t>(IPCSkeleton::GetCallingPid());
394 callerName_ = ConnectionStateManager::GetProcessNameByPid(callerPid_);
395 }
396
GetCallerUid() const397 int32_t ConnectionRecord::GetCallerUid() const
398 {
399 return callerUid_;
400 }
401
GetCallerPid() const402 int32_t ConnectionRecord::GetCallerPid() const
403 {
404 return callerPid_;
405 }
406
GetCallerTokenId() const407 uint32_t ConnectionRecord::GetCallerTokenId() const
408 {
409 return callerTokenId_;
410 }
411
GetCallerName() const412 std::string ConnectionRecord::GetCallerName() const
413 {
414 return callerName_;
415 }
416
GetTargetToken() const417 sptr<IRemoteObject> ConnectionRecord::GetTargetToken() const
418 {
419 auto targetService = targetService_;
420 if (!targetService) {
421 return nullptr;
422 }
423
424 auto token = targetService->GetToken();
425 if (!token) {
426 return nullptr;
427 }
428
429 return token->AsObject();
430 }
431
GetConnection() const432 sptr<IRemoteObject> ConnectionRecord::GetConnection() const
433 {
434 auto callback = GetAbilityConnectCallback();
435 if (!callback) {
436 return nullptr;
437 }
438
439 return callback->AsObject();
440 }
441
SetConnectWant(const Want & want)442 void ConnectionRecord::SetConnectWant(const Want &want)
443 {
444 connectWant_ = want;
445 }
446
GetConnectWant() const447 Want ConnectionRecord::GetConnectWant() const
448 {
449 return connectWant_;
450 }
451
SuspendExtensionAbility()452 int32_t ConnectionRecord::SuspendExtensionAbility()
453 {
454 if (state_ != ConnectionState::CONNECTED) {
455 TAG_LOGE(AAFwkTag::CONNECTION, "connection not established, state: %{public}d",
456 static_cast<int32_t>(state_));
457 return INVALID_CONNECTION_STATE;
458 }
459
460 DelayedSingleton<ConnectionStateManager>::GetInstance()->SuspendConnection(shared_from_this());
461 return ERR_OK;
462 }
463
ResumeExtensionAbility()464 int32_t ConnectionRecord::ResumeExtensionAbility()
465 {
466 if (state_ != ConnectionState::CONNECTED) {
467 TAG_LOGE(AAFwkTag::CONNECTION, "connection not established, state: %{public}d",
468 static_cast<int32_t>(state_));
469 return INVALID_CONNECTION_STATE;
470 }
471
472 DelayedSingleton<ConnectionStateManager>::GetInstance()->ResumeConnection(shared_from_this());
473 return ERR_OK;
474 }
475 } // namespace AAFwk
476 } // namespace OHOS
477