1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "event_statistic.h"
17c29fa5a6Sopenharmony_ci#include "mmi_log.h"
18c29fa5a6Sopenharmony_ci#include "util_ex.h"
19c29fa5a6Sopenharmony_ci
20c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN
21c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_HANDLER
22c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG
23c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "EventStatistic"
24c29fa5a6Sopenharmony_ci
25c29fa5a6Sopenharmony_cinamespace OHOS {
26c29fa5a6Sopenharmony_cinamespace MMI {
27c29fa5a6Sopenharmony_cinamespace {
28c29fa5a6Sopenharmony_ciconst std::string EVENT_FILE_NAME = "/data/service/el1/public/multimodalinput/multimodal_event.dmp";
29c29fa5a6Sopenharmony_ciconst std::string EVENT_FILE_NAME_HISTORY = "/data/service/el1/public/multimodalinput/multimodal_event_history.dmp";
30c29fa5a6Sopenharmony_ciconstexpr int32_t FILE_MAX_SIZE = 100 * 1024 * 1024;
31c29fa5a6Sopenharmony_ciconstexpr int32_t EVENT_OUT_SIZE = 30;
32c29fa5a6Sopenharmony_ciconstexpr int32_t FUNC_EXE_OK = 0;
33c29fa5a6Sopenharmony_ciconstexpr int32_t STRING_WIDTH = 3;
34c29fa5a6Sopenharmony_ci}
35c29fa5a6Sopenharmony_ci
36c29fa5a6Sopenharmony_cistd::queue<std::string> EventStatistic::eventQueue_;
37c29fa5a6Sopenharmony_cistd::list<std::string> EventStatistic::dumperEventList_;
38c29fa5a6Sopenharmony_cistd::mutex EventStatistic::queueMutex_;
39c29fa5a6Sopenharmony_cistd::condition_variable EventStatistic::queueCondition_;
40c29fa5a6Sopenharmony_cibool EventStatistic::writeFileEnabled_ = false;
41c29fa5a6Sopenharmony_ci
42c29fa5a6Sopenharmony_cistd::string EventStatistic::ConvertEventToStr(const std::shared_ptr<InputEvent> eventPtr)
43c29fa5a6Sopenharmony_ci{
44c29fa5a6Sopenharmony_ci    auto nowTime = std::chrono::system_clock::now();
45c29fa5a6Sopenharmony_ci    std::time_t timeT = std::chrono::system_clock::to_time_t(nowTime);
46c29fa5a6Sopenharmony_ci    auto milsecsCount = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime.time_since_epoch()).count();
47c29fa5a6Sopenharmony_ci    std::string handleTime = ConvertTimeToStr(static_cast<int64_t>(timeT));
48c29fa5a6Sopenharmony_ci    int32_t milsec = milsecsCount % 1000;
49c29fa5a6Sopenharmony_ci    std::stringstream strStream;
50c29fa5a6Sopenharmony_ci    strStream << std::left << std::setw(STRING_WIDTH) << milsec;
51c29fa5a6Sopenharmony_ci    std::string milsecStr(strStream.str());
52c29fa5a6Sopenharmony_ci    handleTime += "." + milsecStr;
53c29fa5a6Sopenharmony_ci    std::string eventStr = "{" + handleTime + "," + eventPtr->ToString() + "}";
54c29fa5a6Sopenharmony_ci    return eventStr;
55c29fa5a6Sopenharmony_ci}
56c29fa5a6Sopenharmony_ci
57c29fa5a6Sopenharmony_cistd::string EventStatistic::ConvertTimeToStr(int64_t timestamp)
58c29fa5a6Sopenharmony_ci{
59c29fa5a6Sopenharmony_ci    std::string timeStr = std::to_string(timestamp);
60c29fa5a6Sopenharmony_ci    std::time_t timeT = timestamp;
61c29fa5a6Sopenharmony_ci    std::tm tmInfo;
62c29fa5a6Sopenharmony_ci    localtime_r(&timeT, &tmInfo);
63c29fa5a6Sopenharmony_ci    char buffer[32] = {0};
64c29fa5a6Sopenharmony_ci    if (std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmInfo) > 0) {
65c29fa5a6Sopenharmony_ci        timeStr = buffer;
66c29fa5a6Sopenharmony_ci    }
67c29fa5a6Sopenharmony_ci    return timeStr;
68c29fa5a6Sopenharmony_ci}
69c29fa5a6Sopenharmony_ci
70c29fa5a6Sopenharmony_civoid EventStatistic::PushPointerEvent(std::shared_ptr<PointerEvent> eventPtr)
71c29fa5a6Sopenharmony_ci{
72c29fa5a6Sopenharmony_ci    CHKPV(eventPtr);
73c29fa5a6Sopenharmony_ci    int32_t pointerAction = eventPtr->GetPointerAction();
74c29fa5a6Sopenharmony_ci    if (pointerAction == PointerEvent::POINTER_ACTION_MOVE ||
75c29fa5a6Sopenharmony_ci        eventPtr->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
76c29fa5a6Sopenharmony_ci        MMI_HILOGD("PointEvent is filtered");
77c29fa5a6Sopenharmony_ci        return;
78c29fa5a6Sopenharmony_ci    }
79c29fa5a6Sopenharmony_ci    PushEvent(eventPtr);
80c29fa5a6Sopenharmony_ci}
81c29fa5a6Sopenharmony_ci
82c29fa5a6Sopenharmony_civoid EventStatistic::PushEvent(std::shared_ptr<InputEvent> eventPtr)
83c29fa5a6Sopenharmony_ci{
84c29fa5a6Sopenharmony_ci    std::lock_guard<std::mutex> lock(queueMutex_);
85c29fa5a6Sopenharmony_ci    CHKPV(eventPtr);
86c29fa5a6Sopenharmony_ci    std::string eventStr = ConvertEventToStr(eventPtr);
87c29fa5a6Sopenharmony_ci    dumperEventList_.push_back(eventStr);
88c29fa5a6Sopenharmony_ci    if (dumperEventList_.size() > EVENT_OUT_SIZE) {
89c29fa5a6Sopenharmony_ci        dumperEventList_.pop_front();
90c29fa5a6Sopenharmony_ci    }
91c29fa5a6Sopenharmony_ci    if (writeFileEnabled_) {
92c29fa5a6Sopenharmony_ci        eventQueue_.push(eventStr);
93c29fa5a6Sopenharmony_ci        queueCondition_.notify_all();
94c29fa5a6Sopenharmony_ci    }
95c29fa5a6Sopenharmony_ci}
96c29fa5a6Sopenharmony_ci
97c29fa5a6Sopenharmony_cistd::string EventStatistic::PopEvent()
98c29fa5a6Sopenharmony_ci{
99c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(queueMutex_);
100c29fa5a6Sopenharmony_ci    if (eventQueue_.empty()) {
101c29fa5a6Sopenharmony_ci        queueCondition_.wait(lock, []() { return !eventQueue_.empty(); });
102c29fa5a6Sopenharmony_ci    }
103c29fa5a6Sopenharmony_ci    std::string eventStr = eventQueue_.front();
104c29fa5a6Sopenharmony_ci    eventQueue_.pop();
105c29fa5a6Sopenharmony_ci    return eventStr;
106c29fa5a6Sopenharmony_ci}
107c29fa5a6Sopenharmony_ci
108c29fa5a6Sopenharmony_civoid EventStatistic::WriteEventFile()
109c29fa5a6Sopenharmony_ci{
110c29fa5a6Sopenharmony_ci    while (writeFileEnabled_) {
111c29fa5a6Sopenharmony_ci        std::string eventStr = PopEvent();
112c29fa5a6Sopenharmony_ci        struct stat statbuf;
113c29fa5a6Sopenharmony_ci        int32_t fileSize = 0;
114c29fa5a6Sopenharmony_ci        if (stat(EVENT_FILE_NAME.c_str(), &statbuf) == FUNC_EXE_OK) {
115c29fa5a6Sopenharmony_ci            fileSize = static_cast<int32_t>(statbuf.st_size);
116c29fa5a6Sopenharmony_ci        }
117c29fa5a6Sopenharmony_ci        if (fileSize >= FILE_MAX_SIZE) {
118c29fa5a6Sopenharmony_ci            if (access(EVENT_FILE_NAME_HISTORY.c_str(), F_OK) == FUNC_EXE_OK &&
119c29fa5a6Sopenharmony_ci                remove(EVENT_FILE_NAME_HISTORY.c_str()) != FUNC_EXE_OK) {
120c29fa5a6Sopenharmony_ci                MMI_HILOGE("Remove history file failed");
121c29fa5a6Sopenharmony_ci            }
122c29fa5a6Sopenharmony_ci            if (rename(EVENT_FILE_NAME.c_str(), EVENT_FILE_NAME_HISTORY.c_str()) != FUNC_EXE_OK) {
123c29fa5a6Sopenharmony_ci                MMI_HILOGE("Rename file failed");
124c29fa5a6Sopenharmony_ci            }
125c29fa5a6Sopenharmony_ci        }
126c29fa5a6Sopenharmony_ci        std::ofstream file(EVENT_FILE_NAME, std::ios::app);
127c29fa5a6Sopenharmony_ci        if (file.is_open()) {
128c29fa5a6Sopenharmony_ci            file << eventStr << std::endl;
129c29fa5a6Sopenharmony_ci            file.close();
130c29fa5a6Sopenharmony_ci        } else {
131c29fa5a6Sopenharmony_ci            MMI_HILOGE("Open file failed");
132c29fa5a6Sopenharmony_ci        }
133c29fa5a6Sopenharmony_ci    }
134c29fa5a6Sopenharmony_ci}
135c29fa5a6Sopenharmony_ci
136c29fa5a6Sopenharmony_civoid EventStatistic::Dump(int32_t fd, const std::vector<std::string> &args)
137c29fa5a6Sopenharmony_ci{
138c29fa5a6Sopenharmony_ci    std::lock_guard<std::mutex> lock(queueMutex_);
139c29fa5a6Sopenharmony_ci    for (auto it = dumperEventList_.begin(); it != dumperEventList_.end(); ++it) {
140c29fa5a6Sopenharmony_ci        mprintf(fd, (*it).c_str());
141c29fa5a6Sopenharmony_ci    }
142c29fa5a6Sopenharmony_ci}
143c29fa5a6Sopenharmony_ci} // namespace MMI
144c29fa5a6Sopenharmony_ci} // namespace OHOS