1 /*
2 * Copyright (c) 2021-2022 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 "sensor_dump.h"
17
18 #include <getopt.h>
19
20 #include <cinttypes>
21
22 #include "securec.h"
23 #include "sensor_errors.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "SensorDump"
27
28 namespace OHOS {
29 namespace Sensors {
30 using namespace OHOS::HiviewDFX;
31 namespace {
32 constexpr int32_t MAX_DUMP_PARAMETERS = 32;
33 #ifdef BUILD_VARIANT_ENG
34 constexpr uint32_t MAX_DUMP_DATA_SIZE = 10;
35 #endif // BUILD_VARIANT_ENG
36 constexpr uint32_t MS_NS = 1000000;
37
38 enum {
39 SOLITARIES_DIMENSION = 1,
40 TWO_DIMENSION = 2,
41 COMMON_DIMENSION = 3,
42 VECTOR_DIMENSION = 4,
43 UNCALIBRATED_DIMENSION = 6,
44 SEVEN_DIMENSION = 7,
45 POSE_6DOF_DIMENSION = 15,
46 DEFAULT_DIMENSION = 16,
47 };
48 } // namespace
49
50 std::unordered_map<int32_t, std::string> SensorDump::sensorMap_ = {
51 { SENSOR_TYPE_ID_ACCELEROMETER, "ACCELEROMETER" },
52 { SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED, "ACCELEROMETER UNCALIBRATED" },
53 { SENSOR_TYPE_ID_LINEAR_ACCELERATION, "LINEAR ACCELERATION" },
54 { SENSOR_TYPE_ID_GRAVITY, "GRAVITY" },
55 { SENSOR_TYPE_ID_GYROSCOPE, "GYROSCOPE" },
56 { SENSOR_TYPE_ID_CAPACITIVE, "CAPACITIVE"},
57 { SENSOR_TYPE_ID_TEMPERATURE, "TEMPERATURE"},
58 { SENSOR_TYPE_ID_GESTURE, "GESTURE"},
59 { SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED, "GYROSCOPE UNCALIBRATED" },
60 { SENSOR_TYPE_ID_SIGNIFICANT_MOTION, "SIGNIFICANT MOTION" },
61 { SENSOR_TYPE_ID_PEDOMETER_DETECTION, "PEDOMETER DETECTION" },
62 { SENSOR_TYPE_ID_PEDOMETER, "PEDOMETER" },
63 { SENSOR_TYPE_ID_AMBIENT_TEMPERATURE, "AMBIENT TEMPERATURE" },
64 { SENSOR_TYPE_ID_MAGNETIC_FIELD, "MAGNETIC FIELD" },
65 { SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED, "MAGNETIC FIELD UNCALIBRATED" },
66 { SENSOR_TYPE_ID_HUMIDITY, "HUMIDITY" },
67 { SENSOR_TYPE_ID_BAROMETER, "BAROMETER" },
68 { SENSOR_TYPE_ID_DEVICE_ORIENTATION, "DEVICE ORIENTATION" },
69 { SENSOR_TYPE_ID_ORIENTATION, "ORIENTATION" },
70 { SENSOR_TYPE_ID_ROTATION_VECTOR, "ROTATION VECTOR" },
71 { SENSOR_TYPE_ID_GAME_ROTATION_VECTOR, "GAME ROTATION VECTOR" },
72 { SENSOR_TYPE_ID_GEOMAGNETIC_ROTATION_VECTOR, "GEOMAGNETIC ROTATION VECTOR" },
73 { SENSOR_TYPE_ID_PROXIMITY, "PROXIMITY" },
74 { SENSOR_TYPE_ID_PROXIMITY1, "SECONDARY PROXIMITY" },
75 { SENSOR_TYPE_ID_AMBIENT_LIGHT, "AMBIENT LIGHT" },
76 { SENSOR_TYPE_ID_AMBIENT_LIGHT1, "SECONDARY AMBIENT LIGHT" },
77 { SENSOR_TYPE_ID_HALL, "HALL" },
78 { SENSOR_TYPE_ID_HALL_EXT, "EXTENDED HALL" },
79 { SENSOR_TYPE_ID_HEART_RATE, "HEART RATE" },
80 { SENSOR_TYPE_ID_WEAR_DETECTION, "WEAR DETECTION" },
81 { SENSOR_TYPE_ID_COLOR, "COLOR" },
82 { SENSOR_TYPE_ID_SAR, "SAR" },
83 { SENSOR_TYPE_ID_POSTURE, "POSTURE" },
84 { SENSOR_TYPE_ID_HEADPOSTURE, "HEAD POSTURE" },
85 { SENSOR_TYPE_ID_DROP_DETECTION, "DROP DETECTION" },
86 { SENSOR_TYPE_ID_RPC, "RPC" },
87 };
88
RunSensorDump(int32_t fd,int32_t optionIndex,const std::vector<std::string> & args,char ** argv)89 void SensorDump::RunSensorDump(int32_t fd, int32_t optionIndex, const std::vector<std::string> &args, char **argv)
90 {
91 struct option dumpOptions[] = {
92 {"channel", no_argument, 0, 'c'},
93 #ifdef BUILD_VARIANT_ENG
94 {"data", no_argument, 0, 'd'},
95 #endif // BUILD_VARIANT_ENG
96 {"open", no_argument, 0, 'o'},
97 {"help", no_argument, 0, 'h'},
98 {"list", no_argument, 0, 'l'},
99 {NULL, 0, 0, 0}
100 };
101 optind = 1;
102 int32_t c;
103 while ((c = getopt_long(args.size(), argv, "cdohl", dumpOptions, &optionIndex)) != -1) {
104 switch (c) {
105 case 'c': {
106 DumpSensorChannel(fd, clientInfo_);
107 break;
108 }
109 #ifdef BUILD_VARIANT_ENG
110 case 'd': {
111 DumpSensorData(fd, clientInfo_);
112 break;
113 }
114 #endif // BUILD_VARIANT_ENG
115 case 'o': {
116 DumpOpeningSensor(fd, sensors_, clientInfo_);
117 break;
118 }
119 case 'h': {
120 DumpHelp(fd);
121 break;
122 }
123 case 'l': {
124 DumpSensorList(fd, sensors_);
125 break;
126 }
127 default: {
128 dprintf(fd, "Unrecognized option, More info with: \"hidumper -s 3601 -a -h\"\n");
129 break;
130 }
131 }
132 }
133 }
134
ParseCommand(int32_t fd,const std::vector<std::string> & args,const std::vector<Sensor> & sensors,ClientInfo & clientInfo)135 void SensorDump::ParseCommand(int32_t fd, const std::vector<std::string> &args, const std::vector<Sensor> &sensors,
136 ClientInfo &clientInfo)
137 {
138 int32_t count = 0;
139 for (const auto &str : args) {
140 if (str.find("--") == 0) {
141 ++count;
142 continue;
143 }
144 if (str.find("-") == 0) {
145 count += static_cast<int32_t>(str.size()) - 1;
146 continue;
147 }
148 }
149 if (count > MAX_DUMP_PARAMETERS) {
150 SEN_HILOGE("Cmd param number not more than 32");
151 dprintf(fd, "Cmd param number not more than 32\n");
152 return;
153 }
154 int32_t optionIndex = 0;
155 char **argv = new (std::nothrow) char *[args.size()];
156 CHKPV(argv);
157 if (memset_s(argv, args.size() * sizeof(char *), 0, args.size() * sizeof(char *)) != EOK) {
158 SEN_HILOGE("memset_s failed");
159 delete[] argv;
160 return;
161 }
162 for (size_t i = 0; i < args.size(); ++i) {
163 argv[i] = new (std::nothrow) char[args[i].size() + 1];
164 if (argv[i] == nullptr) {
165 SEN_HILOGE("Alloc failure");
166 goto RELEASE_RES;
167 }
168 if (strcpy_s(argv[i], args[i].size() + 1, args[i].c_str()) != EOK) {
169 SEN_HILOGE("strcpy_s error");
170 goto RELEASE_RES;
171 }
172 }
173 sensors_ = sensors;
174 RunSensorDump(fd, optionIndex, args, argv);
175 RELEASE_RES:
176 for (size_t i = 0; i < args.size(); ++i) {
177 if (argv[i] != nullptr) {
178 delete[] argv[i];
179 }
180 }
181 delete[] argv;
182 }
183
DumpHelp(int32_t fd)184 void SensorDump::DumpHelp(int32_t fd)
185 {
186 dprintf(fd, "Usage:\n");
187 dprintf(fd, " -h, --help: dump help\n");
188 dprintf(fd, " -l, --list: dump the sensor list\n");
189 dprintf(fd, " -c, --channel: dump the sensor data channel info\n");
190 dprintf(fd, " -o, --open: dump the opening sensors\n");
191 #ifdef BUILD_VARIANT_ENG
192 dprintf(fd, " -d, --data: dump the last 10 packages sensor data\n");
193 #endif // BUILD_VARIANT_ENG
194 }
195
DumpSensorList(int32_t fd,const std::vector<Sensor> & sensors)196 bool SensorDump::DumpSensorList(int32_t fd, const std::vector<Sensor> &sensors)
197 {
198 DumpCurrentTime(fd);
199 dprintf(fd, "Total sensor:%d, Sensor list:\n", int32_t { sensors.size() });
200 for (const auto &sensor : sensors) {
201 auto sensorId = sensor.GetSensorId();
202 if (sensorMap_.find(sensorId) == sensorMap_.end()) {
203 continue;
204 }
205 dprintf(fd,
206 "sensorId:%8u | sensorType:%s | sensorName:%s | vendorName:%s | maxRange:%f"
207 "| fifoMaxEventCount:%d | minSamplePeriodNs:%" PRId64 " | maxSamplePeriodNs:%" PRId64 "\n",
208 sensorId, sensorMap_[sensorId].c_str(), sensor.GetSensorName().c_str(), sensor.GetVendorName().c_str(),
209 sensor.GetMaxRange(), sensor.GetFifoMaxEventCount(), sensor.GetMinSamplePeriodNs(),
210 sensor.GetMaxSamplePeriodNs());
211 }
212 return true;
213 }
214
DumpSensorChannel(int32_t fd,ClientInfo & clientInfo)215 bool SensorDump::DumpSensorChannel(int32_t fd, ClientInfo &clientInfo)
216 {
217 DumpCurrentTime(fd);
218 dprintf(fd, "Sensor channel info:\n");
219 std::vector<SensorChannelInfo> channelInfo;
220 clientInfo.GetSensorChannelInfo(channelInfo);
221 for (const auto &channel : channelInfo) {
222 auto sensorId = channel.GetSensorId();
223 if (sensorMap_.find(sensorId) == sensorMap_.end()) {
224 continue;
225 }
226 dprintf(fd,
227 "uid:%d | packageName:%s | sensorId:%8u | sensorType:%s | samplingPeriodNs:%" PRId64 ""
228 "| fifoCount:%u\n",
229 channel.GetUid(), channel.GetPackageName().c_str(), sensorId, sensorMap_[sensorId].c_str(),
230 channel.GetSamplingPeriodNs(), channel.GetFifoCount());
231 }
232 return true;
233 }
234
DumpOpeningSensor(int32_t fd,const std::vector<Sensor> & sensors,ClientInfo & clientInfo)235 bool SensorDump::DumpOpeningSensor(int32_t fd, const std::vector<Sensor> &sensors, ClientInfo &clientInfo)
236 {
237 DumpCurrentTime(fd);
238 dprintf(fd, "Opening sensors:\n");
239 for (const auto &sensor : sensors) {
240 int32_t sensorId = sensor.GetSensorId();
241 if (sensorMap_.find(sensorId) == sensorMap_.end()) {
242 continue;
243 }
244 if (clientInfo.GetSensorState(sensorId)) {
245 dprintf(fd, "sensorId: %8u | sensorType: %s | channelSize: %lu\n",
246 sensorId, sensorMap_[sensorId].c_str(), clientInfo.GetSensorChannel(sensorId).size());
247 }
248 }
249 return true;
250 }
251
252 #ifdef BUILD_VARIANT_ENG
DumpSensorData(int32_t fd,ClientInfo & clientInfo)253 bool SensorDump::DumpSensorData(int32_t fd, ClientInfo &clientInfo)
254 {
255 dprintf(fd, "Last 10 packages sensor data:\n");
256 auto dataMap = clientInfo.GetDumpQueue();
257 int32_t j = 0;
258 for (auto &sensorData : dataMap) {
259 int32_t sensorId = sensorData.first;
260 if (sensorMap_.find(sensorId) == sensorMap_.end()) {
261 continue;
262 }
263 dprintf(fd, "sensorId: %8u | sensorType: %s:\n", sensorId, sensorMap_[sensorId].c_str());
264 for (uint32_t i = 0; i < MAX_DUMP_DATA_SIZE && (!sensorData.second.empty()); i++) {
265 auto data = sensorData.second.front();
266 sensorData.second.pop();
267 timespec time = { 0, 0 };
268 clock_gettime(CLOCK_REALTIME, &time);
269 struct tm *timeinfo = localtime(&(time.tv_sec));
270 CHKPF(timeinfo);
271 dprintf(fd, " %2d (ts=%.9f, time=%02d:%02d:%02d.%03d) | data:%s", ++j, data.timestamp / 1e9,
272 timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, int32_t { (time.tv_nsec / MS_NS) },
273 GetDataBySensorId(sensorId, data).c_str());
274 }
275 }
276 return true;
277 }
278 #endif // BUILD_VARIANT_ENG
279
DumpCurrentTime(int32_t fd)280 void SensorDump::DumpCurrentTime(int32_t fd)
281 {
282 timespec curTime = { 0, 0 };
283 clock_gettime(CLOCK_REALTIME, &curTime);
284 struct tm *timeinfo = localtime(&(curTime.tv_sec));
285 CHKPV(timeinfo);
286 dprintf(fd, "Current time: %02d:%02d:%02d.%03d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
287 int32_t { (curTime.tv_nsec / MS_NS) });
288 }
289
GetDataDimension(int32_t sensorId)290 int32_t SensorDump::GetDataDimension(int32_t sensorId)
291 {
292 switch (sensorId) {
293 case SENSOR_TYPE_ID_BAROMETER:
294 case SENSOR_TYPE_ID_HALL:
295 case SENSOR_TYPE_ID_HALL_EXT:
296 case SENSOR_TYPE_ID_TEMPERATURE:
297 case SENSOR_TYPE_ID_PROXIMITY:
298 case SENSOR_TYPE_ID_PROXIMITY1:
299 case SENSOR_TYPE_ID_HUMIDITY:
300 case SENSOR_TYPE_ID_AMBIENT_TEMPERATURE:
301 case SENSOR_TYPE_ID_SIGNIFICANT_MOTION:
302 case SENSOR_TYPE_ID_PEDOMETER_DETECTION:
303 case SENSOR_TYPE_ID_PEDOMETER:
304 case SENSOR_TYPE_ID_HEART_RATE:
305 case SENSOR_TYPE_ID_WEAR_DETECTION:
306 case SENSOR_TYPE_ID_SAR:
307 return SOLITARIES_DIMENSION;
308 case SENSOR_TYPE_ID_COLOR:
309 return TWO_DIMENSION;
310 case SENSOR_TYPE_ID_ROTATION_VECTOR:
311 case SENSOR_TYPE_ID_HEADPOSTURE:
312 return VECTOR_DIMENSION;
313 case SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED:
314 case SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED:
315 case SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED:
316 return UNCALIBRATED_DIMENSION;
317 case SENSOR_TYPE_ID_POSTURE:
318 return SEVEN_DIMENSION;
319 default:
320 SEN_HILOGW("Unknown sensorId:%{public}d, size:%{public}d", sensorId, COMMON_DIMENSION);
321 return COMMON_DIMENSION;
322 }
323 }
324
GetDataBySensorId(int32_t sensorId,SensorData & sensorData)325 std::string SensorDump::GetDataBySensorId(int32_t sensorId, SensorData &sensorData)
326 {
327 SEN_HILOGD("sensorId:%{public}u", sensorId);
328 std::string str;
329 int32_t dataLen = GetDataDimension(sensorId);
330 if (sensorData.dataLen < sizeof(float)) {
331 SEN_HILOGE("SensorData dataLen less than float size");
332 return str;
333 }
334 auto data = reinterpret_cast<float *>(sensorData.data);
335 for (int32_t i = 0; i < dataLen; ++i) {
336 str.append(std::to_string(*data));
337 if (i != dataLen - 1) {
338 str.append(",");
339 }
340 ++data;
341 }
342 str.append("\n");
343 return str;
344 }
345 } // namespace Sensors
346 } // namespace OHOS
347