1 /*
2 * Copyright (c) 2021-2022 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_manager.h"
17 #include "ability_connection.h"
18 #include "ability_context.h"
19 #include "ability_manager_client.h"
20 #include "dfx_dump_catcher.h"
21 #include "hichecker.h"
22 #include "hilog_tag_wrapper.h"
23 #include "ui_service_extension_connection_constants.h"
24
25 namespace OHOS {
26 namespace AbilityRuntime {
27 using namespace OHOS::HiviewDFX;
GetInstance()28 ConnectionManager& ConnectionManager::GetInstance()
29 {
30 static ConnectionManager connectionManager;
31 return connectionManager;
32 }
33
ConnectAbility(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,const sptr<AbilityConnectCallback> & connectCallback)34 ErrCode ConnectionManager::ConnectAbility(const sptr<IRemoteObject>& connectCaller,
35 const AAFwk::Want& want, const sptr<AbilityConnectCallback>& connectCallback)
36 {
37 return ConnectAbilityInner(connectCaller, want, AAFwk::DEFAULT_INVAL_VALUE, connectCallback);
38 }
39
ConnectAbilityWithAccount(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,int accountId,const sptr<AbilityConnectCallback> & connectCallback)40 ErrCode ConnectionManager::ConnectAbilityWithAccount(const sptr<IRemoteObject>& connectCaller,
41 const AAFwk::Want& want, int accountId, const sptr<AbilityConnectCallback>& connectCallback)
42 {
43 return ConnectAbilityInner(connectCaller, want, accountId, connectCallback);
44 }
45
ConnectUIServiceExtensionAbility(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,const sptr<AbilityConnectCallback> & connectCallback)46 ErrCode ConnectionManager::ConnectUIServiceExtensionAbility(const sptr<IRemoteObject>& connectCaller,
47 const AAFwk::Want& want, const sptr<AbilityConnectCallback>& connectCallback)
48 {
49 return ConnectAbilityInner(connectCaller, want, AAFwk::DEFAULT_INVAL_VALUE, connectCallback, true);
50 }
51
ConnectAbilityInner(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,int accountId,const sptr<AbilityConnectCallback> & connectCallback,bool isUIService)52 ErrCode ConnectionManager::ConnectAbilityInner(const sptr<IRemoteObject>& connectCaller,
53 const AAFwk::Want& want, int accountId, const sptr<AbilityConnectCallback>& connectCallback, bool isUIService)
54 {
55 if (connectCaller == nullptr || connectCallback == nullptr) {
56 TAG_LOGE(AAFwkTag::CONNECTION, "null connectCaller or connectCallback");
57 return AAFwk::ERR_INVALID_CALLER;
58 }
59
60 AppExecFwk::ElementName connectReceiver = want.GetElement();
61 TAG_LOGD(AAFwkTag::CONNECTION, "connectReceiver: %{public}s",
62 (connectReceiver.GetBundleName() + ":" + connectReceiver.GetAbilityName()).c_str());
63
64 sptr<AbilityConnection> abilityConnection;
65 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
66 auto connectionIter = abilityConnections_.begin();
67 for (; connectionIter != abilityConnections_.end(); ++connectionIter) {
68 if (MatchConnection(connectCaller, want, accountId, *connectionIter)) {
69 break;
70 }
71 }
72 if (connectionIter != abilityConnections_.end()) {
73 std::vector<sptr<AbilityConnectCallback>>& callbacks = connectionIter->second;
74 callbacks.push_back(connectCallback);
75 abilityConnection = connectionIter->first.abilityConnection;
76 if (!abilityConnection) {
77 TAG_LOGE(AAFwkTag::CONNECTION, "AbilityConnection not exist");
78 return AAFwk::ERR_INVALID_CALLER;
79 }
80 TAG_LOGI(AAFwkTag::CONNECTION, "abilityConnectionsSize: %{public}zu, ConnectionState: %{public}d",
81 abilityConnections_.size(), abilityConnection->GetConnectionState());
82 abilityConnection->AddConnectCallback(connectCallback);
83 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnection exist, callbackSize:%{public}zu", callbacks.size());
84 if (abilityConnection->GetConnectionState() == CONNECTION_STATE_CONNECTED) {
85 connectCallback->OnAbilityConnectDone(connectReceiver, abilityConnection->GetRemoteObject(),
86 abilityConnection->GetResultCode());
87 return ERR_OK;
88 } else if (abilityConnection->GetConnectionState() == CONNECTION_STATE_CONNECTING) {
89 return ERR_OK;
90 } else {
91 TAG_LOGE(AAFwkTag::CONNECTION, "AbilityConnection disconnected, erase it and reconnect");
92 abilityConnections_.erase(connectionIter);
93 return CreateConnection(connectCaller, want, accountId, connectCallback, isUIService);
94 }
95 } else {
96 return CreateConnection(connectCaller, want, accountId, connectCallback, isUIService);
97 }
98 }
99
GetUIServiceExtProxyPtr(const AAFwk::Want & want)100 void* ConnectionManager::GetUIServiceExtProxyPtr(const AAFwk::Want& want)
101 {
102 sptr<IRemoteObject> uiServiceExtProxySptr = want.GetRemoteObject(UISERVICEHOSTPROXY_KEY);
103 void* uiServiceExtProxy = nullptr;
104 if (uiServiceExtProxySptr != nullptr) {
105 uiServiceExtProxy = uiServiceExtProxySptr.GetRefPtr();
106 }
107 return uiServiceExtProxy;
108 }
109
MatchConnection(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & connectReceiver,int32_t accountId,const std::map<ConnectionInfo,std::vector<sptr<AbilityConnectCallback>>>::value_type & connection)110 bool ConnectionManager::MatchConnection(
111 const sptr<IRemoteObject>& connectCaller, const AAFwk::Want& connectReceiver, int32_t accountId,
112 const std::map<ConnectionInfo, std::vector<sptr<AbilityConnectCallback>>>::value_type& connection)
113 {
114 void* uiServiceExtProxy = GetUIServiceExtProxyPtr(connectReceiver);
115 if (uiServiceExtProxy != connection.first.uiServiceExtProxy) {
116 return false;
117 }
118
119 if (accountId != connection.first.userid) {
120 return false;
121 }
122 if (!connectReceiver.GetElement().GetAbilityName().empty()) {
123 return connectCaller == connection.first.connectCaller &&
124 connectReceiver.GetElement().GetBundleName() == connection.first.connectReceiver.GetBundleName() &&
125 connectReceiver.GetElement().GetModuleName() == connection.first.connectReceiver.GetModuleName() &&
126 connectReceiver.GetElement().GetAbilityName() == connection.first.connectReceiver.GetAbilityName();
127 } else {
128 // ImplicitConnect
129 return connectCaller == connection.first.connectCaller &&
130 connectReceiver.GetElement().GetBundleName() == connection.first.connectReceiver.GetBundleName() &&
131 connectReceiver.GetOperation() == connection.first.connectReceiver;
132 }
133 }
134
CreateConnection(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,int accountId,const sptr<AbilityConnectCallback> & connectCallback,bool isUIService)135 ErrCode ConnectionManager::CreateConnection(const sptr<IRemoteObject>& connectCaller,
136 const AAFwk::Want& want, int accountId, const sptr<AbilityConnectCallback>& connectCallback, bool isUIService)
137 {
138 TAG_LOGD(AAFwkTag::CONNECTION, "called");
139 sptr<AbilityConnection> abilityConnection = new AbilityConnection();
140 if (abilityConnection == nullptr) {
141 TAG_LOGE(AAFwkTag::CONNECTION, "create connection failed");
142 return AAFwk::ERR_INVALID_CALLER;
143 }
144 abilityConnection->AddConnectCallback(connectCallback);
145 abilityConnection->SetConnectionState(CONNECTION_STATE_CONNECTING);
146 ErrCode ret = ERR_OK;
147 if (isUIService) {
148 ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectUIServiceExtesnionAbility(
149 want, abilityConnection, connectCaller, accountId);
150 } else {
151 ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(
152 want, abilityConnection, connectCaller, accountId);
153 }
154 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
155 if (ret == ERR_OK) {
156 ConnectionInfo connectionInfo(connectCaller, want.GetOperation(), abilityConnection, accountId);
157 void* uiServiceExtProxy = GetUIServiceExtProxyPtr(want);
158 connectionInfo.SetUIServiceExtProxyPtr(uiServiceExtProxy);
159 std::vector<sptr<AbilityConnectCallback>> callbacks;
160 callbacks.push_back(connectCallback);
161 abilityConnections_[connectionInfo] = callbacks;
162 } else {
163 TAG_LOGE(AAFwkTag::CONNECTION, "AMS ConnectAbility error:%{public}d", ret);
164 }
165 return ret;
166 }
167
DisconnectAbility(const sptr<IRemoteObject> & connectCaller,const AppExecFwk::ElementName & connectReceiver,const sptr<AbilityConnectCallback> & connectCallback)168 ErrCode ConnectionManager::DisconnectAbility(const sptr<IRemoteObject>& connectCaller,
169 const AppExecFwk::ElementName& connectReceiver, const sptr<AbilityConnectCallback>& connectCallback)
170 {
171 AAFwk::Want wantReceiver;
172 wantReceiver.SetElement(connectReceiver);
173 return DisconnectAbility(connectCaller, wantReceiver, connectCallback);
174 }
175
DisconnectAbility(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & connectReceiver,const sptr<AbilityConnectCallback> & connectCallback,int32_t accountId)176 ErrCode ConnectionManager::DisconnectAbility(const sptr<IRemoteObject>& connectCaller,
177 const AAFwk::Want& connectReceiver, const sptr<AbilityConnectCallback>& connectCallback,
178 int32_t accountId)
179 {
180 if (connectCaller == nullptr || connectCallback == nullptr) {
181 TAG_LOGE(AAFwkTag::CONNECTION, "null connectCaller or connectCallback");
182 return AAFwk::ERR_INVALID_CALLER;
183 }
184
185 auto element = connectReceiver.GetElement();
186 TAG_LOGD(AAFwkTag::CONNECTION, "connectReceiver: %{public}s",
187 (element.GetBundleName() + ":" + element.GetAbilityName()).c_str());
188 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
189 auto item = std::find_if(abilityConnections_.begin(), abilityConnections_.end(),
190 [&connectCaller, &connectReceiver, this, accountId](const auto& obj) {
191 return MatchConnection(connectCaller, connectReceiver, accountId, obj);
192 });
193 if (item != abilityConnections_.end()) {
194 TAG_LOGD(AAFwkTag::CONNECTION, "remove callback, Size:%{public}zu", item->second.size());
195 auto iter = item->second.begin();
196 while (iter != item->second.end()) {
197 if (*iter == connectCallback) {
198 iter = item->second.erase(iter);
199 } else {
200 iter++;
201 }
202 }
203
204 sptr<AbilityConnection> abilityConnection = item->first.abilityConnection;
205
206 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnection exist, size:%{public}zu",
207 abilityConnections_.size());
208 if (item->second.empty()) {
209 abilityConnections_.erase(item);
210 TAG_LOGD(AAFwkTag::CONNECTION, "no callback left, disconnectAbility");
211 return AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(abilityConnection);
212 } else {
213 connectCallback->OnAbilityDisconnectDone(element, ERR_OK);
214 abilityConnection->RemoveConnectCallback(connectCallback);
215 TAG_LOGD(AAFwkTag::CONNECTION, "callbacks not empty, no need disconnectAbility");
216 return ERR_OK;
217 }
218 } else {
219 TAG_LOGE(AAFwkTag::CONNECTION, "not find conn");
220 return AAFwk::CONNECTION_NOT_EXIST;
221 }
222 }
223
DisconnectCaller(const sptr<IRemoteObject> & connectCaller)224 bool ConnectionManager::DisconnectCaller(const sptr<IRemoteObject>& connectCaller)
225 {
226 TAG_LOGD(AAFwkTag::CONNECTION, "call");
227 if (connectCaller == nullptr) {
228 TAG_LOGE(AAFwkTag::CONNECTION, "null connectCaller");
229 return false;
230 }
231 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
232 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnectionsSize:%{public}zu", abilityConnections_.size());
233
234 bool isDisconnect = false;
235 auto iter = abilityConnections_.begin();
236 while (iter != abilityConnections_.end()) {
237 ConnectionInfo connectionInfo = iter->first;
238 if (IsConnectCallerEqual(connectionInfo.connectCaller, connectCaller)) {
239 TAG_LOGD(AAFwkTag::CONNECTION, "DisconnectAbility");
240 ErrCode ret =
241 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(connectionInfo.abilityConnection);
242 if (ret != ERR_OK) {
243 TAG_LOGE(AAFwkTag::CONNECTION, "AMS DisconnectAbility error, ret:%{public}d", ret);
244 }
245 iter = abilityConnections_.erase(iter);
246 isDisconnect = true;
247 } else {
248 ++iter;
249 }
250 }
251
252 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnectionsSize:%{public}zu", abilityConnections_.size());
253 return isDisconnect;
254 }
255
RemoveConnection(const sptr<AbilityConnection> connection)256 bool ConnectionManager::RemoveConnection(const sptr<AbilityConnection> connection)
257 {
258 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
259 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnectionsSize: %{public}zu", abilityConnections_.size());
260
261 bool isDisconnect = false;
262 auto iter = abilityConnections_.begin();
263 while (iter != abilityConnections_.end()) {
264 ConnectionInfo connectionInfo = iter->first;
265 if (connectionInfo.abilityConnection == connection) {
266 TAG_LOGD(AAFwkTag::CONNECTION, "Remove connection");
267 iter = abilityConnections_.erase(iter);
268 isDisconnect = true;
269 } else {
270 ++iter;
271 }
272 }
273 return isDisconnect;
274 }
275
DisconnectNonexistentService(const AppExecFwk::ElementName & element,const sptr<AbilityConnection> connection)276 bool ConnectionManager::DisconnectNonexistentService(
277 const AppExecFwk::ElementName& element, const sptr<AbilityConnection> connection)
278 {
279 bool exit = false;
280 std::map<ConnectionInfo, std::vector<sptr<AbilityConnectCallback>>> abilityConnections;
281 {
282 std::lock_guard<std::recursive_mutex> lock(connectionsLock_);
283 abilityConnections = abilityConnections_;
284 }
285 TAG_LOGD(AAFwkTag::CONNECTION, "abilityConnectionsSize: %{public}zu", abilityConnections.size());
286
287 for (auto &&abilityConnection : abilityConnections) {
288 ConnectionInfo connectionInfo = abilityConnection.first;
289 if (connectionInfo.abilityConnection == connection &&
290 connectionInfo.connectReceiver.GetBundleName() == element.GetBundleName()) {
291 TAG_LOGD(AAFwkTag::CONNECTION, "find connection");
292 exit = true;
293 break;
294 }
295 }
296 if (!exit) {
297 TAG_LOGE(AAFwkTag::CONNECTION, "service need disconnect");
298 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(connection);
299 return true;
300 }
301 return false;
302 }
303
ReportConnectionLeakEvent(const int pid,const int tid)304 void ConnectionManager::ReportConnectionLeakEvent(const int pid, const int tid)
305 {
306 TAG_LOGD(AAFwkTag::CONNECTION, "pid:%{public}d, tid:%{public}d", pid, tid);
307 if (HiChecker::Contains(Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK)) {
308 DfxDumpCatcher dumpLog;
309 std::string stackTrace;
310 bool ret = dumpLog.DumpCatch(pid, tid, stackTrace);
311 if (ret) {
312 std::string cautionMsg = "TriggerRule:RULE_CHECK_ABILITY_CONNECTION_LEAK-pid=" +
313 std::to_string(pid) + "-tid=" + std::to_string(tid) + ", has leaked connection" +
314 ", Are you missing a call to DisconnectAbility()";
315 TAG_LOGD(AAFwkTag::CONNECTION, "cautionMsg:%{public}s", cautionMsg.c_str());
316 Caution caution(Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK, cautionMsg, stackTrace);
317 HiChecker::NotifyAbilityConnectionLeak(caution);
318 } else {
319 TAG_LOGE(AAFwkTag::CONNECTION, "dumpCatch stackTrace failed");
320 }
321 }
322 }
323
IsConnectCallerEqual(const sptr<IRemoteObject> & connectCaller,const sptr<IRemoteObject> & connectCallerOther)324 bool ConnectionManager::IsConnectCallerEqual(const sptr<IRemoteObject>& connectCaller,
325 const sptr<IRemoteObject>& connectCallerOther)
326 {
327 return connectCaller == connectCallerOther;
328 }
329
IsConnectReceiverEqual(AAFwk::Operation & connectReceiver,const AppExecFwk::ElementName & connectReceiverOther)330 bool ConnectionManager::IsConnectReceiverEqual(AAFwk::Operation& connectReceiver,
331 const AppExecFwk::ElementName& connectReceiverOther)
332 {
333 return connectReceiver.GetBundleName() == connectReceiverOther.GetBundleName() &&
334 connectReceiver.GetAbilityName() == connectReceiverOther.GetAbilityName();
335 }
336 } // namespace AbilityRuntime
337 } // namespace OHOS
338