1/* 2 * Copyright (c) 2022-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 "miscdevice_dump.h" 17 18#include <getopt.h> 19 20#include <cinttypes> 21#include <cstring> 22#include <ctime> 23#include <map> 24 25#include "securec.h" 26#include "sensors_errors.h" 27 28#undef LOG_TAG 29#define LOG_TAG "MiscdeviceDump" 30 31namespace OHOS { 32namespace Sensors { 33namespace { 34constexpr uint32_t MAX_DUMP_RECORD_SIZE = 30; 35constexpr uint32_t BASE_YEAR = 1900; 36constexpr uint32_t BASE_MON = 1; 37constexpr int32_t MAX_DUMP_PARAMETERS = 32; 38constexpr int32_t CONVERSION_RATE = 1000; 39} // namespace 40 41static std::map<int32_t, std::string> usageMap_ = { 42 {USAGE_UNKNOWN, "unknown"}, 43 {USAGE_ALARM, "alarm"}, 44 {USAGE_RING, "ring"}, 45 {USAGE_NOTIFICATION, "notification"}, 46 {USAGE_COMMUNICATION, "communication"}, 47 {USAGE_TOUCH, "touch"}, 48 {USAGE_MEDIA, "media"}, 49 {USAGE_PHYSICAL_FEEDBACK, "physicalFeedback"}, 50 {USAGE_SIMULATE_REALITY, "simulateReality"}, 51}; 52 53MiscdeviceDump::MiscdeviceDump() {} 54 55MiscdeviceDump::~MiscdeviceDump() {} 56 57void MiscdeviceDump::ParseCommand(int32_t fd, const std::vector<std::string> &args) 58{ 59 int32_t count = 0; 60 for (const auto &str : args) { 61 if (str.find("--") == 0) { 62 ++count; 63 continue; 64 } 65 if (str.find("-") == 0) { 66 count += static_cast<int32_t>(str.size()) - 1; 67 continue; 68 } 69 } 70 if (count > MAX_DUMP_PARAMETERS) { 71 MISC_HILOGE("Cmd param number not more than 32"); 72 dprintf(fd, "Cmd param number not more than 32\n"); 73 return; 74 } 75 int32_t optionIndex = 0; 76 char **argv = new (std::nothrow) char *[args.size()]; 77 CHKPV(argv); 78 if (memset_s(argv, args.size() * sizeof(char *), 0, args.size() * sizeof(char *)) != EOK) { 79 MISC_HILOGE("Call memset_s failed"); 80 delete[] argv; 81 return; 82 } 83 for (size_t i = 0; i < args.size(); ++i) { 84 argv[i] = new (std::nothrow) char[args[i].size() + 1]; 85 if (argv[i] == nullptr) { 86 MISC_HILOGE("Alloc failure"); 87 goto RELEASE_RES; 88 } 89 if (strcpy_s(argv[i], args[i].size() + 1, args[i].c_str()) != EOK) { 90 MISC_HILOGE("strcpy_s error"); 91 goto RELEASE_RES; 92 } 93 } 94 RunVibratorDump(fd, optionIndex, args, argv); 95 RELEASE_RES: 96 for (size_t i = 0; i < args.size(); ++i) { 97 if (argv[i] != nullptr) { 98 delete[] argv[i]; 99 } 100 } 101 delete[] argv; 102} 103 104void MiscdeviceDump::RunVibratorDump(int32_t fd, int32_t optionIndex, const std::vector<std::string> &args, char **argv) 105{ 106 struct option dumpOptions[] = { 107 {"record", no_argument, 0, 'r'}, 108 {"help", no_argument, 0, 'h'}, 109 {NULL, 0, 0, 0} 110 }; 111 optind = 1; 112 int32_t c; 113 while ((c = getopt_long(args.size(), argv, "rh", dumpOptions, &optionIndex)) != -1) { 114 switch (c) { 115 case 'r': { 116 DumpMiscdeviceRecord(fd); 117 break; 118 } 119 case 'h': { 120 DumpHelp(fd); 121 break; 122 } 123 default: { 124 dprintf(fd, "Unrecognized option, More info with: \"hidumper -s 3602 -a -h\"\n"); 125 break; 126 } 127 } 128 } 129} 130 131void MiscdeviceDump::DumpHelp(int32_t fd) 132{ 133 dprintf(fd, "Usage:\n"); 134 dprintf(fd, " -h, --help: dump help\n"); 135 dprintf(fd, " -r, --record: dump the list of vibrate recorded\n"); 136} 137 138void MiscdeviceDump::DumpMiscdeviceRecord(int32_t fd) 139{ 140 std::lock_guard<std::mutex> queueLock(recordQueueMutex_); 141 if (dumpQueue_.empty()) { 142 MISC_HILOGW("dumpQueue_ is empty"); 143 return; 144 } 145 size_t length = dumpQueue_.size() > MAX_DUMP_RECORD_SIZE ? MAX_DUMP_RECORD_SIZE : dumpQueue_.size(); 146 for (size_t i = 0; i < length; ++i) { 147 auto record = dumpQueue_.front(); 148 dumpQueue_.push(record); 149 dumpQueue_.pop(); 150 VibrateInfo info = record.info; 151 if (info.mode == "time") { 152 dprintf(fd, "startTime:%s | uid:%d | pid:%d | packageName:%s | duration:%d | usage:%s\n", 153 record.startTime.c_str(), info.uid, info.pid, info.packageName.c_str(), 154 info.duration, GetUsageName(info.usage).c_str()); 155 } else if (info.mode == "preset") { 156 dprintf(fd, "startTime:%s | uid:%d | pid:%d | packageName:%s | effect:%s | count:%d | usage:%s\n", 157 record.startTime.c_str(), info.uid, info.pid, info.packageName.c_str(), 158 info.effect.c_str(), info.count, GetUsageName(info.usage).c_str()); 159 } else { 160 dprintf(fd, "startTime:%s | uid:%d | pid:%d | packageName:%s | usage:%s\n", 161 record.startTime.c_str(), info.uid, info.pid, info.packageName.c_str(), 162 GetUsageName(info.usage).c_str()); 163 } 164 } 165} 166 167void MiscdeviceDump::DumpCurrentTime(std::string &startTime) 168{ 169 timespec curTime; 170 clock_gettime(CLOCK_REALTIME, &curTime); 171 struct tm *timeinfo = localtime(&(curTime.tv_sec)); 172 CHKPV(timeinfo); 173 startTime.append(std::to_string(timeinfo->tm_year + BASE_YEAR)).append("-") 174 .append(std::to_string(timeinfo->tm_mon + BASE_MON)).append("-").append(std::to_string(timeinfo->tm_mday)) 175 .append(" ").append(std::to_string(timeinfo->tm_hour)).append(":").append(std::to_string(timeinfo->tm_min)) 176 .append(":").append(std::to_string(timeinfo->tm_sec)).append(".") 177 .append(std::to_string(curTime.tv_nsec / (CONVERSION_RATE * CONVERSION_RATE))); 178} 179 180void MiscdeviceDump::UpdateRecordQueue(const VibrateRecord &record) 181{ 182 std::lock_guard<std::mutex> queueLock(recordQueueMutex_); 183 dumpQueue_.push(record); 184 if (dumpQueue_.size() > MAX_DUMP_RECORD_SIZE) { 185 dumpQueue_.pop(); 186 } 187} 188 189void MiscdeviceDump::SaveVibrateRecord(const VibrateInfo &vibrateInfo) 190{ 191 VibrateRecord record; 192 record.info = vibrateInfo; 193 DumpCurrentTime(record.startTime); 194 UpdateRecordQueue(record); 195} 196 197std::string MiscdeviceDump::GetUsageName(int32_t usage) 198{ 199 auto it = usageMap_.find(usage); 200 if (it == usageMap_.end()) { 201 MISC_HILOGE("Usage:%{public}d is invalid", usage); 202 return {}; 203 } 204 return it->second; 205} 206} // namespace Sensors 207} // namespace OHOS 208