1 /*
2 * Copyright (c) 2022 Chipsea Technologies (Shenzhen) Corp., 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 "medical_sensor_dump.h"
17
18 #include <cinttypes>
19 #include <ctime>
20 #include <queue>
21
22 #include "medical_log_domain.h"
23 #include "medical_errors.h"
24
25 namespace OHOS {
26 namespace Sensors {
27 using namespace OHOS::HiviewDFX;
28
29 enum class DumpDataSizeType {
30 PPG_DATA_SIZE = 400,
31 COMMON_DATA_SIZE = 1,
32 };
33
34 namespace {
35 constexpr HiLogLabel LABEL = { LOG_CORE, MedicalSensorLogDomain::MEDICAL_SENSOR_SERVICE, "MedicalSensorDump" };
36 constexpr uint32_t MAX_DUMP_DATA_SIZE = 10;
37 constexpr uint32_t MS_NS = 1000000;
38 constexpr uint32_t PPG = 256;
39 constexpr int32_t MAX_DMUP_PARAM = 2;
40 } // namespace
41
42 std::unordered_map<uint32_t, std::string> MedicalSensorDump::sensorMap_ = {
43 { PPG, "PPG" },
44 };
45
DumpSensorHelp(int32_t fd,const std::vector<std::u16string> & args)46 bool MedicalSensorDump::DumpSensorHelp(int32_t fd, const std::vector<std::u16string> &args)
47 {
48 if ((args.empty()) || (args[0].compare(u"-h") != 0)) {
49 HiLog::Error(LABEL, "%{public}s args cannot be empty or invalid", __func__);
50 return false;
51 }
52 DumpHelp(fd);
53 return true;
54 }
55
DumpHelp(int32_t fd)56 void MedicalSensorDump::DumpHelp(int32_t fd)
57 {
58 dprintf(fd, "Usage:\n");
59 dprintf(fd, " -h: dump help\n");
60 dprintf(fd, " -l: dump the sensor list\n");
61 dprintf(fd, " -c: dump the sensor data channel info\n");
62 dprintf(fd, " -o: dump the opening sensors\n");
63 dprintf(fd, " -d: dump the last 10 packages sensor data\n");
64 }
65
DumpSensorList(int32_t fd,const std::vector<MedicalSensor> & sensors,const std::vector<std::u16string> & args)66 bool MedicalSensorDump::DumpSensorList(int32_t fd,
67 const std::vector<MedicalSensor> &sensors, const std::vector<std::u16string> &args)
68 {
69 if ((args.empty()) || (args[0].compare(u"-l") != 0)) {
70 HiLog::Error(LABEL, "%{public}s args cannot be empty or invalid", __func__);
71 return false;
72 }
73 DumpCurrentTime(fd);
74 dprintf(fd, "Total sensor:%d, MedicalSensor list:\n", int32_t { sensors.size() });
75 for (const auto &sensor : sensors) {
76 auto sensorId = sensor.GetSensorId();
77 dprintf(fd,
78 "sensorId:%8u | sensorType:%s | name:%s | vendor:%s | maxRange:%f | fifoMaxEventCount:%d "
79 "| minSamplePeriodNs:%lld | maxSamplePeriodNs:%lld\n",
80 sensorId, sensorMap_[sensorId].c_str(), sensor.GetName().c_str(), sensor.GetVendor().c_str(),
81 sensor.GetMaxRange(), sensor.GetFifoMaxEventCount(), (long long) { sensor.GetMinSamplePeriodNs() },
82 (long long) { sensor.GetMaxSamplePeriodNs() });
83 }
84 return true;
85 }
86
DumpSensorChannel(int32_t fd,ClientInfo & clientInfo,const std::vector<std::u16string> & args)87 bool MedicalSensorDump::DumpSensorChannel(int32_t fd, ClientInfo &clientInfo, const std::vector<std::u16string> &args)
88 {
89 if ((args.empty()) || (args[0].compare(u"-c") != 0)) {
90 HiLog::Error(LABEL, "%{public}s args cannot be empty or invalid", __func__);
91 return false;
92 }
93 DumpCurrentTime(fd);
94 dprintf(fd, "MedicalSensor channel info:\n");
95 std::vector<MedicalSensorChannelInfo> channelInfo;
96 clientInfo.GetSensorChannelInfo(channelInfo);
97 for (const auto &channel : channelInfo) {
98 auto sensorId = channel.GetSensorId();
99 std::string cmds("");
100 auto cmdList = channel.GetCmdType();
101 for (auto cmd : cmdList) {
102 cmds += (std::to_string(cmd) + " ");
103 }
104 dprintf(fd,
105 "uid:%d | packageName:%s | sensorId:%8u | sensorType:%s | samplingPeriodNs:%d "
106 "| fifoCount:%u | cmdType:%s\n",
107 channel.GetUid(), channel.GetPackageName().c_str(), sensorId, sensorMap_[sensorId].c_str(),
108 int32_t { channel.GetSamplingPeriodNs() }, channel.GetFifoCount(), cmds.c_str());
109 }
110 return true;
111 }
112
DumpOpeningSensor(int32_t fd,const std::vector<MedicalSensor> & sensors,ClientInfo & clientInfo,const std::vector<std::u16string> & args)113 bool MedicalSensorDump::DumpOpeningSensor(int32_t fd, const std::vector<MedicalSensor> &sensors,
114 ClientInfo &clientInfo, const std::vector<std::u16string> &args)
115 {
116 if ((args.empty()) || (args[0].compare(u"-o") != 0)) {
117 HiLog::Error(LABEL, "%{public}s args cannot be empty or invalid", __func__);
118 return false;
119 }
120 DumpCurrentTime(fd);
121 dprintf(fd, "Opening sensors:\n");
122 for (const auto &sensor : sensors) {
123 uint32_t sensorId = sensor.GetSensorId();
124 if (clientInfo.GetSensorState(sensorId) == SENSOR_ENABLED) {
125 dprintf(fd, "sensorId: %8u | sensorType: %s\n", sensorId, sensorMap_[sensorId].c_str());
126 }
127 }
128 return true;
129 }
130
DumpSensorData(int32_t fd,ClientInfo & clientInfo,const std::vector<std::u16string> & args)131 bool MedicalSensorDump::DumpSensorData(int32_t fd, ClientInfo &clientInfo, const std::vector<std::u16string> &args)
132 {
133 if ((args.empty()) || (args[0].compare(u"-d") != 0)) {
134 HiLog::Error(LABEL, "%{public}s args cannot be empty or invalid", __func__);
135 return false;
136 }
137 dprintf(fd, "Last 10 packages sensor data:\n");
138 auto dataMap = clientInfo.GetDataQueue();
139 int32_t j = 0;
140 for (auto &sensorData : dataMap) {
141 uint32_t sensorId = sensorData.first;
142 dprintf(fd, "sensorId: %8u | sensorType: %s:\n", sensorId, sensorMap_[sensorId].c_str());
143 for (uint32_t i = 0; i < MAX_DUMP_DATA_SIZE && (!sensorData.second.empty()); i++) {
144 auto data = sensorData.second.front();
145 sensorData.second.pop();
146 timespec time = { 0, 0 };
147 tm *timeinfo = localtime(&(time.tv_sec));
148 if (timeinfo == nullptr) {
149 HiLog::Error(LABEL, "%{public}s timeinfo cannot be null", __func__);
150 return false;
151 }
152 dprintf(fd, " %2d (ts=%.9f, time=%02d:%02d:%02d.%03d) | data:%s", ++j, data.timestamp / 1e9,
153 timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, int32_t { (time.tv_nsec / MS_NS) },
154 GetDataBySensorId(sensorId, data).c_str());
155 }
156 }
157 return true;
158 }
159
DumpCurrentTime(int32_t fd)160 void MedicalSensorDump::DumpCurrentTime(int32_t fd)
161 {
162 timespec curTime = { 0, 0 };
163 clock_gettime(CLOCK_REALTIME, &curTime);
164 tm *timeinfo = localtime(&(curTime.tv_sec));
165 if (timeinfo == nullptr) {
166 HiLog::Error(LABEL, "%{public}s timeinfo cannot be null", __func__);
167 return;
168 }
169 dprintf(fd, "Current time: %02d:%02d:%02d.%03d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
170 int32_t { (curTime.tv_nsec / MS_NS) });
171 }
172
DataSizeBySensorId(uint32_t sensorId)173 int32_t MedicalSensorDump::DataSizeBySensorId(uint32_t sensorId)
174 {
175 switch (sensorId) {
176 case PPG:
177 return static_cast<int32_t>(DumpDataSizeType::PPG_DATA_SIZE);
178 default:
179 return static_cast<int32_t>(DumpDataSizeType::COMMON_DATA_SIZE);
180 }
181 }
182
GetDataBySensorId(uint32_t sensorId,struct SensorEvent & sensorData)183 std::string MedicalSensorDump::GetDataBySensorId(uint32_t sensorId, struct SensorEvent &sensorData)
184 {
185 HiLog::Debug(LABEL, "%{public}s sensorId: %{public}u", __func__, sensorId);
186 std::string buffer;
187 int32_t dataLen = DataSizeBySensorId(sensorId);
188 for (int32_t i = 0; i < dataLen; ++i) {
189 buffer.append(std::to_string(sensorData.data[i])).append(",");
190 }
191 buffer.append("\n");
192 return buffer;
193 }
194
Dump(int32_t fd,const std::vector<std::u16string> & args,std::vector<MedicalSensor> & sensors,ClientInfo & clientInfo)195 int32_t MedicalSensorDump::Dump(int32_t fd, const std::vector<std::u16string> &args,
196 std::vector<MedicalSensor> &sensors, ClientInfo &clientInfo)
197 {
198 HiLog::Info(LABEL, "%{public}s begin", __func__);
199
200 if ((args.empty()) || (args[0].size() != MAX_DMUP_PARAM)) {
201 HiLog::Error(LABEL, "%{public}s param cannot be empty or the length is not 2", __func__);
202 dprintf(fd, "cmd param number is not equal to 2\n");
203 DumpHelp(fd);
204 return DUMP_PARAM_ERR;
205 }
206 bool helpRet = DumpSensorHelp(fd, args);
207 bool listRet = DumpSensorList(fd, sensors, args);
208 bool channelRet = DumpSensorChannel(fd, clientInfo, args);
209 bool openRet = DumpOpeningSensor(fd, sensors, clientInfo, args);
210 bool dataRet = DumpSensorData(fd, clientInfo, args);
211 bool total = helpRet + listRet + channelRet + openRet + dataRet;
212 if (!total) {
213 dprintf(fd, "cmd param is error\n");
214 DumpHelp(fd);
215 return DUMP_PARAM_ERR;
216 }
217 HiLog::Info(LABEL, "%{public}s end", __func__);
218 return ERR_OK;
219 }
220 } // namespace Sensors
221 } // namespace OHOS
222