• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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