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)32 ConnectionRecord::ConnectionRecord(const sptr<IRemoteObject> &callerToken,
33 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback)
34 : state_(ConnectionState::INIT),
35 callerToken_(callerToken),
36 targetService_(targetService),
37 connCallback_(connCallback)
38 {
39 recordId_ = connectRecordId++;
40 }
41
~ConnectionRecord()42 ConnectionRecord::~ConnectionRecord()
43 {}
44
CreateConnectionRecord(const sptr<IRemoteObject> &callerToken, const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback)45 std::shared_ptr<ConnectionRecord> ConnectionRecord::CreateConnectionRecord(const sptr<IRemoteObject> &callerToken,
46 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback)
47 {
48 auto connRecord = std::make_shared<ConnectionRecord>(callerToken, targetService, connCallback);
49 CHECK_POINTER_AND_RETURN(connRecord, nullptr);
50 connRecord->SetConnectState(ConnectionState::INIT);
51 return connRecord;
52 }
53
SetConnectState(const ConnectionState &state)54 void ConnectionRecord::SetConnectState(const ConnectionState &state)
55 {
56 state_ = state;
57 }
58
GetConnectState() const59 ConnectionState ConnectionRecord::GetConnectState() const
60 {
61 return state_;
62 }
63
GetToken() const64 sptr<IRemoteObject> ConnectionRecord::GetToken() const
65 {
66 return callerToken_;
67 }
68
GetAbilityRecord() const69 std::shared_ptr<AbilityRecord> ConnectionRecord::GetAbilityRecord() const
70 {
71 return targetService_;
72 }
73
GetAbilityConnectCallback() const74 sptr<IAbilityConnection> ConnectionRecord::GetAbilityConnectCallback() const
75 {
76 std::lock_guard lock(callbackMutex_);
77 return connCallback_;
78 }
79
ClearConnCallBack()80 void ConnectionRecord::ClearConnCallBack()
81 {
82 std::lock_guard lock(callbackMutex_);
83 if (connCallback_) {
84 connCallback_.clear();
85 }
86 }
87
DisconnectAbility()88 int ConnectionRecord::DisconnectAbility()
89 {
90 if (state_ != ConnectionState::CONNECTED) {
91 TAG_LOGE(AAFwkTag::CONNECTION, "connection not established, state: %{public}d",
92 static_cast<int32_t>(state_));
93 return INVALID_CONNECTION_STATE;
94 }
95
96 /* set state to Disconnecting */
97 SetConnectState(ConnectionState::DISCONNECTING);
98 CHECK_POINTER_AND_RETURN(targetService_, ERR_INVALID_VALUE);
99 std::size_t connectNums = targetService_->GetConnectRecordList().size();
100 AppExecFwk::ExtensionAbilityType extAbilityType = targetService_->GetAbilityInfo().extensionAbilityType;
101 bool isAbilityUIServiceExt = (extAbilityType == AppExecFwk::ExtensionAbilityType::UI_SERVICE);
102 if (connectNums == 1 || isAbilityUIServiceExt) {
103 /* post timeout task to taskhandler */
104 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
105 if (handler == nullptr) {
106 TAG_LOGE(AAFwkTag::CONNECTION, "null handler");
107 } else {
108 std::string taskName("DisconnectTimeout_");
109 taskName += std::to_string(recordId_);
110 auto disconnectTask = [connectionRecord = shared_from_this()]() {
111 TAG_LOGE(AAFwkTag::CONNECTION, "Disconnect timeout");
112 connectionRecord->DisconnectTimeout();
113 };
114 int disconnectTimeout =
115 AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * DISCONNECT_TIMEOUT_MULTIPLE;
116 handler->SubmitTask(disconnectTask, taskName, disconnectTimeout);
117 }
118 /* schedule disconnect to target ability */
119 if (isAbilityUIServiceExt) {
120 TAG_LOGI(AAFwkTag::CONNECTION, "Disconnect UIServiceExtension ability, set correct want");
121 targetService_->DisconnectAbilityWithWant(GetConnectWant());
122 } else {
123 TAG_LOGI(AAFwkTag::CONNECTION, "DisconnectAbility called");
124 targetService_->DisconnectAbility();
125 }
126 } else {
127 TAG_LOGI(AAFwkTag::CONNECTION,
128 "current connection count: %{public}zu, no need disconnect, just remove", connectNums);
129 targetService_->RemoveConnectRecordFromList(shared_from_this());
130 SetConnectState(ConnectionState::DISCONNECTED);
131 }
132
133 return ERR_OK;
134 }
135
CompleteConnect(int resultCode)136 void ConnectionRecord::CompleteConnect(int resultCode)
137 {
138 CHECK_POINTER(targetService_);
139 if (resultCode == ERR_OK) {
140 SetConnectState(ConnectionState::CONNECTED);
141 targetService_->SetAbilityState(AbilityState::ACTIVE);
142 }
143 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
144 AppExecFwk::ElementName element(targetService_->GetWant().GetDeviceId(), abilityInfo.bundleName,
145 abilityInfo.name, abilityInfo.moduleName);
146 auto remoteObject = targetService_->GetConnRemoteObject();
147 auto callback = GetAbilityConnectCallback();
148 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
149 if (remoteObject == nullptr) {
150 TAG_LOGW(AAFwkTag::CONNECTION, "null remoteObject: %{public}s", element.GetURI().c_str());
151 if (handler) {
152 SetConnectState(ConnectionState::DISCONNECTING);
153 handler->SubmitTask([service = targetService_]() {
154 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(
155 service->GetToken());
156 });
157 }
158 return;
159 }
160
161 if (callback && handler) {
162 handler->SubmitTask([callback, element, remoteObject, resultCode] {
163 TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityConnectDone");
164 callback->OnAbilityConnectDone(element, remoteObject, resultCode);
165 });
166 }
167 DelayedSingleton<ConnectionStateManager>::GetInstance()->AddConnection(shared_from_this());
168 TAG_LOGI(AAFwkTag::CONNECTION, "result: %{public}d, connectState:%{public}d", resultCode, state_);
169 }
170
CompleteDisconnect(int resultCode, bool isCallerDied, bool isTargetDied)171 void ConnectionRecord::CompleteDisconnect(int resultCode, bool isCallerDied, bool isTargetDied)
172 {
173 if (resultCode == ERR_OK) {
174 SetConnectState(ConnectionState::DISCONNECTED);
175 }
176 CHECK_POINTER(targetService_);
177 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
178 AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
179 abilityInfo.name, abilityInfo.moduleName);
180 auto code = isTargetDied ? (resultCode - 1) : resultCode;
181 auto onDisconnectDoneTask = [connCallback = GetAbilityConnectCallback(), element, code]() {
182 TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityDisconnectDone");
183 if (!connCallback) {
184 TAG_LOGD(AAFwkTag::CONNECTION, "null connCallback");
185 return;
186 }
187 connCallback->OnAbilityDisconnectDone(element, code);
188 };
189 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
190 if (handler == nullptr) {
191 TAG_LOGE(AAFwkTag::CONNECTION, "null handler");
192 return;
193 }
194 handler->SubmitTask(onDisconnectDoneTask);
195 DelayedSingleton<ConnectionStateManager>::GetInstance()->RemoveConnection(shared_from_this(), isCallerDied);
196 TAG_LOGD(AAFwkTag::CONNECTION, "result: %{public}d, connectState:%{public}d", resultCode, state_);
197 }
198
ScheduleDisconnectAbilityDone()199 void ConnectionRecord::ScheduleDisconnectAbilityDone()
200 {
201 if (state_ != ConnectionState::DISCONNECTING) {
202 TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not disconnecting");
203 return;
204 }
205
206 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
207 if (handler == nullptr) {
208 TAG_LOGE(AAFwkTag::CONNECTION, "fail to get AbilityTaskHandler");
209 } else {
210 std::string taskName = std::string("DisconnectTimeout_") + std::to_string(recordId_);
211 handler->CancelTask(taskName);
212 }
213
214 CompleteDisconnect(ERR_OK, GetAbilityConnectCallback() == nullptr);
215 }
216
ScheduleConnectAbilityDone()217 void ConnectionRecord::ScheduleConnectAbilityDone()
218 {
219 if (state_ != ConnectionState::CONNECTING) {
220 TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not connecting");
221 return;
222 }
223
224 sptr<IRemoteObject> hostproxy = nullptr;
225 if (connectWant_.HasParameter(UISERVICEHOSTPROXY_KEY)) {
226 hostproxy = connectWant_.GetRemoteObject(UISERVICEHOSTPROXY_KEY);
227 }
228 auto element = connectWant_.GetElement();
229 Want::ClearWant(&connectWant_);
230 connectWant_.SetElement(element);
231 if (hostproxy != nullptr) {
232 connectWant_.SetParam(UISERVICEHOSTPROXY_KEY, hostproxy);
233 }
234
235 CancelConnectTimeoutTask();
236
237 CompleteConnect(ERR_OK);
238 }
239
CancelConnectTimeoutTask()240 void ConnectionRecord::CancelConnectTimeoutTask()
241 {
242 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
243 if (handler == nullptr) {
244 TAG_LOGE(AAFwkTag::CONNECTION, "fail to get AbilityTaskHandler");
245 } else {
246 std::string taskName = std::string("ConnectTimeout_") + std::to_string(recordId_);
247 handler->CancelTask(taskName);
248 }
249 }
250
DisconnectTimeout()251 void ConnectionRecord::DisconnectTimeout()
252 {
253 CHECK_POINTER(targetService_);
254 /* force to disconnect */
255 /* so scheduler target service disconnect done */
256 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(targetService_->GetToken());
257 }
258
ConvertConnectionState(const ConnectionState &state) const259 std::string ConnectionRecord::ConvertConnectionState(const ConnectionState &state) const
260 {
261 switch (state) {
262 case ConnectionState::INIT:
263 return "INIT";
264 case ConnectionState::CONNECTING:
265 return "CONNECTING";
266 case ConnectionState::CONNECTED:
267 return "CONNECTED";
268 case ConnectionState::DISCONNECTING:
269 return "DISCONNECTING";
270 case ConnectionState::DISCONNECTED:
271 return "DISCONNECTED";
272 default:
273 return "INVALIDSTATE";
274 }
275 }
276
Dump(std::vector<std::string> &info) const277 void ConnectionRecord::Dump(std::vector<std::string> &info) const
278 {
279 info.emplace_back(" > " + GetAbilityRecord()->GetAbilityInfo().bundleName + "/" +
280 GetAbilityRecord()->GetAbilityInfo().name + " connectionState #" +
281 ConvertConnectionState(GetConnectState()));
282 }
283
AttachCallerInfo()284 void ConnectionRecord::AttachCallerInfo()
285 {
286 callerTokenId_ = IPCSkeleton::GetCallingTokenID(); // tokenId identifies the real caller
287 auto targetRecord = Token::GetAbilityRecordByToken(callerToken_);
288 if (targetRecord) {
289 callerUid_ = targetRecord->GetUid();
290 callerPid_ = targetRecord->GetPid();
291 callerName_ = targetRecord->GetAbilityInfo().bundleName;
292 return;
293 }
294
295 callerUid_ = static_cast<int32_t>(IPCSkeleton::GetCallingUid());
296 callerPid_ = static_cast<int32_t>(IPCSkeleton::GetCallingPid());
297 callerName_ = ConnectionStateManager::GetProcessNameByPid(callerPid_);
298 }
299
GetCallerUid() const300 int32_t ConnectionRecord::GetCallerUid() const
301 {
302 return callerUid_;
303 }
304
GetCallerPid() const305 int32_t ConnectionRecord::GetCallerPid() const
306 {
307 return callerPid_;
308 }
309
GetCallerTokenId() const310 uint32_t ConnectionRecord::GetCallerTokenId() const
311 {
312 return callerTokenId_;
313 }
314
GetCallerName() const315 std::string ConnectionRecord::GetCallerName() const
316 {
317 return callerName_;
318 }
319
GetTargetToken() const320 sptr<IRemoteObject> ConnectionRecord::GetTargetToken() const
321 {
322 auto targetService = targetService_;
323 if (!targetService) {
324 return nullptr;
325 }
326
327 auto token = targetService->GetToken();
328 if (!token) {
329 return nullptr;
330 }
331
332 return token->AsObject();
333 }
334
GetConnection() const335 sptr<IRemoteObject> ConnectionRecord::GetConnection() const
336 {
337 auto callback = GetAbilityConnectCallback();
338 if (!callback) {
339 return nullptr;
340 }
341
342 return callback->AsObject();
343 }
344
SetConnectWant(const Want &want)345 void ConnectionRecord::SetConnectWant(const Want &want)
346 {
347 connectWant_ = want;
348 }
349
GetConnectWant() const350 Want ConnectionRecord::GetConnectWant() const
351 {
352 return connectWant_;
353 }
354 } // namespace AAFwk
355 } // namespace OHOS
356