• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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