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
31 namespace OHOS {
32 namespace Sensors {
33 namespace {
34 constexpr uint32_t MAX_DUMP_RECORD_SIZE = 30;
35 constexpr uint32_t BASE_YEAR = 1900;
36 constexpr uint32_t BASE_MON = 1;
37 constexpr int32_t MAX_DUMP_PARAMETERS = 32;
38 constexpr int32_t CONVERSION_RATE = 1000;
39 } // namespace
40
41 static 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
MiscdeviceDump()53 MiscdeviceDump::MiscdeviceDump() {}
54
~MiscdeviceDump()55 MiscdeviceDump::~MiscdeviceDump() {}
56
ParseCommand(int32_t fd,const std::vector<std::string> & args)57 void 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
RunVibratorDump(int32_t fd,int32_t optionIndex,const std::vector<std::string> & args,char ** argv)104 void 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
DumpHelp(int32_t fd)131 void 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
DumpMiscdeviceRecord(int32_t fd)138 void 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
DumpCurrentTime(std::string & startTime)167 void 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
UpdateRecordQueue(const VibrateRecord & record)180 void 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
SaveVibrateRecord(const VibrateInfo & vibrateInfo)189 void MiscdeviceDump::SaveVibrateRecord(const VibrateInfo &vibrateInfo)
190 {
191 VibrateRecord record;
192 record.info = vibrateInfo;
193 DumpCurrentTime(record.startTime);
194 UpdateRecordQueue(record);
195 }
196
GetUsageName(int32_t usage)197 std::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