1 /*
2 * Copyright (c) 2021 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_errors.h"
19 #include "ability_manager_service.h"
20 #include "ability_util.h"
21 #include "connection_state_manager.h"
22 #include "hilog_wrapper.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)33 ConnectionRecord::ConnectionRecord(const sptr<IRemoteObject> &callerToken,
34 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback)
35 : state_(ConnectionState::INIT),
36 callerToken_(callerToken),
37 targetService_(targetService),
38 connCallback_(connCallback)
39 {
40 recordId_ = connectRecordId++;
41 }
42
~ConnectionRecord()43 ConnectionRecord::~ConnectionRecord()
44 {}
45
CreateConnectionRecord(const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AbilityRecord> & targetService,const sptr<IAbilityConnection> & connCallback)46 std::shared_ptr<ConnectionRecord> ConnectionRecord::CreateConnectionRecord(const sptr<IRemoteObject> &callerToken,
47 const std::shared_ptr<AbilityRecord> &targetService, const sptr<IAbilityConnection> &connCallback)
48 {
49 auto connRecord = std::make_shared<ConnectionRecord>(callerToken, targetService, connCallback);
50 CHECK_POINTER_AND_RETURN(connRecord, nullptr);
51 connRecord->SetConnectState(ConnectionState::INIT);
52 return connRecord;
53 }
54
SetConnectState(const ConnectionState & state)55 void ConnectionRecord::SetConnectState(const ConnectionState &state)
56 {
57 state_ = state;
58 }
59
GetConnectState() const60 ConnectionState ConnectionRecord::GetConnectState() const
61 {
62 return state_;
63 }
64
GetToken() const65 sptr<IRemoteObject> ConnectionRecord::GetToken() const
66 {
67 return callerToken_;
68 }
69
GetAbilityRecord() const70 std::shared_ptr<AbilityRecord> ConnectionRecord::GetAbilityRecord() const
71 {
72 return targetService_;
73 }
74
GetAbilityConnectCallback() const75 sptr<IAbilityConnection> ConnectionRecord::GetAbilityConnectCallback() const
76 {
77 return connCallback_;
78 }
79
ClearConnCallBack()80 void ConnectionRecord::ClearConnCallBack()
81 {
82 if (connCallback_) {
83 connCallback_.clear();
84 }
85 }
86
DisconnectAbility()87 int ConnectionRecord::DisconnectAbility()
88 {
89 if (state_ != ConnectionState::CONNECTED) {
90 HILOG_ERROR("The connection has not established, connectionState: %{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 HILOG_ERROR("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 HILOG_ERROR("Disconnect ability 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 targetService_->DisconnectAbility();
117 } else {
118 HILOG_DEBUG("The current connection count is %{public}zu, no need to disconnect, just remove connection.",
119 connectNums);
120 targetService_->RemoveConnectRecordFromList(shared_from_this());
121 SetConnectState(ConnectionState::DISCONNECTED);
122 }
123
124 return ERR_OK;
125 }
126
CompleteConnect(int resultCode)127 void ConnectionRecord::CompleteConnect(int resultCode)
128 {
129 CHECK_POINTER(targetService_);
130 if (resultCode == ERR_OK) {
131 SetConnectState(ConnectionState::CONNECTED);
132 targetService_->SetAbilityState(AbilityState::ACTIVE);
133 }
134 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
135 AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
136 abilityInfo.name, abilityInfo.moduleName);
137 auto remoteObject = targetService_->GetConnRemoteObject();
138 if (connCallback_) {
139 HILOG_DEBUG("OnAbilityConnectDone");
140 connCallback_->OnAbilityConnectDone(element, remoteObject, resultCode);
141 }
142 DelayedSingleton<ConnectionStateManager>::GetInstance()->AddConnection(shared_from_this());
143 HILOG_INFO("result: %{public}d. connectState:%{public}d.", resultCode, state_);
144 }
145
CompleteDisconnect(int resultCode,bool isDied)146 void ConnectionRecord::CompleteDisconnect(int resultCode, bool isDied)
147 {
148 if (resultCode == ERR_OK) {
149 SetConnectState(ConnectionState::DISCONNECTED);
150 }
151 CHECK_POINTER(targetService_);
152 const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
153 AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
154 abilityInfo.name, abilityInfo.moduleName);
155 auto code = isDied ? (resultCode - 1) : resultCode;
156 auto onDisconnectDoneTask = [connCallback = connCallback_, element, code]() {
157 HILOG_DEBUG("OnAbilityDisconnectDone.");
158 if (!connCallback) {
159 HILOG_ERROR("connCallback_ is nullptr.");
160 return;
161 }
162 connCallback->OnAbilityDisconnectDone(element, code);
163 };
164 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
165 if (handler == nullptr) {
166 HILOG_ERROR("handler is nullptr.");
167 return;
168 }
169 handler->SubmitTask(onDisconnectDoneTask);
170 DelayedSingleton<ConnectionStateManager>::GetInstance()->RemoveConnection(shared_from_this(), isDied);
171 HILOG_INFO("result: %{public}d. connectState:%{public}d.", resultCode, state_);
172 }
173
ScheduleDisconnectAbilityDone()174 void ConnectionRecord::ScheduleDisconnectAbilityDone()
175 {
176 if (state_ != ConnectionState::DISCONNECTING) {
177 HILOG_ERROR("fail to schedule disconnect ability done, current state is not disconnecting.");
178 return;
179 }
180
181 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
182 if (handler == nullptr) {
183 HILOG_ERROR("fail to get AbilityTaskHandler");
184 } else {
185 std::string taskName = std::string("DisconnectTimeout_") + std::to_string(recordId_);
186 handler->CancelTask(taskName);
187 }
188
189 CompleteDisconnect(ERR_OK, false);
190 }
191
ScheduleConnectAbilityDone()192 void ConnectionRecord::ScheduleConnectAbilityDone()
193 {
194 if (state_ != ConnectionState::CONNECTING) {
195 HILOG_ERROR("fail to schedule connect ability done, current state is not connecting.");
196 return;
197 }
198 auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
199 if (handler == nullptr) {
200 HILOG_ERROR("fail to get AbilityTaskHandler");
201 } else {
202 std::string taskName = std::string("ConnectTimeout_") + std::to_string(recordId_);
203 handler->CancelTask(taskName);
204 }
205
206 CompleteConnect(ERR_OK);
207 }
208
DisconnectTimeout()209 void ConnectionRecord::DisconnectTimeout()
210 {
211 CHECK_POINTER(targetService_);
212 /* force to disconnect */
213 /* so scheduler target service disconnect done */
214 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(targetService_->GetToken());
215 }
216
ConvertConnectionState(const ConnectionState & state) const217 std::string ConnectionRecord::ConvertConnectionState(const ConnectionState &state) const
218 {
219 switch (state) {
220 case ConnectionState::INIT:
221 return "INIT";
222 case ConnectionState::CONNECTING:
223 return "CONNECTING";
224 case ConnectionState::CONNECTED:
225 return "CONNECTED";
226 case ConnectionState::DISCONNECTING:
227 return "DISCONNECTING";
228 case ConnectionState::DISCONNECTED:
229 return "DISCONNECTED";
230 default:
231 return "INVALIDSTATE";
232 }
233 }
234
Dump(std::vector<std::string> & info) const235 void ConnectionRecord::Dump(std::vector<std::string> &info) const
236 {
237 info.emplace_back(" > " + GetAbilityRecord()->GetAbilityInfo().bundleName + "/" +
238 GetAbilityRecord()->GetAbilityInfo().name + " connectionState #" +
239 ConvertConnectionState(GetConnectState()));
240 }
241
AttachCallerInfo()242 void ConnectionRecord::AttachCallerInfo()
243 {
244 callerTokenId_ = IPCSkeleton::GetCallingTokenID(); // tokenId identifies the real caller
245 auto targetRecord = Token::GetAbilityRecordByToken(callerToken_);
246 if (targetRecord) {
247 callerUid_ = targetRecord->GetUid();
248 callerPid_ = targetRecord->GetPid();
249 callerName_ = targetRecord->GetAbilityInfo().bundleName;
250 return;
251 }
252
253 callerUid_ = static_cast<int32_t>(IPCSkeleton::GetCallingUid());
254 callerPid_ = static_cast<int32_t>(IPCSkeleton::GetCallingPid());
255 callerName_ = ConnectionStateManager::GetProcessNameByPid(callerPid_);
256 }
257
GetCallerUid() const258 int32_t ConnectionRecord::GetCallerUid() const
259 {
260 return callerUid_;
261 }
262
GetCallerPid() const263 int32_t ConnectionRecord::GetCallerPid() const
264 {
265 return callerPid_;
266 }
267
GetCallerTokenId() const268 uint32_t ConnectionRecord::GetCallerTokenId() const
269 {
270 return callerTokenId_;
271 }
272
GetCallerName() const273 std::string ConnectionRecord::GetCallerName() const
274 {
275 return callerName_;
276 }
277
GetTargetToken() const278 sptr<IRemoteObject> ConnectionRecord::GetTargetToken() const
279 {
280 auto targetService = targetService_;
281 if (!targetService) {
282 return nullptr;
283 }
284
285 auto token = targetService->GetToken();
286 if (!token) {
287 return nullptr;
288 }
289
290 return token->AsObject();
291 }
292
GetConnection() const293 sptr<IRemoteObject> ConnectionRecord::GetConnection() const
294 {
295 auto callback = connCallback_;
296 if (!callback) {
297 return nullptr;
298 }
299
300 return callback->AsObject();
301 }
302 } // namespace AAFwk
303 } // namespace OHOS
304