1 /*
2 * Copyright (c) 2022-2024 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 <algorithm>
17 #include "connection_state_item.h"
18
19 #include "hilog_tag_wrapper.h"
20
21 namespace OHOS {
22 namespace AAFwk {
23 /**
24 * @class ConnectedExtension
25 * ConnectedExtension,This class is used to record a connected extension.
26 */
27 class ConnectedExtension : public std::enable_shared_from_this<ConnectedExtension> {
28 public:
CreateConnectedExtension(std::shared_ptr<ConnectionRecord> record)29 static std::shared_ptr<ConnectedExtension> CreateConnectedExtension(std::shared_ptr<ConnectionRecord> record)
30 {
31 if (!record) {
32 return nullptr;
33 }
34
35 auto targetExtension = record->GetAbilityRecord();
36 if (!targetExtension) {
37 return nullptr;
38 }
39
40 return std::make_shared<ConnectedExtension>(targetExtension);
41 }
42
ConnectedExtension()43 ConnectedExtension()
44 {
45 extensionType_ = AppExecFwk::ExtensionAbilityType::UNSPECIFIED;
46 }
47
ConnectedExtension(std::shared_ptr<AbilityRecord> target)48 explicit ConnectedExtension(std::shared_ptr<AbilityRecord> target)
49 {
50 if (!target) {
51 return;
52 }
53 extensionPid_ = target->GetPid();
54 extensionUid_ = target->GetUid();
55 extensionBundleName_ = target->GetAbilityInfo().bundleName;
56 extensionModuleName_ = target->GetAbilityInfo().moduleName;
57 extensionName_ = target->GetAbilityInfo().name;
58 extensionType_ = target->GetAbilityInfo().extensionAbilityType;
59 if (target->GetAbilityInfo().type == AppExecFwk::AbilityType::SERVICE) {
60 extensionType_ = AppExecFwk::ExtensionAbilityType::SERVICE;
61 } else if (target->GetAbilityInfo().type == AppExecFwk::AbilityType::DATA) {
62 extensionType_ = AppExecFwk::ExtensionAbilityType::DATASHARE;
63 }
64 }
65
66 virtual ~ConnectedExtension() = default;
67
AddConnection(sptr<IRemoteObject> connection,ConnectionEvent & event)68 bool AddConnection(sptr<IRemoteObject> connection, ConnectionEvent& event)
69 {
70 if (!connection) {
71 return false;
72 }
73
74 std::lock_guard guard(connectionsMutex_);
75 if (connections_.empty()) {
76 event.connectedEvent = true;
77 connections_.emplace(connection, false);
78 return true;
79 }
80
81 bool needNotify = std::find_if(connections_.begin(), connections_.end(),
82 [](const std::pair<sptr<IRemoteObject>, bool>& pair)->bool {return pair.second == false;})
83 == connections_.end();
84
85 auto it = connections_.find(connection);
86 if (it == connections_.end()) {
87 connections_.emplace(connection, false);
88 } else {
89 (*it).second = false;
90 }
91
92 if (needNotify) {
93 event.resumedEvent = true;
94 return true;
95 }
96 return false;
97 }
98
RemoveConnection(sptr<IRemoteObject> connection,ConnectionEvent & event)99 bool RemoveConnection(sptr<IRemoteObject> connection, ConnectionEvent& event)
100 {
101 if (!connection) {
102 return false;
103 }
104 std::lock_guard guard(connectionsMutex_);
105 auto it = connections_.find(connection);
106 if (it == connections_.end()) {
107 return false;
108 }
109
110 bool isUnAvaliable = (*it).second;
111 connections_.erase(connection);
112 if (connections_.empty()) {
113 event.disconnectedEvent = true;
114 return true;
115 }
116
117 if (isUnAvaliable) {
118 return false;
119 }
120 it = std::find_if(connections_.begin(), connections_.end(),
121 [](const std::pair<sptr<IRemoteObject>, bool>& pair)->bool {return pair.second == false;});
122 if (it == connections_.end()) {
123 event.suspendedEvent = true;
124 return true;
125 }
126 return false;
127 }
128
SuspendConnection(sptr<IRemoteObject> connection)129 bool SuspendConnection(sptr<IRemoteObject> connection)
130 {
131 if (!connection) {
132 return false;
133 }
134 std::lock_guard guard(connectionsMutex_);
135 auto it = connections_.find(connection);
136 if (it == connections_.end()) {
137 return false;
138 }
139
140 if ((*it).second) {
141 return false;
142 }
143 (*it).second = true;
144 it = std::find_if(connections_.begin(), connections_.end(),
145 [](const std::pair<sptr<IRemoteObject>, bool>& pair)->bool {return pair.second == false;});
146
147 return it == connections_.end();
148 }
149
ResumeConnection(sptr<IRemoteObject> connection)150 bool ResumeConnection(sptr<IRemoteObject> connection)
151 {
152 if (!connection) {
153 return false;
154 }
155 std::lock_guard guard(connectionsMutex_);
156 auto it = connections_.find(connection);
157 if (it == connections_.end()) {
158 return false;
159 }
160
161 bool needNotify = std::find_if(connections_.begin(), connections_.end(),
162 [](const std::pair<sptr<IRemoteObject>, bool>& pair)->bool {return pair.second == false;})
163 == connections_.end();
164
165 (*it).second = false;
166 return needNotify;
167 }
168
GenerateExtensionInfo(AbilityRuntime::ConnectionData & data)169 void GenerateExtensionInfo(AbilityRuntime::ConnectionData &data)
170 {
171 {
172 std::lock_guard guard(connectionsMutex_);
173 auto it = std::find_if(connections_.begin(), connections_.end(),
174 [](const std::pair<sptr<IRemoteObject>, bool
175 >& pair) {return pair.second == false;});
176 if (it == connections_.end()) {
177 data.isSuspended = true;
178 }
179 }
180 data.extensionPid = extensionPid_;
181 data.extensionUid = extensionUid_;
182 data.extensionBundleName = extensionBundleName_;
183 data.extensionModuleName = extensionModuleName_;
184 data.extensionName = extensionName_;
185 data.extensionType = extensionType_;
186 }
187
188 private:
189 int32_t extensionPid_ = 0;
190 int32_t extensionUid_ = 0;
191 std::string extensionBundleName_;
192 std::string extensionModuleName_;
193 std::string extensionName_;
194 AppExecFwk::ExtensionAbilityType extensionType_;
195
196 std::mutex connectionsMutex_;
197 std::map<sptr<IRemoteObject>, bool> connections_; // remote object of IAbilityConnection
198 };
199
200 /**
201 * @class ConnectedDataAbility
202 * ConnectedDataAbility,This class is used to record a connected data ability.
203 */
204 class ConnectedDataAbility : public std::enable_shared_from_this<ConnectedDataAbility> {
205 public:
CreateConnectedDataAbility(const std::shared_ptr<DataAbilityRecord> & record)206 static std::shared_ptr<ConnectedDataAbility> CreateConnectedDataAbility(
207 const std::shared_ptr<DataAbilityRecord> &record)
208 {
209 if (!record) {
210 return nullptr;
211 }
212
213 auto targetAbility = record->GetAbilityRecord();
214 if (!targetAbility) {
215 return nullptr;
216 }
217
218 return std::make_shared<ConnectedDataAbility>(targetAbility);
219 }
220
ConnectedDataAbility()221 ConnectedDataAbility() {}
222
ConnectedDataAbility(const std::shared_ptr<AbilityRecord> & target)223 explicit ConnectedDataAbility(const std::shared_ptr<AbilityRecord> &target)
224 {
225 if (!target) {
226 return;
227 }
228
229 dataAbilityPid_ = target->GetPid();
230 dataAbilityUid_ = target->GetUid();
231 bundleName_ = target->GetAbilityInfo().bundleName;
232 moduleName_ = target->GetAbilityInfo().moduleName;
233 abilityName_ = target->GetAbilityInfo().name;
234 }
235
236 virtual ~ConnectedDataAbility() = default;
237
AddCaller(const DataAbilityCaller & caller)238 bool AddCaller(const DataAbilityCaller &caller)
239 {
240 if (!caller.isNotHap && !caller.callerToken) {
241 return false;
242 }
243
244 bool needNotify = callers_.empty();
245 auto it = find_if(callers_.begin(), callers_.end(), [&caller](const std::shared_ptr<CallerInfo> &info) {
246 if (caller.isNotHap) {
247 return info && info->IsNotHap() && info->GetCallerPid() == caller.callerPid;
248 } else {
249 return info && info->GetCallerToken() == caller.callerToken;
250 }
251 });
252 if (it == callers_.end()) {
253 callers_.emplace_back(std::make_shared<CallerInfo>(caller.isNotHap, caller.callerPid, caller.callerToken));
254 }
255
256 return needNotify;
257 }
258
RemoveCaller(const DataAbilityCaller & caller)259 bool RemoveCaller(const DataAbilityCaller &caller)
260 {
261 if (!caller.isNotHap && !caller.callerToken) {
262 return false;
263 }
264
265 auto it = find_if(callers_.begin(), callers_.end(), [&caller](const std::shared_ptr<CallerInfo> &info) {
266 if (caller.isNotHap) {
267 return info && info->IsNotHap() && info->GetCallerPid() == caller.callerPid;
268 } else {
269 return info && info->GetCallerToken() == caller.callerToken;
270 }
271 });
272 if (it != callers_.end()) {
273 callers_.erase(it);
274 }
275
276 return callers_.empty();
277 }
278
GenerateExtensionInfo(AbilityRuntime::ConnectionData & data)279 void GenerateExtensionInfo(AbilityRuntime::ConnectionData &data)
280 {
281 data.extensionPid = dataAbilityPid_;
282 data.extensionUid = dataAbilityUid_;
283 data.extensionBundleName = bundleName_;
284 data.extensionModuleName = moduleName_;
285 data.extensionName = abilityName_;
286 data.extensionType = AppExecFwk::ExtensionAbilityType::DATASHARE;
287 }
288
289 private:
290 class CallerInfo : public std::enable_shared_from_this<CallerInfo> {
291 public:
CallerInfo(bool isNotHap,int32_t callerPid,const sptr<IRemoteObject> & callerToken)292 CallerInfo(bool isNotHap, int32_t callerPid, const sptr<IRemoteObject> &callerToken)
293 : isNotHap_(isNotHap), callerPid_(callerPid), callerToken_(callerToken) {}
294
IsNotHap() const295 bool IsNotHap() const
296 {
297 return isNotHap_;
298 }
299
GetCallerPid() const300 int32_t GetCallerPid() const
301 {
302 return callerPid_;
303 }
304
GetCallerToken() const305 sptr<IRemoteObject> GetCallerToken() const
306 {
307 return callerToken_;
308 }
309
310 private:
311 bool isNotHap_ = false;
312 int32_t callerPid_ = 0;
313 sptr<IRemoteObject> callerToken_ = nullptr;
314 };
315
316 int32_t dataAbilityPid_ = 0;
317 int32_t dataAbilityUid_ = 0;
318 std::string bundleName_;
319 std::string moduleName_;
320 std::string abilityName_;
321 std::list<std::shared_ptr<CallerInfo>> callers_; // caller infos of this data ability.
322 };
323
ConnectionStateItem(int32_t callerUid,int32_t callerPid,const std::string & callerName)324 ConnectionStateItem::ConnectionStateItem(int32_t callerUid, int32_t callerPid, const std::string &callerName)
325 : callerUid_(callerUid), callerPid_(callerPid), callerName_(callerName)
326 {
327 }
328
~ConnectionStateItem()329 ConnectionStateItem::~ConnectionStateItem()
330 {}
331
CreateConnectionStateItem(const std::shared_ptr<ConnectionRecord> & record)332 std::shared_ptr<ConnectionStateItem> ConnectionStateItem::CreateConnectionStateItem(
333 const std::shared_ptr<ConnectionRecord> &record)
334 {
335 if (!record) {
336 return nullptr;
337 }
338
339 return std::make_shared<ConnectionStateItem>(record->GetCallerUid(),
340 record->GetCallerPid(), record->GetCallerName());
341 }
342
CreateConnectionStateItem(const DataAbilityCaller & dataCaller)343 std::shared_ptr<ConnectionStateItem> ConnectionStateItem::CreateConnectionStateItem(
344 const DataAbilityCaller &dataCaller)
345 {
346 return std::make_shared<ConnectionStateItem>(dataCaller.callerUid,
347 dataCaller.callerPid, dataCaller.callerName);
348 }
349
AddConnection(std::shared_ptr<ConnectionRecord> record,AbilityRuntime::ConnectionData & data,ConnectionEvent & event)350 bool ConnectionStateItem::AddConnection(std::shared_ptr<ConnectionRecord> record,
351 AbilityRuntime::ConnectionData &data, ConnectionEvent &event)
352 {
353 if (!record) {
354 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connection record");
355 return false;
356 }
357
358 auto token = record->GetTargetToken();
359 if (!token) {
360 TAG_LOGE(AAFwkTag::CONNECTION, "invalid token");
361 return false;
362 }
363
364 sptr<IRemoteObject> connectionObj = record->GetConnection();
365 if (!connectionObj) {
366 TAG_LOGE(AAFwkTag::CONNECTION, "no connection callback");
367 return false;
368 }
369
370 std::shared_ptr<ConnectedExtension> connectedExtension = nullptr;
371 auto it = connectionMap_.find(token);
372 if (it == connectionMap_.end()) {
373 connectedExtension = ConnectedExtension::CreateConnectedExtension(record);
374 if (connectedExtension) {
375 connectionMap_[token] = connectedExtension;
376 }
377 } else {
378 connectedExtension = it->second;
379 }
380
381 if (!connectedExtension) {
382 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connectedExtension");
383 return false;
384 }
385
386 bool needNotify = connectedExtension->AddConnection(connectionObj, event);
387 if (needNotify) {
388 GenerateConnectionData(connectedExtension, data);
389 }
390
391 return needNotify;
392 }
393
RemoveConnection(std::shared_ptr<ConnectionRecord> record,AbilityRuntime::ConnectionData & data,ConnectionEvent & event)394 bool ConnectionStateItem::RemoveConnection(std::shared_ptr<ConnectionRecord> record,
395 AbilityRuntime::ConnectionData &data, ConnectionEvent &event)
396 {
397 if (!record) {
398 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connection record");
399 return false;
400 }
401
402 auto token = record->GetTargetToken();
403 if (!token) {
404 TAG_LOGE(AAFwkTag::CONNECTION, "invalid token");
405 return false;
406 }
407
408 sptr<IRemoteObject> connectionObj = record->GetConnection();
409 if (!connectionObj) {
410 TAG_LOGE(AAFwkTag::CONNECTION, "no connection callback");
411 return false;
412 }
413
414 auto it = connectionMap_.find(token);
415 if (it == connectionMap_.end()) {
416 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
417 return false;
418 }
419
420 auto connectedExtension = it->second;
421 if (!connectedExtension) {
422 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
423 return false;
424 }
425
426 bool needNotify = connectedExtension->RemoveConnection(connectionObj, event);
427 if (needNotify) {
428 connectionMap_.erase(it);
429 GenerateConnectionData(connectedExtension, data);
430 }
431
432 return needNotify;
433 }
434
SuspendConnection(std::shared_ptr<ConnectionRecord> record,AbilityRuntime::ConnectionData & data)435 bool ConnectionStateItem::SuspendConnection(std::shared_ptr<ConnectionRecord> record,
436 AbilityRuntime::ConnectionData &data)
437 {
438 if (!record) {
439 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connection record");
440 return false;
441 }
442
443 auto token = record->GetTargetToken();
444 if (!token) {
445 TAG_LOGE(AAFwkTag::CONNECTION, "invalid token");
446 return false;
447 }
448
449 sptr<IRemoteObject> connectionObj = record->GetConnection();
450 if (!connectionObj) {
451 TAG_LOGE(AAFwkTag::CONNECTION, "no connection callback");
452 return false;
453 }
454
455 auto it = connectionMap_.find(token);
456 if (it == connectionMap_.end()) {
457 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
458 return false;
459 }
460
461 auto connectedExtension = it->second;
462 if (!connectedExtension) {
463 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
464 return false;
465 }
466
467 bool needNotify = connectedExtension->SuspendConnection(connectionObj);
468 if (needNotify) {
469 GenerateConnectionData(connectedExtension, data);
470 }
471
472 return needNotify;
473 }
474
ResumeConnection(std::shared_ptr<ConnectionRecord> record,AbilityRuntime::ConnectionData & data)475 bool ConnectionStateItem::ResumeConnection(std::shared_ptr<ConnectionRecord> record,
476 AbilityRuntime::ConnectionData &data)
477 {
478 if (!record) {
479 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connection record");
480 return false;
481 }
482
483 auto token = record->GetTargetToken();
484 if (!token) {
485 TAG_LOGE(AAFwkTag::CONNECTION, "invalid token");
486 return false;
487 }
488
489 sptr<IRemoteObject> connectionObj = record->GetConnection();
490 if (!connectionObj) {
491 TAG_LOGE(AAFwkTag::CONNECTION, "no connection callback");
492 return false;
493 }
494
495 auto it = connectionMap_.find(token);
496 if (it == connectionMap_.end()) {
497 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
498 return false;
499 }
500
501 auto connectedExtension = it->second;
502 if (!connectedExtension) {
503 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedExtension");
504 return false;
505 }
506
507 bool needNotify = connectedExtension->ResumeConnection(connectionObj);
508 if (needNotify) {
509 GenerateConnectionData(connectedExtension, data);
510 }
511
512 return needNotify;
513 }
514
AddDataAbilityConnection(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & dataAbility,AbilityRuntime::ConnectionData & data)515 bool ConnectionStateItem::AddDataAbilityConnection(const DataAbilityCaller &caller,
516 const std::shared_ptr<DataAbilityRecord> &dataAbility, AbilityRuntime::ConnectionData &data)
517 {
518 if (!dataAbility) {
519 TAG_LOGE(AAFwkTag::CONNECTION, "invalid dataAbility");
520 return false;
521 }
522
523 auto token = dataAbility->GetToken();
524 if (!token) {
525 TAG_LOGE(AAFwkTag::CONNECTION, "invalid dataAbility token");
526 return false;
527 }
528
529 std::shared_ptr<ConnectedDataAbility> connectedAbility = nullptr;
530 auto it = dataAbilityMap_.find(token);
531 if (it == dataAbilityMap_.end()) {
532 connectedAbility = ConnectedDataAbility::CreateConnectedDataAbility(dataAbility);
533 if (connectedAbility) {
534 dataAbilityMap_[token] = connectedAbility;
535 }
536 } else {
537 connectedAbility = it->second;
538 }
539
540 if (!connectedAbility) {
541 TAG_LOGE(AAFwkTag::CONNECTION, "invalid connectedAbility");
542 return false;
543 }
544
545 bool needNotify = connectedAbility->AddCaller(caller);
546 if (needNotify) {
547 GenerateConnectionData(connectedAbility, data);
548 }
549
550 return needNotify;
551 }
552
RemoveDataAbilityConnection(const DataAbilityCaller & caller,const std::shared_ptr<DataAbilityRecord> & dataAbility,AbilityRuntime::ConnectionData & data)553 bool ConnectionStateItem::RemoveDataAbilityConnection(const DataAbilityCaller &caller,
554 const std::shared_ptr<DataAbilityRecord> &dataAbility, AbilityRuntime::ConnectionData &data)
555 {
556 if (!dataAbility) {
557 TAG_LOGE(AAFwkTag::CONNECTION, "invalid data ability record");
558 return false;
559 }
560
561 auto token = dataAbility->GetToken();
562 if (!token) {
563 TAG_LOGE(AAFwkTag::CONNECTION, "invalid data ability token");
564 return false;
565 }
566
567 auto it = dataAbilityMap_.find(token);
568 if (it == dataAbilityMap_.end()) {
569 TAG_LOGE(AAFwkTag::CONNECTION, "no such connected data ability");
570 return false;
571 }
572
573 auto connectedDataAbility = it->second;
574 if (!connectedDataAbility) {
575 TAG_LOGE(AAFwkTag::CONNECTION, "no such connectedDataAbility");
576 return false;
577 }
578
579 bool needNotify = connectedDataAbility->RemoveCaller(caller);
580 if (needNotify) {
581 dataAbilityMap_.erase(it);
582 GenerateConnectionData(connectedDataAbility, data);
583 }
584
585 return needNotify;
586 }
587
HandleDataAbilityDied(const sptr<IRemoteObject> & token,AbilityRuntime::ConnectionData & data)588 bool ConnectionStateItem::HandleDataAbilityDied(const sptr<IRemoteObject> &token,
589 AbilityRuntime::ConnectionData &data)
590 {
591 if (!token) {
592 return false;
593 }
594
595 auto it = dataAbilityMap_.find(token);
596 if (it == dataAbilityMap_.end()) {
597 TAG_LOGE(AAFwkTag::CONNECTION, "no such data ability");
598 return false;
599 }
600
601 auto connectedDataAbility = it->second;
602 if (!connectedDataAbility) {
603 TAG_LOGE(AAFwkTag::CONNECTION, "no connectedDataAbility");
604 return false;
605 }
606
607 dataAbilityMap_.erase(it);
608 GenerateConnectionData(connectedDataAbility, data);
609 return true;
610 }
611
IsEmpty() const612 bool ConnectionStateItem::IsEmpty() const
613 {
614 return connectionMap_.empty() && dataAbilityMap_.empty();
615 }
616
GenerateAllConnectionData(std::vector<AbilityRuntime::ConnectionData> & datas)617 void ConnectionStateItem::GenerateAllConnectionData(std::vector<AbilityRuntime::ConnectionData> &datas)
618 {
619 AbilityRuntime::ConnectionData data;
620 for (auto it = connectionMap_.begin(); it != connectionMap_.end(); ++it) {
621 GenerateConnectionData(it->second, data);
622 datas.emplace_back(data);
623 }
624
625 for (auto it = dataAbilityMap_.begin(); it != dataAbilityMap_.end(); ++it) {
626 GenerateConnectionData(it->second, data);
627 datas.emplace_back(data);
628 }
629 }
630
GenerateConnectionData(const std::shared_ptr<ConnectedExtension> & connectedExtension,AbilityRuntime::ConnectionData & data)631 void ConnectionStateItem::GenerateConnectionData(
632 const std::shared_ptr<ConnectedExtension> &connectedExtension, AbilityRuntime::ConnectionData &data)
633 {
634 if (connectedExtension) {
635 connectedExtension->GenerateExtensionInfo(data);
636 }
637 data.callerUid = callerUid_;
638 data.callerPid = callerPid_;
639 data.callerName = callerName_;
640 }
641
GenerateConnectionData(const std::shared_ptr<ConnectedDataAbility> & connectedDataAbility,AbilityRuntime::ConnectionData & data)642 void ConnectionStateItem::GenerateConnectionData(const std::shared_ptr<ConnectedDataAbility> &connectedDataAbility,
643 AbilityRuntime::ConnectionData &data)
644 {
645 if (connectedDataAbility) {
646 connectedDataAbility->GenerateExtensionInfo(data);
647 }
648 data.callerUid = callerUid_;
649 data.callerPid = callerPid_;
650 data.callerName = callerName_;
651 }
652 } // namespace AAFwk
653 } // namespace OHOS
654