1 /*
2  * Copyright (c) 2023 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 "security_collector_subscriber_manager.h"
17 #include "security_collector_define.h"
18 #include "security_collector_log.h"
19 #include "data_collection.h"
20 
21 namespace OHOS::Security::SecurityCollector {
22 namespace {
23     constexpr int32_t MAX_APP_SUBSCRIBE_COUNT = 100;
24 }
SecurityCollectorSubscriberManager()25 SecurityCollectorSubscriberManager::SecurityCollectorSubscriberManager()
26 {
27 }
28 
GetExtraInfo()29 std::string SecurityCollectorSubscriberManager::CollectorListenner::GetExtraInfo()
30 {
31     if (subscriber_) {
32         return subscriber_->GetSecurityCollectorSubscribeInfo().GetEvent().extra;
33     }
34     return {};
35 }
36 
OnNotify(const Event & event)37 void SecurityCollectorSubscriberManager::CollectorListenner::OnNotify(const Event &event)
38 {
39     SecurityCollectorSubscriberManager::GetInstance().NotifySubscriber(event);
40 }
41 
NotifySubscriber(const Event & event)42 void SecurityCollectorSubscriberManager::NotifySubscriber(const Event &event)
43 {
44     std::lock_guard<std::mutex> lock(collectorMutex_);
45     LOGE("publish event: eventid:%{public}" PRId64 ", version:%{public}s, extra:%{public}s",
46         event.eventId, event.version.c_str(), event.extra.c_str());
47     const auto it = eventToSubscribers_.find(event.eventId);
48     if (it == eventToSubscribers_.end()) {
49         return;
50     }
51     for (const auto &subscriber : it->second) {
52         if (subscriber != nullptr) {
53             subscriber->OnChange(event);
54         }
55     }
56 }
57 
GetAppSubscribeCount(const std::string & appName)58 int32_t SecurityCollectorSubscriberManager::GetAppSubscribeCount(const std::string &appName)
59 {
60     int32_t count = 0;
61     for (const auto &element : eventToSubscribers_) {
62         const auto &subscribers = element.second;
63         count = std::count_if(subscribers.begin(), subscribers.end(), [appName] (const auto &subscriber) {
64             return subscriber->GetAppName() == appName;
65         });
66     }
67     LOGI("subcirbipt count, appName=%{public}s, count=%{public}d", appName.c_str(), count);
68     return count;
69 }
70 
GetAppSubscribeCount(const std::string & appName,int64_t eventId)71 int32_t SecurityCollectorSubscriberManager::GetAppSubscribeCount(const std::string &appName, int64_t eventId)
72 {
73     const auto &subscribers = eventToSubscribers_[eventId];
74     if (std::any_of(subscribers.begin(), subscribers.end(), [appName] (const auto &subscriber) {
75             return subscriber->GetAppName() == appName;
76         })) {
77         LOGI("subcirbipt count 1, appName=%{public}s, eventId:%{public}" PRId64 "", appName.c_str(), eventId);
78         return 1;
79     }
80     LOGI("subcirbipt count 0, appName=%{public}s, eventId:%{public}" PRId64 "", appName.c_str(), eventId);
81     return 0;
82 }
83 
FindEventIds(const sptr<IRemoteObject> & remote)84 std::set<int64_t> SecurityCollectorSubscriberManager::FindEventIds(const sptr<IRemoteObject> &remote)
85 {
86     std::set<int64_t> eventIds;
87     for (const auto &element : eventToSubscribers_) {
88         const auto &subscribers = element.second;
89         auto it = std::find_if(subscribers.begin(), subscribers.end(),
90             [remote] (const auto &subscriber) { return subscriber->GetRemote() == remote; });
91         if (it != subscribers.end()) {
92             LOGI("Find Event By Callback appName=%{public}s, eventId:%{public}" PRId64 "",
93                  (*it)->GetAppName().c_str(), element.first);
94             eventIds.emplace(element.first);
95         }
96     }
97     return eventIds;
98 }
99 
FindSecurityCollectorSubscribers(const sptr<IRemoteObject> & remote)100 auto SecurityCollectorSubscriberManager::FindSecurityCollectorSubscribers(const sptr<IRemoteObject> &remote)
101 {
102     std::set<std::shared_ptr<SecurityCollectorSubscriber>> subscribers;
103     for (const auto &element : eventToSubscribers_) {
104         auto it = std::find_if(element.second.begin(), element.second.end(),
105             [remote] (const auto &d) { return d->GetRemote() == remote; });
106         if (it != element.second.end()) {
107             LOGI("Find Event Listenner appName=%{public}s, eventId:%{public}" PRId64 "",
108                 (*it)->GetAppName().c_str(), element.first);
109             subscribers.emplace(*it);
110         }
111     }
112     return subscribers;
113 }
SubscribeCollector(const std::shared_ptr<SecurityCollectorSubscriber> & subscriber)114 bool SecurityCollectorSubscriberManager::SubscribeCollector(
115     const std::shared_ptr<SecurityCollectorSubscriber> &subscriber)
116 {
117     std::lock_guard<std::mutex> lock(collectorMutex_);
118     if (subscriber == nullptr) {
119         LOGE("subscriber is null");
120         return false;
121     }
122     std::string appName = subscriber->GetAppName();
123     int64_t eventId = subscriber->GetSecurityCollectorSubscribeInfo().GetEvent().eventId;
124     LOGI("appName:%{public}s, eventId:%{public}" PRId64 "", appName.c_str(), eventId);
125     if (GetAppSubscribeCount(appName) >= MAX_APP_SUBSCRIBE_COUNT) {
126         LOGE("Max count for app name:%{public}s", appName.c_str());
127         return false;
128     }
129     if (GetAppSubscribeCount(appName, eventId) > 0) {
130         LOGE("Already subscribed eventId:%{public}" PRId64 "", eventId);
131         return false;
132     }
133     if (eventToListenner_.count(eventId) == 0) {
134         auto collectorListenner = std::make_shared<SecurityCollectorSubscriberManager::CollectorListenner>(subscriber);
135         LOGI("Scheduling start collector, eventId:%{public}" PRId64 "", eventId);
136         if (!DataCollection::GetInstance().StartCollectors(std::vector<int64_t>{eventId}, collectorListenner)) {
137             LOGE("failed to start collectors");
138             return false;
139         }
140         eventToListenner_.emplace(eventId, collectorListenner);
141     } else {
142         LOGI("Scheduling do not start collecctor, eventId:%{public}" PRId64 "", eventId);
143     }
144     eventToSubscribers_[eventId].emplace(subscriber);
145     LOGI("eventId:%{public}" PRId64 ", callbackCount:%{public}u",
146         eventId, static_cast<uint32_t>(eventToSubscribers_[eventId].size()));
147     int64_t duration = subscriber->GetSecurityCollectorSubscribeInfo().GetDuration();
148     if (duration > 0) {
149         auto remote = subscriber->GetRemote();
150         auto timer = std::make_shared<CleanupTimer>();
151         timers_.emplace(remote, timer);
152         timer->Start(remote, duration);
153     }
154     return true;
155 }
156 
UnsubscribeCollector(const sptr<IRemoteObject> & remote)157 bool SecurityCollectorSubscriberManager::UnsubscribeCollector(const sptr<IRemoteObject> &remote)
158 {
159     std::lock_guard<std::mutex> lock(collectorMutex_);
160     std::set<int64_t> eventIds = FindEventIds(remote);
161     for (int64_t eventId : eventIds) {
162         LOGI("Remove collecctor, eventId:%{public}" PRId64 "", eventId);
163         if (eventId == -1) {
164             LOGE("eventId is not found");
165             return false;
166         }
167         auto subscribers = FindSecurityCollectorSubscribers(remote);
168         if (subscribers.size() == 0) {
169             LOGE("subscriber is null");
170             return false;
171         }
172         for (auto subscriber: subscribers) {
173             eventToSubscribers_[eventId].erase(subscriber);
174             if (eventToSubscribers_[eventId].size() == 0) {
175                 LOGI("Scheduling stop collector, eventId:%{public}" PRId64 "", eventId);
176                 (void) DataCollection::GetInstance().StopCollectors(std::vector<int64_t>{eventId});
177                 eventToSubscribers_.erase(eventId);
178                 eventToListenner_.erase(eventId);
179             }
180         }
181     }
182 
183     LOGI("erase timer befoe remoteObject");
184     timers_.erase(remote);
185     LOGI("erase timer after remoteObject");
186     return true;
187 }
188 }