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 "data_publisher.h"
17 
18 #include <cerrno>
19 #include <cstdlib>
20 #include <map>
21 #include <set>
22 #include <string>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <utility>
27 #include <vector>
28 
29 #include "data_publisher_sys_event_callback.h"
30 #include "data_share_common.h"
31 #include "data_share_dao.h"
32 #include "data_share_store.h"
33 #include "data_share_util.h"
34 #include "event_publish.h"
35 #include "file_util.h"
36 #include "hisysevent.h"
37 #include "hiview_event_common.h"
38 #include "iquery_base_callback.h"
39 #include "json/json.h"
40 #include "hiview_logger.h"
41 #include "ret_code.h"
42 #include "string_util.h"
43 #include "sys_event_query.h"
44 #include "time_util.h"
45 
46 using namespace OHOS::HiviewDFX::SubscribeStore;
47 using namespace OHOS::HiviewDFX::BaseEventSpace;
48 
49 namespace OHOS {
50 namespace HiviewDFX {
51 DEFINE_LOG_TAG("HiView-DataPublisher");
52 namespace {
GetBundleNameFromJsonStr(const std::string & jsonInfo)53 std::string GetBundleNameFromJsonStr(const std::string& jsonInfo)
54 {
55     std::string bundleName = "";
56     Json::Value root;
57     Json::Reader reader;
58     if (!reader.parse(jsonInfo, root)) {
59         HIVIEW_LOGE("failed to parse jsonInfo.");
60         return bundleName;
61     }
62     if (root[BUNDLE_NAME].isString()) {
63         bundleName = root[BUNDLE_NAME].asString();
64     }
65     return bundleName;
66 }
67 }  // namespace
68 
DataPublisher()69 DataPublisher::DataPublisher()
70 {
71     this->InitSubscriber();
72 }
73 
AddSubscriber(int32_t uid,const std::vector<std::string> & eventList)74 int32_t DataPublisher::AddSubscriber(int32_t uid, const std::vector<std::string> &eventList)
75 {
76     std::string events;
77     std::shared_ptr<DataShareDao> dataShareDao = GetDataShareDao();
78     auto ret = dataShareDao->GetEventListByUid(uid, events);
79     if (ret != DB_SUCC) {
80         HIVIEW_LOGE("query DB failed.");
81         return ret;
82     }
83     std::vector<std::string> oldEventList;
84     StringUtil::SplitStr(events, ";", oldEventList);
85     for (auto &event : oldEventList) {
86         eventRelationMap_[event].erase(uid);
87     }
88     for (auto &event : eventList) {
89         eventRelationMap_[event].insert(uid);
90     }
91     auto newEvents = StringUtil::ConvertVectorToStr(eventList, ";");
92     ret = dataShareDao->SaveSubscriberInfo(uid, newEvents);
93     if (ret != DB_SUCC) {
94         HIVIEW_LOGE("query DB failed.");
95         return ret;
96     }
97     return IPC_CALL_SUCCEED;
98 }
99 
RemoveSubscriber(int32_t uid)100 int32_t DataPublisher::RemoveSubscriber(int32_t uid)
101 {
102     std::string events;
103     std::shared_ptr<DataShareDao> dataShareDao = GetDataShareDao();
104     auto ret = dataShareDao->GetEventListByUid(uid, events);
105     if (ret != DB_SUCC) {
106         HIVIEW_LOGE("failed to get events by uid");
107         return ERR_REMOVE_SUBSCRIBE;
108     }
109     if (events.empty()) {
110         HIVIEW_LOGE("events list is empty");
111         return ERR_REMOVE_SUBSCRIBE;
112     }
113     std::vector<std::string> eventList;
114     StringUtil::SplitStr(events, ";", eventList);
115     for (auto &event : eventList) {
116         eventRelationMap_[event].erase(uid);
117     }
118     ret = dataShareDao->DeleteSubscriberInfo(uid);
119     if (ret != DB_SUCC) {
120         HIVIEW_LOGE("failed to delete subscriberInfo");
121         return ERR_REMOVE_SUBSCRIBE;
122     }
123     return IPC_CALL_SUCCEED;
124 }
125 
InitSubscriber()126 void DataPublisher::InitSubscriber()
127 {
128     std::map<int, std::string> uidToEventsMap;
129     std::shared_ptr<DataShareDao> dataShareDao = GetDataShareDao();
130     int ret = dataShareDao->GetTotalSubscriberInfo(uidToEventsMap);
131     if (ret != DB_SUCC) {
132         HIVIEW_LOGE("failed to get total subscriberInfo");
133         return;
134     }
135     for (auto it = uidToEventsMap.begin(); it != uidToEventsMap.end(); ++it) {
136         int uid = it->first;
137         std::string events = it->second;
138         std::vector<std::string> eventList;
139         StringUtil::SplitStr(events, ";", eventList);
140         for (auto &event : eventList) {
141             eventRelationMap_[event].insert(uid);
142         }
143     }
144 }
145 
OnSysEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> & event)146 void DataPublisher::OnSysEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> &event)
147 {
148     HandleAppUninstallEvent(event);
149     HandleAppStartEvent(event);
150     if (eventRelationMap_.find(event->eventName_) == eventRelationMap_.end()) {
151         return;
152     }
153     if (!CreateHiviewTempDir()) {
154         HIVIEW_LOGE("failed to create resourceFile.");
155         return;
156     }
157     int64_t timestamp = static_cast<int64_t>(TimeUtil::GetMilliseconds());
158     std::string timeStr = std::to_string(timestamp);
159     std::string srcPath = TEMP_SRC_DIR;
160     if (looper_ != nullptr) {
161         auto task = std::bind(&DataPublisher::HandleSubscribeTask, this, event, srcPath, timeStr);
162         looper_->AddTimerEvent(nullptr, nullptr, task, DELAY_TIME, false);
163     } else {
164         HIVIEW_LOGW("looper_ is null, call the subscribe function directly.");
165         HandleSubscribeTask(event, srcPath, timeStr);
166     }
167 }
168 
HandleSubscribeTask(std::shared_ptr<OHOS::HiviewDFX::SysEvent> & event,std::string srcPath,std::string timeStr)169 void DataPublisher::HandleSubscribeTask(std::shared_ptr<OHOS::HiviewDFX::SysEvent> &event,
170     std::string srcPath, std::string timeStr)
171 {
172     std::string eventJson = event->AsJsonStr();
173     if (!FileUtil::SaveStringToFile(srcPath, eventJson + ",", true)) {
174         HIVIEW_LOGE("failed to persist eventJson to file.");
175         return;
176     }
177     std::set<int> uidSet = eventRelationMap_[event->eventName_];
178     std::string desPath;
179     for (auto uid : uidSet) {
180         desPath = OHOS::HiviewDFX::DataShareUtil::GetSandBoxPathByUid(uid);
181         desPath.append("/")
182             .append(event->domain_)
183             .append("-")
184             .append(timeStr)
185             .append("-")
186             .append(SUCCESS_CODE)
187             .append(FILE_SUFFIX);
188         auto res = OHOS::HiviewDFX::DataShareUtil::CopyFile(srcPath.c_str(), desPath.c_str());
189         if (res == -1) {
190             HIVIEW_LOGE("failed to move file to desPath.");
191         }
192         if (chmod(desPath.c_str(), FileUtil::FILE_PERM_666)) {
193             HIVIEW_LOGE("Failed to chmod socket.");
194         }
195     }
196 }
197 
HandleAppUninstallEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> & event)198 void DataPublisher::HandleAppUninstallEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> &event)
199 {
200     if (event->eventName_ != BUNDLE_UNINSTALL) {
201         return;
202     }
203     std::string jsonExtraInfo = event->AsJsonStr();
204     std::string bundleName = GetBundleNameFromJsonStr(jsonExtraInfo);
205     if (bundleName.empty()) {
206         return;
207     }
208     int32_t uid = -1;
209     std::shared_ptr<DataShareDao> dataShareDao = GetDataShareDao();
210     auto ret = dataShareDao->GetUidByBundleName(bundleName, uid);
211     if (ret != DB_SUCC) {
212         HIVIEW_LOGE("failed to query from DB.");
213         return;
214     }
215     ret = RemoveSubscriber(uid);
216     if (ret != DB_SUCC) {
217         HIVIEW_LOGE("failed to remove from DB.");
218     }
219 }
220 
HandleAppStartEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> & event)221 void DataPublisher::HandleAppStartEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> &event)
222 {
223     if (event->eventName_ != "APP_START") {
224         return;
225     }
226     std::string jsonExtraInfo = event->AsJsonStr();
227     std::string bundleName = GetBundleNameFromJsonStr(jsonExtraInfo);
228     if (bundleName.empty()) {
229         HIVIEW_LOGW("bundleName empty.");
230         return;
231     }
232     int32_t uid = OHOS::HiviewDFX::DataShareUtil::GetUidByBundleName(bundleName);
233     EventPublish::GetInstance().PushEvent(uid, event->eventName_, HiSysEvent::EventType::BEHAVIOR, jsonExtraInfo);
234 }
235 
SetWorkLoop(std::shared_ptr<EventLoop> looper)236 void DataPublisher::SetWorkLoop(std::shared_ptr<EventLoop> looper)
237 {
238     if (looper == nullptr) {
239         HIVIEW_LOGW("SetWorkLoop failed, looper is null.");
240         return;
241     }
242     looper_ = looper;
243 }
244 
AddExportTask(std::shared_ptr<BaseEventQueryWrapper> queryWrapper,int64_t timestamp,int32_t uid)245 void DataPublisher::AddExportTask(std::shared_ptr<BaseEventQueryWrapper> queryWrapper, int64_t timestamp, int32_t uid)
246 {
247     auto iter = uidTimeStampMap_.find(uid);
248     if (iter != uidTimeStampMap_.end()) {
249         iter->second = timestamp;
250     } else {
251         uidTimeStampMap_[uid] = timestamp;
252     }
253     if (!CreateHiviewTempDir()) {
254         HIVIEW_LOGE("failed to create resourceFile.");
255         return;
256     }
257     std::string timeStr = std::to_string(timestamp);
258     std::string srcPath = TEMP_EXPORT_SRC_DIR;
259     if (!FileUtil::RemoveFile(srcPath)) {
260         HIVIEW_LOGE("failed to remove resourceFile.");
261     }
262     std::string desPath = OHOS::HiviewDFX::DataShareUtil::GetSandBoxPathByUid(uid);
263     desPath.append(DOMAIN_PATH);
264     desPath.append(timeStr);
265     if (looper_ != nullptr) {
266         auto task = [queryWrapper, srcPath, desPath] {
267             OHOS::sptr<OHOS::HiviewDFX::IQueryBaseCallback> exportCallback =
268                 new(std::nothrow) DataPublisherSysEventCallback(srcPath, desPath, 0, 0);
269             int32_t queryResult = 0;
270             queryWrapper->Query(exportCallback, queryResult);
271         };
272         looper_->AddTimerEvent(nullptr, nullptr, task, DELAY_TIME, false);
273     } else {
274         static OHOS::sptr<OHOS::HiviewDFX::IQueryBaseCallback> exportCallback =
275             new(std::nothrow) DataPublisherSysEventCallback(srcPath, desPath, 0, 0);
276         int32_t queryResult = 0;
277         queryWrapper->Query(exportCallback, queryResult);
278     }
279 }
280 
CreateHiviewTempDir()281 bool DataPublisher::CreateHiviewTempDir()
282 {
283     if (!FileUtil::FileExists(PATH_DIR) && !FileUtil::ForceCreateDirectory(PATH_DIR)) {
284         HIVIEW_LOGE("failed to create events dir.");
285         return false;
286     }
287     return true;
288 }
289 
GetTimeStampByUid(int32_t uid)290 int64_t DataPublisher::GetTimeStampByUid(int32_t uid)
291 {
292     int64_t timeStamp;
293     auto iter = uidTimeStampMap_.find(uid);
294     if (iter != uidTimeStampMap_.end()) {
295         timeStamp = iter->second;
296     } else {
297         timeStamp = 0;
298     }
299     return timeStamp;
300 }
301 
GetDataShareDao()302 std::shared_ptr<DataShareDao> DataPublisher::GetDataShareDao()
303 {
304     std::shared_ptr<DataShareStore> dataShareStore = std::make_shared<DataShareStore>(DATABASE_DIR);
305     return std::make_shared<DataShareDao>(dataShareStore);
306 }
307 
308 }  // namespace HiviewDFX
309 }  // namespace OHOS