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 32namespace OHOS { 33namespace Sensors { 34using namespace OHOS::HiviewDFX; 35namespace { 36constexpr int32_t MAX_DUMP_PARAMETERS = 32; 37#ifdef BUILD_VARIANT_ENG 38constexpr uint32_t MAX_DUMP_DATA_SIZE = 10; 39#endif // BUILD_VARIANT_ENG 40constexpr uint32_t MS_NS = 1000000; 41 42enum { 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 54std::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 93void 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 139void 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 188void 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 200bool 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 219bool 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 239bool 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 257bool 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 284void 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 294int32_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 329std::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