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