1/* 2 * Copyright (c) 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 16#include "event_statistic.h" 17#include "mmi_log.h" 18#include "util_ex.h" 19 20#undef MMI_LOG_DOMAIN 21#define MMI_LOG_DOMAIN MMI_LOG_HANDLER 22#undef MMI_LOG_TAG 23#define MMI_LOG_TAG "EventStatistic" 24 25namespace OHOS { 26namespace MMI { 27namespace { 28const std::string EVENT_FILE_NAME = "/data/service/el1/public/multimodalinput/multimodal_event.dmp"; 29const std::string EVENT_FILE_NAME_HISTORY = "/data/service/el1/public/multimodalinput/multimodal_event_history.dmp"; 30constexpr int32_t FILE_MAX_SIZE = 100 * 1024 * 1024; 31constexpr int32_t EVENT_OUT_SIZE = 30; 32constexpr int32_t FUNC_EXE_OK = 0; 33constexpr int32_t STRING_WIDTH = 3; 34} 35 36std::queue<std::string> EventStatistic::eventQueue_; 37std::list<std::string> EventStatistic::dumperEventList_; 38std::mutex EventStatistic::queueMutex_; 39std::condition_variable EventStatistic::queueCondition_; 40bool EventStatistic::writeFileEnabled_ = false; 41 42std::string EventStatistic::ConvertEventToStr(const std::shared_ptr<InputEvent> eventPtr) 43{ 44 auto nowTime = std::chrono::system_clock::now(); 45 std::time_t timeT = std::chrono::system_clock::to_time_t(nowTime); 46 auto milsecsCount = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime.time_since_epoch()).count(); 47 std::string handleTime = ConvertTimeToStr(static_cast<int64_t>(timeT)); 48 int32_t milsec = milsecsCount % 1000; 49 std::stringstream strStream; 50 strStream << std::left << std::setw(STRING_WIDTH) << milsec; 51 std::string milsecStr(strStream.str()); 52 handleTime += "." + milsecStr; 53 std::string eventStr = "{" + handleTime + "," + eventPtr->ToString() + "}"; 54 return eventStr; 55} 56 57std::string EventStatistic::ConvertTimeToStr(int64_t timestamp) 58{ 59 std::string timeStr = std::to_string(timestamp); 60 std::time_t timeT = timestamp; 61 std::tm tmInfo; 62 localtime_r(&timeT, &tmInfo); 63 char buffer[32] = {0}; 64 if (std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmInfo) > 0) { 65 timeStr = buffer; 66 } 67 return timeStr; 68} 69 70void EventStatistic::PushPointerEvent(std::shared_ptr<PointerEvent> eventPtr) 71{ 72 CHKPV(eventPtr); 73 int32_t pointerAction = eventPtr->GetPointerAction(); 74 if (pointerAction == PointerEvent::POINTER_ACTION_MOVE || 75 eventPtr->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) { 76 MMI_HILOGD("PointEvent is filtered"); 77 return; 78 } 79 PushEvent(eventPtr); 80} 81 82void EventStatistic::PushEvent(std::shared_ptr<InputEvent> eventPtr) 83{ 84 std::lock_guard<std::mutex> lock(queueMutex_); 85 CHKPV(eventPtr); 86 std::string eventStr = ConvertEventToStr(eventPtr); 87 dumperEventList_.push_back(eventStr); 88 if (dumperEventList_.size() > EVENT_OUT_SIZE) { 89 dumperEventList_.pop_front(); 90 } 91 if (writeFileEnabled_) { 92 eventQueue_.push(eventStr); 93 queueCondition_.notify_all(); 94 } 95} 96 97std::string EventStatistic::PopEvent() 98{ 99 std::unique_lock<std::mutex> lock(queueMutex_); 100 if (eventQueue_.empty()) { 101 queueCondition_.wait(lock, []() { return !eventQueue_.empty(); }); 102 } 103 std::string eventStr = eventQueue_.front(); 104 eventQueue_.pop(); 105 return eventStr; 106} 107 108void EventStatistic::WriteEventFile() 109{ 110 while (writeFileEnabled_) { 111 std::string eventStr = PopEvent(); 112 struct stat statbuf; 113 int32_t fileSize = 0; 114 if (stat(EVENT_FILE_NAME.c_str(), &statbuf) == FUNC_EXE_OK) { 115 fileSize = static_cast<int32_t>(statbuf.st_size); 116 } 117 if (fileSize >= FILE_MAX_SIZE) { 118 if (access(EVENT_FILE_NAME_HISTORY.c_str(), F_OK) == FUNC_EXE_OK && 119 remove(EVENT_FILE_NAME_HISTORY.c_str()) != FUNC_EXE_OK) { 120 MMI_HILOGE("Remove history file failed"); 121 } 122 if (rename(EVENT_FILE_NAME.c_str(), EVENT_FILE_NAME_HISTORY.c_str()) != FUNC_EXE_OK) { 123 MMI_HILOGE("Rename file failed"); 124 } 125 } 126 std::ofstream file(EVENT_FILE_NAME, std::ios::app); 127 if (file.is_open()) { 128 file << eventStr << std::endl; 129 file.close(); 130 } else { 131 MMI_HILOGE("Open file failed"); 132 } 133 } 134} 135 136void EventStatistic::Dump(int32_t fd, const std::vector<std::string> &args) 137{ 138 std::lock_guard<std::mutex> lock(queueMutex_); 139 for (auto it = dumperEventList_.begin(); it != dumperEventList_.end(); ++it) { 140 mprintf(fd, (*it).c_str()); 141 } 142} 143} // namespace MMI 144} // namespace OHOS