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