• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 #include "os_event_listener.h"
16 
17 #include <cerrno>
18 #include <fstream>
19 #include <sys/inotify.h>
20 
21 #include "app_event_observer_mgr.h"
22 #include "app_event_store.h"
23 #include "application_context.h"
24 #include "event_json_util.h"
25 #include "file_util.h"
26 #include "hiappevent_base.h"
27 #include "hilog/log.h"
28 #include "parameters.h"
29 #include "storage_acl.h"
30 
31 #undef LOG_DOMAIN
32 #define LOG_DOMAIN 0xD002D07
33 
34 #undef LOG_TAG
35 #define LOG_TAG "OsEventListener"
36 
37 namespace OHOS {
38 namespace HiviewDFX {
39 namespace {
40 constexpr int BUF_SIZE = 2048;
41 const std::string APP_EVENT_DIR = "/hiappevent";
42 const std::string DOMAIN_PROPERTY = "domain";
43 const std::string NAME_PROPERTY = "name";
44 const std::string EVENT_TYPE_PROPERTY = "eventType";
45 const std::string PARAM_PROPERTY = "params";
46 const std::string RUNNING_ID_PROPERTY = "app_running_unique_id";
47 const std::string OS_LOG_PATH = "/data/storage/el2/log/hiappevent";
48 const std::string XATTR_NAME = "user.appevent";
49 const std::string KEY_HIAPPEVENT_ENABLE = "hiviewdfx.hiappevent.enable";
50 
UpdateListenedEvents(const std::string & dir,uint64_t eventsMask)51 bool UpdateListenedEvents(const std::string& dir, uint64_t eventsMask)
52 {
53     if (!FileUtil::SetDirXattr(dir, XATTR_NAME, std::to_string(eventsMask))) {
54         HILOG_ERROR(LOG_CORE, "failed to set xattr dir=%{public}s, value=%{public}" PRIu64, dir.c_str(), eventsMask);
55         return false;
56     }
57     return true;
58 }
59 
GetMaskFromDirXattr(const std::string & path)60 uint64_t GetMaskFromDirXattr(const std::string& path)
61 {
62     std::string value;
63     if (!FileUtil::GetDirXattr(path, XATTR_NAME, value)) {
64         HILOG_ERROR(LOG_CORE, "failed to get xattr.");
65         return 0;
66     }
67     HILOG_INFO(LOG_CORE, "getxattr success value=%{public}s.", value.c_str());
68     return static_cast<uint64_t>(std::strtoull(value.c_str(), nullptr, 0));
69 }
70 }
71 
OsEventListener()72 OsEventListener::OsEventListener()
73 {
74     Init();
75 }
76 
~OsEventListener()77 OsEventListener::~OsEventListener()
78 {
79     HILOG_INFO(LOG_CORE, "~OsEventListener");
80     inotifyThread_ = nullptr;
81     if (inotifyFd_ != -1) {
82         (void)inotify_rm_watch(inotifyFd_, inotifyWd_);
83         close(inotifyFd_);
84         inotifyFd_ = -1;
85     }
86 }
87 
Init()88 void OsEventListener::Init()
89 {
90     std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
91         OHOS::AbilityRuntime::Context::GetApplicationContext();
92     if (context == nullptr) {
93         HILOG_ERROR(LOG_CORE, "Context is null.");
94         return;
95     }
96     if (context->GetCacheDir().empty()) {
97         HILOG_ERROR(LOG_CORE, "The files dir obtained from context is empty.");
98         return;
99     }
100     osEventPath_ = context->GetCacheDir() + APP_EVENT_DIR;
101     if (!FileUtil::IsFileExists(osEventPath_)) {
102         return;
103     }
104     // get subscribed events from dir xattr
105     osEventsMask_ = GetMaskFromDirXattr(osEventPath_);
106 
107     // read os events from dir files
108     std::vector<std::string> files;
109     FileUtil::GetDirFiles(osEventPath_, files);
110     GetEventsFromFiles(files, historyEvents_);
111     for (auto& event : historyEvents_) {
112         int64_t eventSeq = AppEventStore::GetInstance().InsertEvent(event);
113         if (eventSeq <= 0) {
114             HILOG_WARN(LOG_CORE, "failed to store event to db");
115             continue;
116         }
117         event->SetSeq(eventSeq);
118         AppEventStore::GetInstance().QueryCustomParamsAdd2EventPack(event);
119     }
120     for (const auto& file : files) {
121         (void)FileUtil::RemoveFile(file);
122     }
123 }
124 
GetEvents(std::vector<std::shared_ptr<AppEventPack>> & events)125 void OsEventListener::GetEvents(std::vector<std::shared_ptr<AppEventPack>>& events)
126 {
127     events = historyEvents_;
128 }
129 
StartListening()130 bool OsEventListener::StartListening()
131 {
132     if (!OHOS::system::GetBoolParameter(KEY_HIAPPEVENT_ENABLE, true)) {
133         HILOG_INFO(LOG_CORE, "hiappevent is disabled");
134         RemoveOsEventDir();
135         return false;
136     }
137     return InitDir(OS_LOG_PATH) && InitDir(osEventPath_) && RegisterDirListener(osEventPath_);
138 }
139 
RemoveOsEventDir()140 bool OsEventListener::RemoveOsEventDir()
141 {
142     inotifyStopFlag_ = true;
143     HILOG_INFO(LOG_CORE, "rm dir");
144     return FileUtil::ForceRemoveDirectory(osEventPath_) && FileUtil::ForceRemoveDirectory(OS_LOG_PATH);
145 }
146 
InitDir(const std::string & dirPath)147 bool OsEventListener::InitDir(const std::string& dirPath)
148 {
149     if (!FileUtil::IsFileExists(dirPath) && !FileUtil::ForceCreateDirectory(dirPath)) {
150         HILOG_ERROR(LOG_CORE, "failed to create dir=%{public}s", dirPath.c_str());
151         return false;
152     }
153     if (OHOS::StorageDaemon::AclSetAccess(dirPath, "u:1201:rwx") != 0) {
154         HILOG_ERROR(LOG_CORE, "failed to set acl access dir=%{public}s", dirPath.c_str());
155         return false;
156     }
157     return true;
158 }
159 
AddListenedEvents(uint64_t eventsMask)160 bool OsEventListener::AddListenedEvents(uint64_t eventsMask)
161 {
162     osEventsMask_ |= eventsMask;
163     HILOG_INFO(LOG_CORE, "add mask=%{public}" PRIu64 ", eventsMask=%{public}" PRIu64, eventsMask, osEventsMask_);
164     return UpdateListenedEvents(osEventPath_, osEventsMask_);
165 }
166 
SetListenedEvents(uint64_t eventsMask)167 bool OsEventListener::SetListenedEvents(uint64_t eventsMask)
168 {
169     osEventsMask_ = eventsMask;
170     HILOG_INFO(LOG_CORE, "set eventsMask=%{public}" PRIu64, osEventsMask_);
171     return UpdateListenedEvents(osEventPath_, osEventsMask_);
172 }
173 
RegisterDirListener(const std::string & dirPath)174 bool OsEventListener::RegisterDirListener(const std::string& dirPath)
175 {
176     if (inotifyFd_ < 0) {
177         inotifyFd_ = inotify_init();
178         if (inotifyFd_ < 0) {
179             HILOG_ERROR(LOG_CORE, "failed to inotify init : %s(%s).\n", strerror(errno), dirPath.c_str());
180             return false;
181         }
182         inotifyWd_ = inotify_add_watch(inotifyFd_, dirPath.c_str(), IN_MOVED_TO | IN_CLOSE_WRITE);
183         if (inotifyWd_ < 0) {
184             HILOG_ERROR(LOG_CORE, "failed to add watch entry : %s(%s).\n", strerror(errno), dirPath.c_str());
185             close(inotifyFd_);
186             inotifyFd_ = -1;
187             return false;
188         }
189         HILOG_INFO(LOG_CORE, "inotify add watch dir=%{public}s successfully", dirPath.c_str());
190     }
191     inotifyStopFlag_ = false;
192     if (inotifyThread_ == nullptr) {
193         auto listenerPtr = shared_from_this();
194         inotifyThread_ = std::make_unique<std::thread>([listenerPtr] { listenerPtr->HandleDirEvent(); });
195         inotifyThread_->detach();
196     }
197     return true;
198 }
199 
HandleDirEvent()200 void OsEventListener::HandleDirEvent()
201 {
202     if (pthread_setname_np(pthread_self(), "OS_AppEvent_Ls") != 0) {
203         HILOG_WARN(LOG_CORE, "Failed to set threadName, errno=%{public}d", errno);
204     }
205     while (!inotifyStopFlag_) {
206         char buffer[BUF_SIZE] = {0};
207         char* offset = buffer;
208         struct inotify_event* event = reinterpret_cast<struct inotify_event*>(buffer);
209         if (inotifyFd_ < 0) {
210             HILOG_ERROR(LOG_CORE, "Invalid inotify fd=%{public}d", inotifyFd_);
211             break;
212         }
213         int len = read(inotifyFd_, buffer, sizeof(buffer) - 1);
214         if (len <= 0) {
215             HILOG_ERROR(LOG_CORE, "failed to read event");
216             continue;
217         }
218         while ((offset - buffer) < len) {
219             if (event->len != 0) {
220                 HILOG_INFO(LOG_CORE, "fileName: %{public}s event->mask: 0x%{public}x, event->len: %{public}d",
221                     event->name, event->mask, event->len);
222                 std::string fileName = FileUtil::GetFilePathByDir(osEventPath_, std::string(event->name));
223                 HandleInotify(fileName);
224             }
225             uint32_t tmpLen = sizeof(struct inotify_event) + event->len;
226             event = reinterpret_cast<struct inotify_event*>(offset + tmpLen);
227             offset += tmpLen;
228         }
229     }
230 }
231 
HandleInotify(const std::string & file)232 void OsEventListener::HandleInotify(const std::string& file)
233 {
234     std::vector<std::shared_ptr<AppEventPack>> events;
235     GetEventsFromFiles({file}, events);
236     AppEventObserverMgr::GetInstance().HandleEvents(events);
237     (void)FileUtil::RemoveFile(file);
238 }
239 
GetEventsFromFiles(const std::vector<std::string> & files,std::vector<std::shared_ptr<AppEventPack>> & events)240 void OsEventListener::GetEventsFromFiles(
241     const std::vector<std::string>& files, std::vector<std::shared_ptr<AppEventPack>>& events)
242 {
243     for (const auto& filePath : files) {
244         std::vector<std::string> lines;
245         if (!FileUtil::LoadLinesFromFile(filePath, lines)) {
246             HILOG_ERROR(LOG_CORE, "file open failed, file=%{public}s", filePath.c_str());
247             continue;
248         }
249         for (const auto& line : lines) {
250             auto event = GetAppEventPackFromJson(line);
251             if (event != nullptr) {
252                 events.emplace_back(event);
253             }
254         }
255     }
256 }
257 
GetAppEventPackFromJson(const std::string & jsonStr)258 std::shared_ptr<AppEventPack> OsEventListener::GetAppEventPackFromJson(const std::string& jsonStr)
259 {
260     Json::Value eventJson;
261     Json::Reader reader(Json::Features::strictMode());
262     if (!reader.parse(jsonStr, eventJson)) {
263         HILOG_ERROR(LOG_CORE, "parse event detail info failed, please check the style of json");
264         return nullptr;
265     }
266     if (!eventJson.isObject()) {
267         return nullptr;
268     }
269     auto appEventPack = std::make_shared<AppEventPack>();
270     appEventPack->SetDomain(EventJsonUtil::ParseString(eventJson, DOMAIN_PROPERTY));
271     appEventPack->SetName(EventJsonUtil::ParseString(eventJson, NAME_PROPERTY));
272     appEventPack->SetType(EventJsonUtil::ParseInt(eventJson, EVENT_TYPE_PROPERTY));
273     if (eventJson.isMember(PARAM_PROPERTY) && eventJson[PARAM_PROPERTY].isObject()) {
274         Json::Value paramsJson = eventJson[PARAM_PROPERTY];
275         if (paramsJson.isMember(RUNNING_ID_PROPERTY) && paramsJson[RUNNING_ID_PROPERTY].isString()) {
276             appEventPack->SetRunningId(paramsJson[RUNNING_ID_PROPERTY].asString());
277             paramsJson.removeMember(RUNNING_ID_PROPERTY);
278         }
279         appEventPack->SetParamStr(Json::FastWriter().write(paramsJson));
280     }
281     return appEventPack;
282 }
283 } // namespace HiviewDFX
284 } // namespace OHOS
285