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