1 /*
2 * Copyright (c) 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_state_manager.h"
17
18 #include <fstream>
19
20 #include "app_mgr_interface.h"
21 #include "connection_observer_errors.h"
22 #include "hilog_wrapper.h"
23 #include "if_system_ability_manager.h"
24 #include "iservice_registry.h"
25 #include "system_ability_definition.h"
26
27 namespace OHOS {
28 namespace AAFwk {
29 namespace {
30 static const int MAX_PROCESS_LEN = 256;
GetAppMgr()31 OHOS::sptr<OHOS::AppExecFwk::IAppMgr> GetAppMgr()
32 {
33 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
34 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
35 if (!systemAbilityManager) {
36 return nullptr;
37 }
38 OHOS::sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
39 return OHOS::iface_cast<OHOS::AppExecFwk::IAppMgr>(object);
40 }
41 }
42 using namespace OHOS::AbilityRuntime;
43
ConnectionStateManager()44 ConnectionStateManager::ConnectionStateManager() {}
45
~ConnectionStateManager()46 ConnectionStateManager::~ConnectionStateManager() {}
47
GetProcessNameByPid(int32_t pid)48 std::string ConnectionStateManager::GetProcessNameByPid(int32_t pid)
49 {
50 char path[MAX_PROCESS_LEN] = { 0 };
51 if (snprintf_s(path, MAX_PROCESS_LEN, MAX_PROCESS_LEN - 1, "/proc/%d/cmdline", pid) <= 0) {
52 return "";
53 }
54 std::ifstream file(path);
55 std::string name = "";
56 getline(file, name);
57 return name;
58 }
59
Init()60 void ConnectionStateManager::Init()
61 {
62 if (!observerController_) {
63 observerController_ = std::make_shared<ConnectionObserverController>();
64 }
65 InitAppStateObserver();
66 }
67
RegisterObserver(const sptr<AbilityRuntime::IConnectionObserver> & observer)68 int ConnectionStateManager::RegisterObserver(const sptr<AbilityRuntime::IConnectionObserver> &observer)
69 {
70 if (!observerController_) {
71 return ERR_SERVICE_NOT_INIT;
72 }
73
74 return observerController_->AddObserver(observer);
75 }
76
UnregisterObserver(const sptr<AbilityRuntime::IConnectionObserver> & observer)77 int ConnectionStateManager::UnregisterObserver(const sptr<AbilityRuntime::IConnectionObserver> &observer)
78 {
79 if (!observerController_) {
80 return ERR_SERVICE_NOT_INIT;
81 }
82 observerController_->RemoveObserver(observer);
83
84 return 0;
85 }
86
AddConnection(const std::shared_ptr<ConnectionRecord> & connectionRecord)87 void ConnectionStateManager::AddConnection(const std::shared_ptr<ConnectionRecord> &connectionRecord)
88 {
89 std::shared_ptr<ConnectionObserverController> controller = observerController_;
90 if (!controller) {
91 return;
92 }
93
94 if (!connectionRecord) {
95 HILOG_ERROR("connection record is invalid");
96 return;
97 }
98
99 ConnectionData connectionData;
100 if (!AddConnectionInner(connectionRecord, connectionData)) {
101 HILOG_WARN("add connection, no need to notify observers");
102 return;
103 }
104 controller->NotifyExtensionConnected(connectionData);
105 }
106
RemoveConnection(const std::shared_ptr<ConnectionRecord> & connectionRecord,bool isCallerDied)107 void ConnectionStateManager::RemoveConnection(const std::shared_ptr<ConnectionRecord> &connectionRecord,
108 bool isCallerDied)
109 {
110 std::shared_ptr<ConnectionObserverController> controller = observerController_;
111 if (!controller) {
112 return;
113 }
114
115 if (!connectionRecord) {
116 HILOG_ERROR("connection record is invalid when remove connection");
117 return;
118 }
119
120 // if caller died, notify at once.
121 if (isCallerDied) {
122 HandleCallerDied(connectionRecord->GetCallerPid());
123 return;
124 }
125
126 ConnectionData connectionData;
127 if (!RemoveConnectionInner(connectionRecord, connectionData)) {
128 HILOG_WARN("remove connection, no need to notify observers");
129 return;
130 }
131 controller->NotifyExtensionDisconnected(connectionData);
132 }
133
AddDataAbilityConnection(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & record)134 void ConnectionStateManager::AddDataAbilityConnection(const DataAbilityCaller &caller,
135 const std::shared_ptr<DataAbilityRecord> &record)
136 {
137 if (!CheckDataAbilityConnectionParams(caller, record)) {
138 return;
139 }
140
141 ConnectionData connectionData;
142 if (!AddDataAbilityConnectionInner(caller, record, connectionData)) {
143 HILOG_WARN("add data ability onnection, no need to notify observers");
144 return;
145 }
146 observerController_->NotifyExtensionConnected(connectionData);
147 }
148
RemoveDataAbilityConnection(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & record)149 void ConnectionStateManager::RemoveDataAbilityConnection(const DataAbilityCaller &caller,
150 const std::shared_ptr<DataAbilityRecord> &record)
151 {
152 if (!CheckDataAbilityConnectionParams(caller, record)) {
153 return;
154 }
155
156 ConnectionData connectionData;
157 if (!RemoveDataAbilityConnectionInner(caller, record, connectionData)) {
158 HILOG_WARN("remove data ability, no need to notify observers");
159 return;
160 }
161 observerController_->NotifyExtensionDisconnected(connectionData);
162 }
163
CheckDataAbilityConnectionParams(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & record) const164 bool ConnectionStateManager::CheckDataAbilityConnectionParams(const DataAbilityCaller &caller,
165 const std::shared_ptr<DataAbilityRecord> &record) const
166 {
167 if (!observerController_) {
168 return false;
169 }
170
171 if (!record) {
172 HILOG_ERROR("data ability record is invalid");
173 return false;
174 }
175
176 if (caller.callerPid == 0) {
177 HILOG_ERROR("data ability, invalid caller pid");
178 return false;
179 }
180
181 return true;
182 }
183
HandleDataAbilityDied(const std::shared_ptr<DataAbilityRecord> & record)184 void ConnectionStateManager::HandleDataAbilityDied(const std::shared_ptr<DataAbilityRecord> &record)
185 {
186 if (!record) {
187 HILOG_ERROR("invalid data ability.");
188 return;
189 }
190
191 auto token = record->GetToken();
192 if (!token) {
193 HILOG_ERROR("invalid data ability token.");
194 return;
195 }
196
197 std::vector<AbilityRuntime::ConnectionData> allData;
198 HandleDataAbilityDiedInner(token, allData);
199 if (allData.empty()) {
200 HILOG_WARN("allConnectionData is empty.");
201 return;
202 }
203
204 std::shared_ptr<ConnectionObserverController> controller = observerController_;
205 if (!controller) {
206 return;
207 }
208
209 for (auto& item : allData) {
210 controller->NotifyExtensionDisconnected(item);
211 }
212 }
213
HandleDataAbilityCallerDied(int32_t callerPid)214 void ConnectionStateManager::HandleDataAbilityCallerDied(int32_t callerPid)
215 {
216 if (callerPid <= 0) {
217 HILOG_WARN("invalid data ability caller pid.");
218 return;
219 }
220
221 HandleCallerDied(callerPid);
222 }
223
AddDlpManager(const std::shared_ptr<AbilityRecord> & dlpManger)224 void ConnectionStateManager::AddDlpManager(const std::shared_ptr<AbilityRecord> &dlpManger)
225 {
226 if (!dlpManger) {
227 return;
228 }
229
230 auto userId = dlpManger->GetOwnerMissionUserId();
231 std::lock_guard<std::recursive_mutex> guard(dlpLock_);
232 auto it = dlpItems_.find(userId);
233 if (it == dlpItems_.end()) {
234 dlpItems_[userId] = std::make_shared<DlpStateItem>(dlpManger->GetUid(), dlpManger->GetPid());
235 }
236 }
237
RemoveDlpManager(const std::shared_ptr<AbilityRecord> & dlpManger)238 void ConnectionStateManager::RemoveDlpManager(const std::shared_ptr<AbilityRecord> &dlpManger)
239 {
240 if (!dlpManger) {
241 return;
242 }
243
244 std::lock_guard<std::recursive_mutex> guard(dlpLock_);
245 dlpItems_.erase(dlpManger->GetOwnerMissionUserId());
246 }
247
AddDlpAbility(const std::shared_ptr<AbilityRecord> & dlpAbility)248 void ConnectionStateManager::AddDlpAbility(const std::shared_ptr<AbilityRecord> &dlpAbility)
249 {
250 std::shared_ptr<ConnectionObserverController> controller = observerController_;
251 if (!controller) {
252 return;
253 }
254
255 DlpStateData dlpData;
256 if (!HandleDlpAbilityInner(dlpAbility, true, dlpData)) {
257 HILOG_DEBUG("no need to report dlp opened connection state.");
258 return;
259 }
260 controller->NotifyDlpAbilityOpened(dlpData);
261 }
262
RemoveDlpAbility(const std::shared_ptr<AbilityRecord> & dlpAbility)263 void ConnectionStateManager::RemoveDlpAbility(const std::shared_ptr<AbilityRecord> &dlpAbility)
264 {
265 std::shared_ptr<ConnectionObserverController> controller = observerController_;
266 if (!controller) {
267 return;
268 }
269
270 DlpStateData dlpData;
271 if (!HandleDlpAbilityInner(dlpAbility, false, dlpData)) {
272 HILOG_DEBUG("no need to report dlp closed connection state.");
273 return;
274 }
275 controller->NotifyDlpAbilityClosed(dlpData);
276 }
277
HandleAppDied(int32_t pid)278 void ConnectionStateManager::HandleAppDied(int32_t pid)
279 {
280 HandleCallerDied(pid);
281 }
282
GetDlpConnectionInfos(std::vector<AbilityRuntime::DlpConnectionInfo> & infos)283 void ConnectionStateManager::GetDlpConnectionInfos(std::vector<AbilityRuntime::DlpConnectionInfo> &infos)
284 {
285 std::lock_guard<std::recursive_mutex> guard(dlpLock_);
286 for (auto it = dlpItems_.begin(); it != dlpItems_.end(); it++) {
287 auto item = it->second;
288 if (!item) {
289 continue;
290 }
291
292 AbilityRuntime::DlpConnectionInfo info;
293 info.dlpUid = item->GetDlpUid();
294 info.openedAbilityCount = item->GetOpenedAbilitySize();
295 infos.emplace_back(info);
296 }
297 }
298
AddConnectionInner(const std::shared_ptr<ConnectionRecord> & connectionRecord,AbilityRuntime::ConnectionData & data)299 bool ConnectionStateManager::AddConnectionInner(const std::shared_ptr<ConnectionRecord> &connectionRecord,
300 AbilityRuntime::ConnectionData &data)
301 {
302 std::shared_ptr<ConnectionStateItem> targetItem = nullptr;
303 auto callerPid = connectionRecord->GetCallerPid();
304 std::lock_guard<std::recursive_mutex> guard(stateLock_);
305 auto it = connectionStates_.find(callerPid);
306 if (it == connectionStates_.end()) {
307 targetItem = ConnectionStateItem::CreateConnectionStateItem(connectionRecord);
308 if (targetItem) {
309 connectionStates_[callerPid] = targetItem;
310 }
311 } else {
312 targetItem = it->second;
313 }
314
315 if (!targetItem) {
316 HILOG_ERROR("failed to find target connection state item.");
317 return false;
318 }
319
320 return targetItem->AddConnection(connectionRecord, data);
321 }
322
RemoveConnectionInner(const std::shared_ptr<ConnectionRecord> & connectionRecord,AbilityRuntime::ConnectionData & data)323 bool ConnectionStateManager::RemoveConnectionInner(const std::shared_ptr<ConnectionRecord> &connectionRecord,
324 AbilityRuntime::ConnectionData &data)
325 {
326 auto callerPid = connectionRecord->GetCallerPid();
327 std::lock_guard<std::recursive_mutex> guard(stateLock_);
328 auto it = connectionStates_.find(callerPid);
329 if (it == connectionStates_.end()) {
330 HILOG_WARN("can not find target item, connection caller pid:%{public}d.", callerPid);
331 return false;
332 }
333
334 auto targetItem = it->second;
335 if (!targetItem) {
336 HILOG_ERROR("failed to find target connection state item.");
337 return false;
338 }
339
340 bool result = targetItem->RemoveConnection(connectionRecord, data);
341 if (result && targetItem->IsEmpty()) {
342 connectionStates_.erase(it);
343 }
344 return result;
345 }
346
HandleCallerDied(int32_t callerPid)347 void ConnectionStateManager::HandleCallerDied(int32_t callerPid)
348 {
349 auto connectionStateItem = RemoveDiedCaller(callerPid);
350 if (!connectionStateItem) {
351 HILOG_WARN("no connectionStateItem, may already handled.");
352 return;
353 }
354
355 std::vector<AbilityRuntime::ConnectionData> allConnectionData;
356 connectionStateItem->GenerateAllConnectionData(allConnectionData);
357 if (allConnectionData.empty()) {
358 HILOG_WARN("allConnectionData is empty.");
359 return;
360 }
361
362 std::shared_ptr<ConnectionObserverController> controller = observerController_;
363 if (!controller) {
364 return;
365 }
366
367 for (auto& connectionData : allConnectionData) {
368 controller->NotifyExtensionDisconnected(connectionData);
369 }
370 }
371
RemoveDiedCaller(int32_t callerPid)372 std::shared_ptr<ConnectionStateItem> ConnectionStateManager::RemoveDiedCaller(int32_t callerPid)
373 {
374 std::lock_guard<std::recursive_mutex> guard(stateLock_);
375 auto it = connectionStates_.find(callerPid);
376 if (it == connectionStates_.end()) {
377 HILOG_WARN("can not find target item, connection caller pid:%{public}d, may already handled.", callerPid);
378 return nullptr;
379 }
380 auto stateItem = it->second;
381 (void)connectionStates_.erase(it);
382
383 return stateItem;
384 }
385
AddDataAbilityConnectionInner(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & record,ConnectionData & data)386 bool ConnectionStateManager::AddDataAbilityConnectionInner(const DataAbilityCaller &caller,
387 const std::shared_ptr<DataAbilityRecord> &record, ConnectionData &data)
388 {
389 std::shared_ptr<ConnectionStateItem> targetItem = nullptr;
390 std::lock_guard<std::recursive_mutex> guard(stateLock_);
391 auto it = connectionStates_.find(caller.callerPid);
392 if (it == connectionStates_.end()) {
393 targetItem = ConnectionStateItem::CreateConnectionStateItem(caller);
394 if (targetItem) {
395 connectionStates_[caller.callerPid] = targetItem;
396 }
397 } else {
398 targetItem = it->second;
399 }
400
401 if (!targetItem) {
402 HILOG_ERROR("failed to find target connection state item.");
403 return false;
404 }
405
406 return targetItem->AddDataAbilityConnection(caller, record, data);
407 }
408
RemoveDataAbilityConnectionInner(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & record,AbilityRuntime::ConnectionData & data)409 bool ConnectionStateManager::RemoveDataAbilityConnectionInner(const DataAbilityCaller &caller,
410 const std::shared_ptr<DataAbilityRecord> &record, AbilityRuntime::ConnectionData &data)
411 {
412 std::lock_guard<std::recursive_mutex> guard(stateLock_);
413 auto it = connectionStates_.find(caller.callerPid);
414 if (it == connectionStates_.end()) {
415 HILOG_WARN("can not find target item, connection caller pid:%{public}d.", caller.callerPid);
416 return false;
417 }
418
419 auto targetItem = it->second;
420 if (!targetItem) {
421 HILOG_ERROR("failed to find target data ability state item.");
422 return false;
423 }
424
425 bool result = targetItem->RemoveDataAbilityConnection(caller, record, data);
426 if (result && targetItem->IsEmpty()) {
427 connectionStates_.erase(it);
428 }
429 return result;
430 }
431
HandleDataAbilityDiedInner(const sptr<IRemoteObject> & abilityToken,std::vector<AbilityRuntime::ConnectionData> & allData)432 void ConnectionStateManager::HandleDataAbilityDiedInner(const sptr<IRemoteObject> &abilityToken,
433 std::vector<AbilityRuntime::ConnectionData> &allData)
434 {
435 std::lock_guard<std::recursive_mutex> guard(stateLock_);
436 for (auto it = connectionStates_.begin(); it != connectionStates_.end();) {
437 auto item = it->second;
438 if (!item) {
439 connectionStates_.erase(it++);
440 continue;
441 }
442
443 AbilityRuntime::ConnectionData data;
444 if (item->HandleDataAbilityDied(abilityToken, data)) {
445 allData.emplace_back(data);
446 }
447
448 if (item->IsEmpty()) {
449 connectionStates_.erase(it++);
450 } else {
451 it++;
452 }
453 }
454 }
455
HandleDlpAbilityInner(const std::shared_ptr<AbilityRecord> & dlpAbility,bool isAdd,AbilityRuntime::DlpStateData & dlpData)456 bool ConnectionStateManager::HandleDlpAbilityInner(const std::shared_ptr<AbilityRecord> &dlpAbility,
457 bool isAdd, AbilityRuntime::DlpStateData &dlpData)
458 {
459 if (!dlpAbility) {
460 HILOG_DEBUG("invalid dlp ability.");
461 return false;
462 }
463
464 if (dlpAbility->GetAppIndex() == 0) {
465 HILOG_DEBUG("this is not dlp ability, do not report connection stat.");
466 return false;
467 }
468
469 std::lock_guard<std::recursive_mutex> guard(dlpLock_);
470 auto it = dlpItems_.find(dlpAbility->GetOwnerMissionUserId());
471 if (it == dlpItems_.end()) {
472 HILOG_WARN("no dlp manager, invalid state.");
473 return false;
474 }
475
476 auto dlpItem = it->second;
477 if (!dlpItem) {
478 HILOG_WARN("invalid dlpItem.");
479 return false;
480 }
481
482 if (isAdd) {
483 return dlpItem->AddDlpConnectionState(dlpAbility, dlpData);
484 }
485
486 return dlpItem->RemoveDlpConnectionState(dlpAbility, dlpData);
487 }
488
InitAppStateObserver()489 void ConnectionStateManager::InitAppStateObserver()
490 {
491 if (appStateObserver_) {
492 return;
493 }
494
495 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppMgr();
496 if (!appManager) {
497 HILOG_WARN("%{public}s app manager nullptr!", __func__);
498 return;
499 }
500
501 appStateObserver_ = new (std::nothrow)InnerAppStateObserver([](int32_t pid) {
502 DelayedSingleton<ConnectionStateManager>::GetInstance()->HandleAppDied(pid);
503 });
504 int32_t err = appManager->RegisterApplicationStateObserver(appStateObserver_);
505 if (err != 0) {
506 HILOG_ERROR("%{public}s register to appmanager failed. err:%{public}d", __func__, err);
507 appStateObserver_ = nullptr;
508 return;
509 }
510 }
511 } // namespace AAFwk
512 } // namespace OHOS
513