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, "fail to get TaskHandler");
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         TAG_LOGI(AAFwkTag::CONNECTION, "DisconnectAbility called");
120         if (isAbilityUIServiceExt) {
121             TAG_LOGI(AAFwkTag::CONNECTION, "Disconnect UIServiceExtension ability, set correct want");
122             targetService_->DisconnectAbilityWithWant(GetConnectWant());
123         } else {
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()136 void ConnectionRecord::CompleteConnect()
137 {
138     SetConnectState(ConnectionState::CONNECTED);
139     CHECK_POINTER(targetService_);
140     targetService_->SetAbilityState(AbilityState::ACTIVE);
141     TAG_LOGI(AAFwkTag::ABILITYMGR, "CompleteConnect,%{public}s", targetService_->GetAbilityInfo().name.c_str());
142     const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
143     AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
144         abilityInfo.name, abilityInfo.moduleName);
145     auto remoteObject = targetService_->GetConnRemoteObject();
146     auto callback = GetAbilityConnectCallback();
147     auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
148     if (remoteObject == nullptr) {
149         TAG_LOGW(AAFwkTag::CONNECTION, "extension returned null: %{public}s", element.GetURI().c_str());
150         if (handler) {
151             SetConnectState(ConnectionState::DISCONNECTING);
152             handler->SubmitTask([service = targetService_]() {
153                 DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(
154                     service->GetToken());
155                 });
156         }
157         return;
158     }
159 
160     if (callback && handler) {
161         handler->SubmitTask([callback, element, remoteObject] {
162             TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityConnectDone");
163             callback->OnAbilityConnectDone(element, remoteObject, ERR_OK);
164             });
165     }
166     DelayedSingleton<ConnectionStateManager>::GetInstance()->AddConnection(shared_from_this());
167     TAG_LOGI(AAFwkTag::CONNECTION, "connectState:%{public}d", state_);
168 }
169 
CompleteDisconnect(int resultCode,bool isCallerDied,bool isTargetDied)170 void ConnectionRecord::CompleteDisconnect(int resultCode, bool isCallerDied, bool isTargetDied)
171 {
172     if (resultCode == ERR_OK) {
173         SetConnectState(ConnectionState::DISCONNECTED);
174     }
175     CHECK_POINTER(targetService_);
176     const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo();
177     AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
178         abilityInfo.name, abilityInfo.moduleName);
179     auto code = isTargetDied ? (resultCode - 1) : resultCode;
180     auto onDisconnectDoneTask = [connCallback = GetAbilityConnectCallback(), element, code]() {
181         TAG_LOGD(AAFwkTag::CONNECTION, "OnAbilityDisconnectDone");
182         if (!connCallback) {
183             TAG_LOGD(AAFwkTag::CONNECTION, "null connCallback");
184             return;
185         }
186         connCallback->OnAbilityDisconnectDone(element, code);
187     };
188     auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
189     if (handler == nullptr) {
190         TAG_LOGE(AAFwkTag::CONNECTION, "null handler");
191         return;
192     }
193     handler->SubmitTask(onDisconnectDoneTask);
194     DelayedSingleton<ConnectionStateManager>::GetInstance()->RemoveConnection(shared_from_this(), isCallerDied);
195     TAG_LOGD(AAFwkTag::CONNECTION, "result: %{public}d, connectState:%{public}d", resultCode, state_);
196 }
197 
ScheduleDisconnectAbilityDone()198 void ConnectionRecord::ScheduleDisconnectAbilityDone()
199 {
200     if (state_ != ConnectionState::DISCONNECTING) {
201         TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not disconnecting");
202         return;
203     }
204 
205     auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
206     if (handler == nullptr) {
207         TAG_LOGE(AAFwkTag::CONNECTION, "fail to get AbilityTaskHandler");
208     } else {
209         std::string taskName = std::string("DisconnectTimeout_") + std::to_string(recordId_);
210         handler->CancelTask(taskName);
211     }
212 
213     CompleteDisconnect(ERR_OK, GetAbilityConnectCallback() == nullptr);
214 }
215 
ScheduleConnectAbilityDone()216 void ConnectionRecord::ScheduleConnectAbilityDone()
217 {
218     if (state_ != ConnectionState::CONNECTING) {
219         TAG_LOGE(AAFwkTag::CONNECTION, "failed, current state not connecting");
220         return;
221     }
222 
223     sptr<IRemoteObject> hostproxy = nullptr;
224     if (connectWant_.HasParameter(UISERVICEHOSTPROXY_KEY)) {
225         hostproxy = connectWant_.GetRemoteObject(UISERVICEHOSTPROXY_KEY);
226     }
227     auto element = connectWant_.GetElement();
228     Want::ClearWant(&connectWant_);
229     connectWant_.SetElement(element);
230     if (hostproxy != nullptr) {
231         connectWant_.SetParam(UISERVICEHOSTPROXY_KEY, hostproxy);
232     }
233 
234     CancelConnectTimeoutTask();
235 
236     CompleteConnect();
237 }
238 
CancelConnectTimeoutTask()239 void ConnectionRecord::CancelConnectTimeoutTask()
240 {
241     auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetTaskHandler();
242     if (handler == nullptr) {
243         TAG_LOGE(AAFwkTag::CONNECTION, "fail to get AbilityTaskHandler");
244     } else {
245         std::string taskName = std::string("ConnectTimeout_") + std::to_string(recordId_);
246         handler->CancelTask(taskName);
247     }
248 }
249 
DisconnectTimeout()250 void ConnectionRecord::DisconnectTimeout()
251 {
252     CHECK_POINTER(targetService_);
253     /* force to disconnect */
254     /* so scheduler target service disconnect done */
255     DelayedSingleton<AbilityManagerService>::GetInstance()->ScheduleDisconnectAbilityDone(targetService_->GetToken());
256 }
257 
ConvertConnectionState(const ConnectionState & state) const258 std::string ConnectionRecord::ConvertConnectionState(const ConnectionState &state) const
259 {
260     switch (state) {
261         case ConnectionState::INIT:
262             return "INIT";
263         case ConnectionState::CONNECTING:
264             return "CONNECTING";
265         case ConnectionState::CONNECTED:
266             return "CONNECTED";
267         case ConnectionState::DISCONNECTING:
268             return "DISCONNECTING";
269         case ConnectionState::DISCONNECTED:
270             return "DISCONNECTED";
271         default:
272             return "INVALIDSTATE";
273     }
274 }
275 
Dump(std::vector<std::string> & info) const276 void ConnectionRecord::Dump(std::vector<std::string> &info) const
277 {
278     info.emplace_back("       > " + GetAbilityRecord()->GetAbilityInfo().bundleName + "/" +
279                       GetAbilityRecord()->GetAbilityInfo().name + "   connectionState #" +
280                       ConvertConnectionState(GetConnectState()));
281 }
282 
AttachCallerInfo()283 void ConnectionRecord::AttachCallerInfo()
284 {
285     callerTokenId_ = IPCSkeleton::GetCallingTokenID(); // tokenId identifies the real caller
286     auto targetRecord = Token::GetAbilityRecordByToken(callerToken_);
287     if (targetRecord) {
288         callerUid_ = targetRecord->GetUid();
289         callerPid_ = targetRecord->GetPid();
290         callerName_ = targetRecord->GetAbilityInfo().bundleName;
291         return;
292     }
293 
294     callerUid_ = static_cast<int32_t>(IPCSkeleton::GetCallingUid());
295     callerPid_ = static_cast<int32_t>(IPCSkeleton::GetCallingPid());
296     callerName_ = ConnectionStateManager::GetProcessNameByPid(callerPid_);
297 }
298 
GetCallerUid() const299 int32_t ConnectionRecord::GetCallerUid() const
300 {
301     return callerUid_;
302 }
303 
GetCallerPid() const304 int32_t ConnectionRecord::GetCallerPid() const
305 {
306     return callerPid_;
307 }
308 
GetCallerTokenId() const309 uint32_t ConnectionRecord::GetCallerTokenId() const
310 {
311     return callerTokenId_;
312 }
313 
GetCallerName() const314 std::string ConnectionRecord::GetCallerName() const
315 {
316     return callerName_;
317 }
318 
GetTargetToken() const319 sptr<IRemoteObject> ConnectionRecord::GetTargetToken() const
320 {
321     auto targetService = targetService_;
322     if (!targetService) {
323         return nullptr;
324     }
325 
326     auto token = targetService->GetToken();
327     if (!token) {
328         return nullptr;
329     }
330 
331     return token->AsObject();
332 }
333 
GetConnection() const334 sptr<IRemoteObject> ConnectionRecord::GetConnection() const
335 {
336     auto callback = GetAbilityConnectCallback();
337     if (!callback) {
338         return nullptr;
339     }
340 
341     return callback->AsObject();
342 }
343 
SetConnectWant(const Want & want)344 void ConnectionRecord::SetConnectWant(const Want &want)
345 {
346     connectWant_ = want;
347 }
348 
GetConnectWant() const349 Want ConnectionRecord::GetConnectWant() const
350 {
351     return connectWant_;
352 }
353 }  // namespace AAFwk
354 }  // namespace OHOS
355