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_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_wrapper.h"
23
24 namespace OHOS {
25 namespace AbilityRuntime {
26 using namespace OHOS::HiviewDFX;
GetInstance()27 ConnectionManager& ConnectionManager::GetInstance()
28 {
29 static ConnectionManager connectionManager;
30 return connectionManager;
31 }
32
ConnectAbility(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,const sptr<AbilityConnectCallback> & connectCallback)33 ErrCode ConnectionManager::ConnectAbility(const sptr<IRemoteObject> &connectCaller,
34 const AAFwk::Want &want, const sptr<AbilityConnectCallback> &connectCallback)
35 {
36 return ConnectAbilityInner(connectCaller, want, AAFwk::DEFAULT_INVAL_VALUE, connectCallback);
37 }
38
ConnectAbilityWithAccount(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,int accountId,const sptr<AbilityConnectCallback> & connectCallback)39 ErrCode ConnectionManager::ConnectAbilityWithAccount(const sptr<IRemoteObject> &connectCaller,
40 const AAFwk::Want &want, int accountId, const sptr<AbilityConnectCallback> &connectCallback)
41 {
42 return ConnectAbilityInner(connectCaller, want, accountId, connectCallback);
43 }
44
ConnectAbilityInner(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,int accountId,const sptr<AbilityConnectCallback> & connectCallback)45 ErrCode ConnectionManager::ConnectAbilityInner(const sptr<IRemoteObject> &connectCaller,
46 const AAFwk::Want &want, int accountId, const sptr<AbilityConnectCallback> &connectCallback)
47 {
48 if (connectCaller == nullptr || connectCallback == nullptr) {
49 HILOG_ERROR("%{public}s, connectCaller or connectCallback is nullptr.", __func__);
50 return ERR_INVALID_VALUE;
51 }
52
53 AppExecFwk::ElementName connectReceiver = want.GetElement();
54 HILOG_DEBUG("%{public}s begin, connectCaller: %{public}p, connectReceiver: %{public}s.",
55 __func__, connectCaller.GetRefPtr(),
56 (connectReceiver.GetBundleName() + ":" + connectReceiver.GetAbilityName()).c_str());
57
58 sptr<AbilityConnection> abilityConnection;
59 auto item = std::find_if(abilityConnections_.begin(), abilityConnections_.end(),
60 [&connectCaller, &connectReceiver](const std::map<ConnectionInfo,
61 std::vector<sptr<AbilityConnectCallback>>>::value_type &obj) {
62 return connectCaller == obj.first.connectCaller &&
63 connectReceiver.GetBundleName() == obj.first.connectReceiver.GetBundleName() &&
64 connectReceiver.GetAbilityName() == obj.first.connectReceiver.GetAbilityName();
65 });
66 if (item != abilityConnections_.end()) {
67 std::vector<sptr<AbilityConnectCallback>> callbacks = item->second;
68 callbacks.push_back(connectCallback);
69 abilityConnections_[item->first] = callbacks;
70 abilityConnection = item->first.abilityConnection;
71 abilityConnection->SetConnectCallback(connectCallback);
72 HILOG_INFO("%{public}s end, find abilityConnection:%{public}p exist, callbackSize:%{public}d.",
73 __func__, abilityConnection.GetRefPtr(), (int32_t)callbacks.size());
74 if (abilityConnection->GetResultCode() == ERR_OK) {
75 connectCallback->OnAbilityConnectDone(connectReceiver, abilityConnection->GetRemoteObject(),
76 abilityConnection->GetResultCode());
77 return ERR_OK;
78 } else {
79 return HandleCallbackTimeOut(connectCaller, want, connectReceiver, abilityConnection, connectCallback);
80 }
81 } else {
82 abilityConnection = new AbilityConnection(connectCallback);
83 ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(
84 want, abilityConnection, connectCaller, accountId);
85 if (ret == ERR_OK) {
86 ConnectionInfo connectionInfo(connectCaller, connectReceiver, abilityConnection);
87 std::vector<sptr<AbilityConnectCallback>> callbacks;
88 callbacks.push_back(connectCallback);
89 abilityConnections_[connectionInfo] = callbacks;
90 }
91 HILOG_DEBUG("%{public}s end, not find connection, connection: %{public}p, abilityConnectionsSize:%{public}d.",
92 __func__, abilityConnection.GetRefPtr(), (int32_t)abilityConnections_.size());
93 return ret;
94 }
95 }
96
DisconnectAbility(const sptr<IRemoteObject> & connectCaller,const AppExecFwk::ElementName & connectReceiver,const sptr<AbilityConnectCallback> & connectCallback)97 ErrCode ConnectionManager::DisconnectAbility(const sptr<IRemoteObject> &connectCaller,
98 const AppExecFwk::ElementName &connectReceiver, const sptr<AbilityConnectCallback> &connectCallback)
99 {
100 if (connectCaller == nullptr || connectCallback == nullptr) {
101 HILOG_ERROR("%{public}s, connectCaller or connectCallback is nullptr.", __func__);
102 return ERR_INVALID_VALUE;
103 }
104
105 HILOG_DEBUG("%{public}s begin, connectCaller: %{public}p, connectReceiver: %{public}s.",
106 __func__, connectCaller.GetRefPtr(),
107 (connectReceiver.GetBundleName() + ":" + connectReceiver.GetAbilityName()).c_str());
108
109 auto item = std::find_if(abilityConnections_.begin(), abilityConnections_.end(),
110 [&connectCaller, &connectReceiver](
111 const std::map<ConnectionInfo, std::vector<sptr<AbilityConnectCallback>>>::value_type &obj) {
112 return connectCaller == obj.first.connectCaller &&
113 connectReceiver.GetBundleName() == obj.first.connectReceiver.GetBundleName() &&
114 connectReceiver.GetAbilityName() == obj.first.connectReceiver.GetAbilityName();
115 });
116 if (item != abilityConnections_.end()) {
117 std::vector<sptr<AbilityConnectCallback>> callbacks = item->second;
118 HILOG_DEBUG("%{public}s begin remove callback, callbackSize:%{public}d.", __func__, (int32_t)callbacks.size());
119 auto iter = callbacks.begin();
120 while (iter != callbacks.end()) {
121 if (*iter == connectCallback) {
122 iter = callbacks.erase(iter);
123 } else {
124 iter++;
125 }
126 }
127 abilityConnections_[item->first] = callbacks;
128 sptr<AbilityConnection> abilityConnection;
129 abilityConnection = item->first.abilityConnection;
130 abilityConnection->SetConnectCallback(connectCallback);
131 HILOG_INFO("%{public}s end, find abilityConnection:%{public}p exist, abilityConnectionsSize:%{public}d.",
132 __func__, abilityConnection.GetRefPtr(), (int32_t)abilityConnections_.size());
133 if (callbacks.size() == 0) {
134 abilityConnections_.erase(item);
135 HILOG_DEBUG("%{public}s disconnectAbility.", __func__);
136 return AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(abilityConnection);
137 } else {
138 connectCallback->OnAbilityDisconnectDone(connectReceiver, ERR_OK);
139 HILOG_DEBUG("%{public}s callbacks is not empty, do not need disconnectAbility.", __func__);
140 return ERR_OK;
141 }
142 } else {
143 HILOG_ERROR("%{public}s not find conn exist.", __func__);
144 return ERR_INVALID_VALUE;
145 }
146 }
147
DisconnectCaller(const sptr<IRemoteObject> & connectCaller)148 bool ConnectionManager::DisconnectCaller(const sptr<IRemoteObject> &connectCaller)
149 {
150 HILOG_DEBUG("%{public}s begin.", __func__);
151 if (connectCaller == nullptr) {
152 HILOG_ERROR("%{public}s end, connectCaller is nullptr.", __func__);
153 return false;
154 }
155
156 HILOG_DEBUG("%{public}s, connectCaller:%{public}p, abilityConnectionsSize:%{public}d.",
157 __func__, connectCaller.GetRefPtr(), (int32_t)abilityConnections_.size());
158
159 bool isDisconnect = false;
160 auto iter = abilityConnections_.begin();
161 while (iter != abilityConnections_.end()) {
162 ConnectionInfo connectionInfo = iter->first;
163 if (IsConnectCallerEqual(connectionInfo.connectCaller, connectCaller)) {
164 HILOG_DEBUG("%{public}s DisconnectAbility connection:%{public}p.",
165 __func__, connectionInfo.abilityConnection.GetRefPtr());
166 ErrCode ret =
167 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(connectionInfo.abilityConnection);
168 if (ret != ERR_OK) {
169 HILOG_ERROR("%{public}s ams->DisconnectAbility error, ret=%{public}d", __func__, ret);
170 }
171 iter = abilityConnections_.erase(iter);
172 isDisconnect = true;
173 } else {
174 ++iter;
175 }
176 }
177
178 HILOG_DEBUG("%{public}s end, abilityConnectionsSize:%{public}d.", __func__, (int32_t)abilityConnections_.size());
179 return isDisconnect;
180 }
181
DisconnectReceiver(const AppExecFwk::ElementName & connectReceiver)182 bool ConnectionManager::DisconnectReceiver(const AppExecFwk::ElementName &connectReceiver)
183 {
184 HILOG_DEBUG("%{public}s begin, abilityConnectionsSize:%{public}d, bundleName:%{public}s, abilityName:%{public}s.",
185 __func__, (int32_t)abilityConnections_.size(), connectReceiver.GetBundleName().c_str(),
186 connectReceiver.GetAbilityName().c_str());
187
188 bool isDisconnect = false;
189 auto iter = abilityConnections_.begin();
190 while (iter != abilityConnections_.end()) {
191 ConnectionInfo connectionInfo = iter->first;
192 if (IsConnectReceiverEqual(connectionInfo.connectReceiver, connectReceiver)) {
193 iter = abilityConnections_.erase(iter);
194 isDisconnect = true;
195 } else {
196 ++iter;
197 }
198 }
199
200 HILOG_DEBUG("%{public}s end, abilityConnectionsSize:%{public}d.", __func__, (int32_t)abilityConnections_.size());
201 return isDisconnect;
202 }
203
ReportConnectionLeakEvent(const int pid,const int tid)204 void ConnectionManager::ReportConnectionLeakEvent(const int pid, const int tid)
205 {
206 HILOG_DEBUG("%{public}s begin, pid:%{public}d, tid:%{public}d.", __func__, pid, tid);
207 if (HiChecker::Contains(Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK)) {
208 DfxDumpCatcher dumplog;
209 std::string stackTrace;
210 bool ret = dumplog.DumpCatch(pid, tid, stackTrace);
211 if (ret) {
212 std::string cautionMsg = "TriggerRule:RULE_CHECK_ABILITY_CONNECTION_LEAK-pid=" +
213 std::to_string(pid) + "-tid=" + std::to_string(tid) + ", has leaked connection" +
214 ", Are you missing a call to DisconnectAbility()";
215 HILOG_DEBUG("%{public}s cautionMsg:%{public}s.", __func__, cautionMsg.c_str());
216 Caution caution(Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK, cautionMsg, stackTrace);
217 HiChecker::NotifyAbilityConnectionLeak(caution);
218 } else {
219 HILOG_ERROR("%{public}s dumpCatch stackTrace failed.", __func__);
220 }
221 }
222 }
223
IsConnectCallerEqual(const sptr<IRemoteObject> & connectCaller,const sptr<IRemoteObject> & connectCallerOther)224 bool ConnectionManager::IsConnectCallerEqual(const sptr<IRemoteObject> &connectCaller,
225 const sptr<IRemoteObject> &connectCallerOther)
226 {
227 return connectCaller == connectCallerOther;
228 }
229
IsConnectReceiverEqual(const AppExecFwk::ElementName & connectReceiver,const AppExecFwk::ElementName & connectReceiverOther)230 bool ConnectionManager::IsConnectReceiverEqual(const AppExecFwk::ElementName &connectReceiver,
231 const AppExecFwk::ElementName &connectReceiverOther)
232 {
233 return connectReceiver.GetBundleName() == connectReceiverOther.GetBundleName() &&
234 connectReceiver.GetAbilityName() == connectReceiverOther.GetAbilityName();
235 }
236
HandleCallbackTimeOut(const sptr<IRemoteObject> & connectCaller,const AAFwk::Want & want,const AppExecFwk::ElementName & connectReceiver,sptr<AbilityConnection> abilityConnection,const sptr<AbilityConnectCallback> & connectCallback)237 ErrCode ConnectionManager::HandleCallbackTimeOut(const sptr<IRemoteObject> &connectCaller, const AAFwk::Want &want,
238 const AppExecFwk::ElementName &connectReceiver, sptr<AbilityConnection> abilityConnection,
239 const sptr<AbilityConnectCallback> &connectCallback)
240 {
241 if (abilityConnection->GetRemoteObject() == nullptr) {
242 while (true) {
243 if (abilityConnection->GetRemoteObject() != nullptr) {
244 connectCallback->OnAbilityConnectDone(connectReceiver, abilityConnection->GetRemoteObject(),
245 abilityConnection->GetResultCode());
246 return ERR_OK;
247 }
248 }
249 } else {
250 return AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, abilityConnection, connectCaller);
251 }
252 }
253 } // namespace AbilityRuntime
254 } // namespace OHOS