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