1/*
2 * Copyright (c) 2024 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_hdi_dump.h"
17#include "osal_mem.h"
18#include <securec.h>
19#include <unordered_map>
20#include "sensor_uhdf_log.h"
21
22#define HDF_LOG_TAG uhdf_sensor_hdi_dump
23
24constexpr int32_t GET_SENSORINFO = 0;
25constexpr int32_t DATA_LEN = 256;
26
27namespace OHOS {
28namespace HDI {
29namespace Sensor {
30namespace V2_0 {
31
32static const char *SENSOR_HELP =
33    " Sensor manager dump options:\n"
34    "     -h: [sensor command help]\n"
35    "     -l: [show sensor list]\n"
36    "     -d: [The data information is displayed 10 times]\n"
37    "     -c: [show sensor client information]\n";
38
39SensorHdiDump::SensorHdiDump()
40{}
41
42SensorHdiDump::~SensorHdiDump()
43{}
44
45int32_t SensorHdiDump::SensorShowList(struct HdfSBuf *reply)
46{
47    std::vector<HdfSensorInformation> sensorInfoList;
48
49    SensorClientsManager::GetInstance()->CopySensorInfo(sensorInfoList, GET_SENSORINFO);
50
51    if (sensorInfoList.empty()) {
52        HDF_LOGE("%{public}s: no sensor info in list", __func__);
53        return HDF_FAILURE;
54    }
55
56    for (const auto &it : sensorInfoList) {
57        std::string st = {0};
58        st = "sensorName:  " + it.sensorName + "\n" +
59             "sensorId:  " + std::to_string(it.sensorId) + "\n" +
60             "sensorTypeId:  " + std::to_string(it.sensorTypeId) + "\n" +
61             "maxRange:  " + std::to_string(it.maxRange) + "\n" +
62             "accuracy:  " + std::to_string(it.accuracy) + "\n" +
63             "power:  " + std::to_string(it.power) + "\n" +
64             "minDelay:  " + std::to_string(it.minDelay) + "\n" +
65             "maxDelay:  " + std::to_string(it.maxDelay) + "\n" +
66             "fifoMaxEventCount:  " + std::to_string(it.fifoMaxEventCount) + "\n" +
67             "============================================\n";
68            (void)HdfSbufWriteString(reply, st.c_str());
69    }
70    return HDF_SUCCESS;
71}
72
73std::string SensorHdiDump::SensorInfoDataToString(const float *data,
74                                                  const int64_t timesTamp,
75                                                  const int32_t dataDimension,
76                                                  const int32_t sensorId)
77{
78    std::string dataStr = {0};
79    std::string st = {0};
80    char arrayStr[DATA_LEN] = {0};
81
82    for (int32_t i = 0; i < dataDimension; i++) {
83        if (sprintf_s(arrayStr + strlen(arrayStr), DATA_LEN, "[%f]", data[i]) < 0) {
84            HDF_LOGE("%{public}s: sprintf_s failed", __func__);
85            return st;
86        }
87    }
88
89    dataStr = arrayStr;
90    st = "sensor id: " + std::to_string(sensorId) + ", ts = " +
91        std::to_string(timesTamp / 1e9) + ", data = " + dataStr + "\n";
92
93    return st;
94}
95
96int32_t SensorHdiDump::ShowData(const float *data,
97                                const int64_t timesTamp,
98                                const int32_t dataDimension,
99                                const int32_t sensorId,
100                                struct HdfSBuf *reply)
101{
102    std::string sensorInfoData = {0};
103
104    switch (dataDimension) {
105        case MEM_X:
106        case MEM_XY:
107        case MEM_XYZ:
108        case MEM_UNCALIBRATED:
109        case MEM_POSTURE:
110        case MEM_SPE_RGB:
111            sensorInfoData = SensorInfoDataToString(data, timesTamp, dataDimension, sensorId);
112            break;
113        default:
114            HDF_LOGE("%{public}s: unsupported dimension, dimension is %{public}d", __func__, dataDimension);
115            break;
116    }
117
118    if (sensorInfoData.empty()) {
119        HDF_LOGE("%{public}s: sensor infomation data is empty!", __func__);
120        return HDF_FAILURE;
121    }
122
123    (void)HdfSbufWriteString(reply, sensorInfoData.c_str());
124    return HDF_SUCCESS;
125}
126
127int32_t SensorHdiDump::SensorShowData(struct HdfSBuf *reply)
128{
129    struct SensorsDataPack eventDumpList;
130    uint8_t *eventData = nullptr;
131
132    SensorClientsManager::GetInstance()->GetEventData(eventDumpList);
133
134    (void)HdfSbufWriteString(reply, "============== The last 10 data records ==============\n");
135
136    for (int32_t i = 0; i < eventDumpList.count; i++) {
137        int32_t index = static_cast<const uint32_t>(eventDumpList.pos + i) < MAX_DUMP_DATA_SIZE ?
138            (eventDumpList.pos + i) : (eventDumpList.pos + i - MAX_DUMP_DATA_SIZE);
139        uint32_t dataLen = eventDumpList.listDumpArray[index].dataLen;
140        eventData = static_cast<uint8_t*>(OsalMemCalloc(dataLen));
141        if (eventData == nullptr) {
142            HDF_LOGE("%{public}s: malloc failed!", __func__);
143            return HDF_FAILURE;
144        }
145
146        std::copy(eventDumpList.listDumpArray[index].data.begin(),
147                  eventDumpList.listDumpArray[index].data.end(), eventData);
148        float *data = reinterpret_cast<float*>(eventData);
149
150        int32_t dataDimension = static_cast<int32_t>(dataLen / sizeof(float));
151
152        int32_t ret = ShowData(data, eventDumpList.listDumpArray[index].timestamp, dataDimension,
153                               eventDumpList.listDumpArray[index].sensorId, reply);
154        if (ret != HDF_SUCCESS) {
155            OsalMemFree(eventData);
156            HDF_LOGE("%{public}s: print sensor infomation data failed!", __func__);
157            return HDF_FAILURE;
158        }
159
160        OsalMemFree(eventData);
161        eventData = nullptr;
162    }
163
164    return HDF_SUCCESS;
165}
166
167int32_t SensorHdiDump::SensorShowClient(struct HdfSBuf *reply)
168{
169    std::unordered_map<int, SensorClientInfo> sensorClientInfoMap;
170    if (!SensorClientsManager::GetInstance()->GetClients(HDF_TRADITIONAL_SENSOR_TYPE, sensorClientInfoMap)) {
171        HDF_LOGD("%{public}s groupId %{public}d is not used by anyone", __func__, HDF_TRADITIONAL_SENSOR_TYPE);
172        return HDF_FAILURE;
173    }
174    std::unordered_map<int32_t, struct BestSensorConfig> bestSensorConfigMap;
175    (void)SensorClientsManager::GetInstance()->GetBestSensorConfigMap(bestSensorConfigMap);
176    std::unordered_map<int, std::set<int>> sensorEnabled = SensorClientsManager::GetInstance()->GetSensorUsed();
177    (void)HdfSbufWriteString(reply, "============== all clients information ==============\n\n");
178    std::string sensorInfoData = "";
179    sensorInfoData += "bestSensorConfigMap={\n";
180    for (const auto &entry2 : bestSensorConfigMap) {
181        auto sensorId = entry2.first;
182        auto bestSensorConfig = entry2.second;
183        sensorInfoData += "{sensorId=" + std::to_string(sensorId) + ",";
184        sensorInfoData += "bestSensorConfig={";
185        sensorInfoData += "samplingInterval=" + std::to_string(bestSensorConfig.samplingInterval) + ",";
186        sensorInfoData += "reportInterval=" + std::to_string(bestSensorConfig.reportInterval);
187        sensorInfoData += "}}\n";
188    }
189    sensorInfoData += "}\n\n";
190    for (const auto &entry : sensorClientInfoMap) {
191        auto serviceId = entry.first;
192        auto sensorClientInfo = entry.second;
193        sensorInfoData += "serviceId=" + std::to_string(serviceId) + " ";
194        sensorInfoData += "sensorConfigMap_={\n";
195        for (const auto &entry2 : sensorClientInfo.sensorConfigMap_) {
196            auto sensorId = entry2.first;
197            auto sensorConfig = entry2.second;
198            sensorInfoData += "{sensorId=" + std::to_string(sensorId) + ",";
199            sensorInfoData += "sensorConfig={";
200            sensorInfoData += "samplingInterval=" + std::to_string(sensorConfig.samplingInterval) + ",";
201            sensorInfoData += "reportInterval=" + std::to_string(sensorConfig.reportInterval) + ",";
202            sensorInfoData += "curCount/periodCount=" + std::to_string(sensorClientInfo.curCountMap_[sensorId]) + "/" +
203                    std::to_string(sensorClientInfo.periodCountMap_[sensorId]) + ",";
204            if (sensorEnabled.find(sensorId) != sensorEnabled.end() &&
205                sensorEnabled.find(sensorId)->second.find(serviceId) != sensorEnabled.find(sensorId)->second.end()) {
206                sensorInfoData += "enable";
207            }
208            sensorInfoData += "}}\n";
209        }
210        sensorInfoData += "}\n\n";
211    }
212    (void)HdfSbufWriteString(reply, sensorInfoData.c_str());
213    return HDF_SUCCESS;
214}
215
216int32_t SensorHdiDump::DevHostSensorHdiDump(struct HdfSBuf *data, struct HdfSBuf *reply)
217{
218    uint32_t argc = 0;
219
220    if (data == nullptr || reply == nullptr) {
221        HDF_LOGE("%{public}s: data or reply is nullptr", __func__);
222        return HDF_FAILURE;
223    }
224
225    if (!HdfSbufReadUint32(data, &argc)) {
226        HDF_LOGE("%{public}s: read &argc failed", __func__);
227        return HDF_FAILURE;
228    }
229
230    if (argc == 0) {
231        (void)HdfSbufWriteString(reply, SENSOR_HELP);
232        return HDF_SUCCESS;
233    }
234
235    for (uint32_t i = 0; i < argc; i++) {
236        const char *value = HdfSbufReadString(data);
237        if (value == nullptr) {
238            HDF_LOGE("%{public}s: arg is invalid", __func__);
239            return HDF_FAILURE;
240        }
241        if (strcmp(value, "-h") == 0) {
242            (void)HdfSbufWriteString(reply, SENSOR_HELP);
243            return HDF_SUCCESS;
244        } else if (strcmp(value, "-l") == 0) {
245            SensorShowList(reply);
246            return HDF_SUCCESS;
247        } else if (strcmp(value, "-d") == 0) {
248            SensorShowData(reply);
249            return HDF_SUCCESS;
250        } else if (strcmp(value, "-c") == 0) {
251            SensorShowClient(reply);
252            return HDF_SUCCESS;
253        }
254    }
255
256    return HDF_SUCCESS;
257}
258
259int32_t GetSensorDump(struct HdfSBuf *data, struct HdfSBuf *reply)
260{
261    SensorHdiDump::DevHostSensorHdiDump(data, reply);
262    return HDF_SUCCESS;
263}
264
265} // V2_0
266} // Sensor
267} // HDI
268} // OHOS