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