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