1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci 16020a203aSopenharmony_ci#include "active_key_event.h" 17020a203aSopenharmony_ci 18020a203aSopenharmony_ci#include <vector> 19020a203aSopenharmony_ci 20020a203aSopenharmony_ci#include "event_log_task.h" 21020a203aSopenharmony_ci#include "file_util.h" 22020a203aSopenharmony_ci#include "hiview_logger.h" 23020a203aSopenharmony_ci#include "sys_event.h" 24020a203aSopenharmony_ci#include "time_util.h" 25020a203aSopenharmony_ci#include "trace_collector.h" 26020a203aSopenharmony_cinamespace OHOS { 27020a203aSopenharmony_cinamespace HiviewDFX { 28020a203aSopenharmony_cinamespace { 29020a203aSopenharmony_ci static const inline char* CMD_LIST[] = { 30020a203aSopenharmony_ci "cmd:w", 31020a203aSopenharmony_ci "cmd:rs", 32020a203aSopenharmony_ci "cmd:a", 33020a203aSopenharmony_ci "k:SysRqFile", 34020a203aSopenharmony_ci "cmd:p", 35020a203aSopenharmony_ci "cmd:d", 36020a203aSopenharmony_ci "cmd:c", 37020a203aSopenharmony_ci }; 38020a203aSopenharmony_ci} 39020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "EventLogger-ActiveKeyEvent"); 40020a203aSopenharmony_ciActiveKeyEvent::ActiveKeyEvent() 41020a203aSopenharmony_ci{ 42020a203aSopenharmony_ci triggeringTime_ = 0; 43020a203aSopenharmony_ci logStore_ = nullptr; 44020a203aSopenharmony_ci} 45020a203aSopenharmony_ci 46020a203aSopenharmony_ciActiveKeyEvent::~ActiveKeyEvent() 47020a203aSopenharmony_ci{ 48020a203aSopenharmony_ci std::unique_lock<ffrt::mutex> uniqueLock(mutex_); 49020a203aSopenharmony_ci for (auto it = subscribeIds_.begin(); it != subscribeIds_.end(); it = subscribeIds_.erase(it)) { 50020a203aSopenharmony_ci if (*it >= 0) { 51020a203aSopenharmony_ci MMI::InputManager::GetInstance()->UnsubscribeKeyEvent(*it); 52020a203aSopenharmony_ci HIVIEW_LOGI("~ActiveKeyEvent subscribeId_: %{public}d", *it); 53020a203aSopenharmony_ci } 54020a203aSopenharmony_ci } 55020a203aSopenharmony_ci} 56020a203aSopenharmony_ci 57020a203aSopenharmony_ciint64_t ActiveKeyEvent::SystemTimeMillisecond() 58020a203aSopenharmony_ci{ 59020a203aSopenharmony_ci struct timespec t; 60020a203aSopenharmony_ci t.tv_sec = 0; 61020a203aSopenharmony_ci t.tv_nsec = 0; 62020a203aSopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &t); 63020a203aSopenharmony_ci return (int64_t)((t.tv_sec) * TimeUtil::SEC_TO_NANOSEC + t.tv_nsec) / TimeUtil::SEC_TO_MICROSEC; 64020a203aSopenharmony_ci} 65020a203aSopenharmony_ci 66020a203aSopenharmony_civoid ActiveKeyEvent::InitSubscribe(std::set<int32_t> preKeys, int32_t finalKey, int32_t count, int32_t holdTime) 67020a203aSopenharmony_ci{ 68020a203aSopenharmony_ci const int32_t maxCount = 5; 69020a203aSopenharmony_ci if (++count > maxCount) { 70020a203aSopenharmony_ci return; 71020a203aSopenharmony_ci } 72020a203aSopenharmony_ci std::shared_ptr<MMI::KeyOption> keyOption = std::make_shared<MMI::KeyOption>(); 73020a203aSopenharmony_ci if (keyOption == nullptr) { 74020a203aSopenharmony_ci HIVIEW_LOGE("Invalid key option"); 75020a203aSopenharmony_ci return; 76020a203aSopenharmony_ci } 77020a203aSopenharmony_ci 78020a203aSopenharmony_ci keyOption->SetPreKeys(preKeys); 79020a203aSopenharmony_ci keyOption->SetFinalKey(finalKey); 80020a203aSopenharmony_ci keyOption->SetFinalKeyDown(true); 81020a203aSopenharmony_ci keyOption->SetFinalKeyDownDuration(holdTime); 82020a203aSopenharmony_ci auto keyEventCallBack = [this] (std::shared_ptr<MMI::KeyEvent> keyEvent) { 83020a203aSopenharmony_ci this->CombinationKeyCallback(keyEvent); 84020a203aSopenharmony_ci }; 85020a203aSopenharmony_ci int32_t subscribeId = MMI::InputManager::GetInstance()->SubscribeKeyEvent(keyOption, keyEventCallBack); 86020a203aSopenharmony_ci if (subscribeId < 0) { 87020a203aSopenharmony_ci HIVIEW_LOGE("SubscribeKeyEvent failed, finalKey: %{public}d," 88020a203aSopenharmony_ci "subscribeId: %{public}d option failed.", finalKey, subscribeId); 89020a203aSopenharmony_ci auto task = [this, preKeys, finalKey, count, holdTime] { 90020a203aSopenharmony_ci this->InitSubscribe(preKeys, finalKey, count, holdTime); 91020a203aSopenharmony_ci taskOutDeps++; 92020a203aSopenharmony_ci }; 93020a203aSopenharmony_ci std::string taskName("InitSubscribe" + std::to_string(finalKey) + "_" + std::to_string(count)); 94020a203aSopenharmony_ci ffrt::submit(task, {}, {&taskOutDeps}, ffrt::task_attr().name(taskName.c_str())); 95020a203aSopenharmony_ci } 96020a203aSopenharmony_ci std::unique_lock<ffrt::mutex> uniqueLock(mutex_); 97020a203aSopenharmony_ci subscribeIds_.emplace_back(subscribeId); 98020a203aSopenharmony_ci HIVIEW_LOGI("CombinationKeyInit finalKey: %{public}d subscribeId_: %{public}d", 99020a203aSopenharmony_ci finalKey, subscribeId); 100020a203aSopenharmony_ci} 101020a203aSopenharmony_ci 102020a203aSopenharmony_civoid ActiveKeyEvent::Init(std::shared_ptr<LogStoreEx> logStore) 103020a203aSopenharmony_ci{ 104020a203aSopenharmony_ci HIVIEW_LOGI("CombinationKeyInit"); 105020a203aSopenharmony_ci logStore_ = logStore; 106020a203aSopenharmony_ci 107020a203aSopenharmony_ci std::set<int32_t> prePowerKeys; 108020a203aSopenharmony_ci prePowerKeys.insert(MMI::KeyEvent::KEYCODE_VOLUME_DOWN); 109020a203aSopenharmony_ci auto initSubscribePower = [this, prePowerKeys] { 110020a203aSopenharmony_ci this->InitSubscribe(prePowerKeys, MMI::KeyEvent::KEYCODE_POWER, 0, 500); 111020a203aSopenharmony_ci }; 112020a203aSopenharmony_ci std::set<int32_t> preOnlyPowerKeys; 113020a203aSopenharmony_ci auto initSubscribeOnlyPower = [this, preOnlyPowerKeys] { 114020a203aSopenharmony_ci this->InitSubscribe(preOnlyPowerKeys, MMI::KeyEvent::KEYCODE_POWER, 0, 3000); 115020a203aSopenharmony_ci }; 116020a203aSopenharmony_ci ffrt::submit(initSubscribePower, {}, {}, ffrt::task_attr().name("initSubscribePower").qos(ffrt::qos_default)); 117020a203aSopenharmony_ci ffrt::submit(initSubscribeOnlyPower, {}, {}, 118020a203aSopenharmony_ci ffrt::task_attr().name("initSubscribeOnlyPower").qos(ffrt::qos_default)); 119020a203aSopenharmony_ci} 120020a203aSopenharmony_ci 121020a203aSopenharmony_civoid ActiveKeyEvent::HitraceCapture() 122020a203aSopenharmony_ci{ 123020a203aSopenharmony_ci std::shared_ptr<UCollectUtil::TraceCollector> collector = UCollectUtil::TraceCollector::Create(); 124020a203aSopenharmony_ci UCollect::TraceCaller caller = UCollect::TraceCaller::BETACLUB; 125020a203aSopenharmony_ci auto result = collector->DumpTrace(caller); 126020a203aSopenharmony_ci if (result.retCode != 0) { 127020a203aSopenharmony_ci HIVIEW_LOGE("get hitrace fail! error code: %{public}d", result.retCode); 128020a203aSopenharmony_ci return; 129020a203aSopenharmony_ci } 130020a203aSopenharmony_ci} 131020a203aSopenharmony_ci 132020a203aSopenharmony_civoid ActiveKeyEvent::SysMemCapture(int fd) 133020a203aSopenharmony_ci{ 134020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, "\n\ncatcher cmd : /proc/meminfo\n"); 135020a203aSopenharmony_ci std::string content; 136020a203aSopenharmony_ci FileUtil::LoadStringFromFile("/proc/meminfo", content); 137020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 138020a203aSopenharmony_ci} 139020a203aSopenharmony_ci 140020a203aSopenharmony_civoid ActiveKeyEvent::DumpCapture(int fd) 141020a203aSopenharmony_ci{ 142020a203aSopenharmony_ci SysEventCreator sysEventCreator("HIVIEWDFX", "ACTIVE_KEY", SysEventCreator::FAULT); 143020a203aSopenharmony_ci std::shared_ptr<SysEvent> sysEvent = std::make_shared<SysEvent>("ActiveKeyEvent", nullptr, sysEventCreator); 144020a203aSopenharmony_ci int noNeedJsonFd = -1; 145020a203aSopenharmony_ci std::unique_ptr<EventLogTask> logTask = std::make_unique<EventLogTask>(fd, noNeedJsonFd, sysEvent); 146020a203aSopenharmony_ci for (const std::string& cmd : CMD_LIST) { 147020a203aSopenharmony_ci logTask->AddLog(cmd); 148020a203aSopenharmony_ci } 149020a203aSopenharmony_ci 150020a203aSopenharmony_ci auto ret = logTask->StartCompose(); 151020a203aSopenharmony_ci if (ret != EventLogTask::TASK_SUCCESS) { 152020a203aSopenharmony_ci HIVIEW_LOGE("capture fail %{public}d", ret); 153020a203aSopenharmony_ci } 154020a203aSopenharmony_ci SysMemCapture(fd); 155020a203aSopenharmony_ci} 156020a203aSopenharmony_ci 157020a203aSopenharmony_civoid ActiveKeyEvent::CombinationKeyHandle(std::shared_ptr<MMI::KeyEvent> keyEvent) 158020a203aSopenharmony_ci{ 159020a203aSopenharmony_ci HIVIEW_LOGI("Receive CombinationKeyHandle."); 160020a203aSopenharmony_ci if (logStore_ == nullptr) { 161020a203aSopenharmony_ci return; 162020a203aSopenharmony_ci } 163020a203aSopenharmony_ci 164020a203aSopenharmony_ci std::string logFile = "ACTIVE_KEY_EVENT-0-" + 165020a203aSopenharmony_ci TimeUtil::TimestampFormatToDate(TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC, 166020a203aSopenharmony_ci "%Y%m%d%H%M%S") + ".log"; 167020a203aSopenharmony_ci if (FileUtil::FileExists("/data/log/eventlog/" + logFile)) { 168020a203aSopenharmony_ci HIVIEW_LOGW("filename: %{public}s is existed, direct use.", logFile.c_str()); 169020a203aSopenharmony_ci return; 170020a203aSopenharmony_ci } 171020a203aSopenharmony_ci int fd = logStore_->CreateLogFile(logFile); 172020a203aSopenharmony_ci 173020a203aSopenharmony_ci auto sysStart = ActiveKeyEvent::SystemTimeMillisecond(); 174020a203aSopenharmony_ci const uint32_t placeholder = 3; 175020a203aSopenharmony_ci auto start = TimeUtil::GetMilliseconds(); 176020a203aSopenharmony_ci uint64_t startTime = start / TimeUtil::SEC_TO_MILLISEC; 177020a203aSopenharmony_ci std::ostringstream startTimeStr; 178020a203aSopenharmony_ci startTimeStr << "start time: " << TimeUtil::TimestampFormatToDate(startTime, "%Y/%m/%d-%H:%M:%S"); 179020a203aSopenharmony_ci startTimeStr << ":" << std::setw(placeholder) << std::setfill('0') << 180020a203aSopenharmony_ci std::to_string(start % TimeUtil::SEC_TO_MILLISEC) << std::endl; 181020a203aSopenharmony_ci std::vector<int32_t> keys = keyEvent->GetPressedKeys(); 182020a203aSopenharmony_ci for (auto& i : keys) { 183020a203aSopenharmony_ci startTimeStr << "CombinationKeyCallback key : "; 184020a203aSopenharmony_ci startTimeStr << MMI::KeyEvent::KeyCodeToString(i) << std::endl; 185020a203aSopenharmony_ci } 186020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, startTimeStr.str()); 187020a203aSopenharmony_ci 188020a203aSopenharmony_ci auto hitraceCapture = [this] { this->HitraceCapture(); }; 189020a203aSopenharmony_ci ffrt::submit(hitraceCapture, {}, {}, ffrt::task_attr().name("HitraceCapture").qos(ffrt::qos_user_initiated)); 190020a203aSopenharmony_ci 191020a203aSopenharmony_ci DumpCapture(fd); 192020a203aSopenharmony_ci auto end = ActiveKeyEvent::SystemTimeMillisecond(); 193020a203aSopenharmony_ci std::string totalTime = "\n\nCatcher log total time is " + std::to_string(end - sysStart) + "ms\n"; 194020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, totalTime); 195020a203aSopenharmony_ci close(fd); 196020a203aSopenharmony_ci} 197020a203aSopenharmony_ci 198020a203aSopenharmony_civoid ActiveKeyEvent::CombinationKeyCallback(std::shared_ptr<MMI::KeyEvent> keyEvent) 199020a203aSopenharmony_ci{ 200020a203aSopenharmony_ci HIVIEW_LOGI("Receive CombinationKeyCallback key id: %{public}d.", keyEvent->GetId()); 201020a203aSopenharmony_ci uint64_t now = (uint64_t)ActiveKeyEvent::SystemTimeMillisecond(); 202020a203aSopenharmony_ci const uint64_t interval = 10000; 203020a203aSopenharmony_ci if (now - triggeringTime_ < interval) { 204020a203aSopenharmony_ci return; 205020a203aSopenharmony_ci } 206020a203aSopenharmony_ci triggeringTime_ = now; 207020a203aSopenharmony_ci auto combinationKeyHandle = [this, keyEvent] { this->CombinationKeyHandle(keyEvent); }; 208020a203aSopenharmony_ci ffrt::submit(combinationKeyHandle, {}, {}, 209020a203aSopenharmony_ci ffrt::task_attr().name("ActiveKeyEvent").qos(ffrt::qos_user_initiated)); 210020a203aSopenharmony_ci} 211020a203aSopenharmony_ci} // namespace HiviewDFX 212020a203aSopenharmony_ci} // namespace OHOS