1 /*
2 * Copyright (c) 2023 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 "hdf_dump.h"
17
18 #include "ipc_payload_statistics.h"
19
20 #include "file_ex.h"
21 #include "string_ex.h"
22 #include "unistd.h"
23
24 #include "hdf_base.h"
25 #include "hdf_dump_reg.h"
26 #include "hdf_core_log.h"
27 #include "hdf_sbuf.h"
28 #include "securec.h"
29
30 #define HDF_LOG_TAG hdf_dump
31
32 using namespace OHOS;
33
34 static DevHostDumpFunc g_dump = nullptr;
35
36 const char *HDF_DUMP_SUCCESS_STR = " success\n";
37 const char *HDF_DUMP_FAIL_STR = " fail\n";
38
39 // The maximum parameter is the parameter sent to the host, including public(num=2) and private(mux_num=20) parameters
40 static constexpr int32_t MAX_PARA_NUM = 22;
41
HdfDumpIpcStatStart(std::string & result)42 static void HdfDumpIpcStatStart(std::string& result)
43 {
44 result = std::string("HdfDumpIpcStatStart pid:") + std::to_string(getpid());
45 bool ret = IPCPayloadStatistics::StartStatistics();
46 result += ret ? HDF_DUMP_SUCCESS_STR : HDF_DUMP_FAIL_STR;
47 return;
48 }
49
HdfDumpIpcStatStop(std::string & result)50 static void HdfDumpIpcStatStop(std::string& result)
51 {
52 result = std::string("HdfDumpIpcStatStop pid:") + std::to_string(getpid());
53 bool ret = IPCPayloadStatistics::StopStatistics();
54 result += ret ? HDF_DUMP_SUCCESS_STR : HDF_DUMP_FAIL_STR;
55 return;
56 }
57
HdfDumpIpcStatGet(std::string & result)58 static void HdfDumpIpcStatGet(std::string& result)
59 {
60 result += "********************************GlobalStatisticsInfo********************************";
61 result += "\nCurrentPid:";
62 result += std::to_string(getpid());
63 result += "\nTotalCount:";
64 result += std::to_string(IPCPayloadStatistics::GetTotalCount());
65 result += "\nTotalTimeCost:";
66 result += std::to_string(IPCPayloadStatistics::GetTotalCost());
67
68 std::vector<int32_t> pids;
69 pids = IPCPayloadStatistics::GetPids();
70 for (unsigned int i = 0; i < pids.size(); i++) {
71 int32_t pid = pids[i];
72 result += "\n--------------------------------ProcessStatisticsInfo-------------------------------";
73 result += "\nCallingPid:";
74 result += std::to_string(pid);
75 result += "\nCallingPidTotalCount:";
76 result += std::to_string(IPCPayloadStatistics::GetCount(pid));
77 result += "\nCallingPidTotalTimeCost:";
78 result += std::to_string(IPCPayloadStatistics::GetCost(pid));
79
80 std::vector<IPCInterfaceInfo> intfs;
81 intfs = IPCPayloadStatistics::GetDescriptorCodes(pid);
82 for (unsigned int j = 0; j < intfs.size(); j++) {
83 IPCInterfaceInfo intf = intfs[j];
84 result += "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~InterfaceStatisticsInfo~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
85 result += "\nDescriptorCode:";
86 result += Str16ToStr8(intf.desc) + std::string("_") + std::to_string(intf.code);
87 result += "\nDescriptorCodeCount:";
88 result += std::to_string(
89 IPCPayloadStatistics::GetDescriptorCodeCount(pid, intf.desc, intf.code));
90
91 result += "\nDescriptorCodeTimeCost:";
92 result += "\nTotal:";
93 result += std::to_string(
94 IPCPayloadStatistics::GetDescriptorCodeCost(pid, intf.desc, intf.code).totalCost);
95 result += " | Max:";
96 result += std::to_string(
97 IPCPayloadStatistics::GetDescriptorCodeCost(pid, intf.desc, intf.code).maxCost);
98 result += " | Min:";
99 result += std::to_string(
100 IPCPayloadStatistics::GetDescriptorCodeCost(pid, intf.desc, intf.code).minCost);
101 result += " | Avg:";
102 result += std::to_string(
103 IPCPayloadStatistics::GetDescriptorCodeCost(pid, intf.desc, intf.code).averCost);
104 result += "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
105 }
106 result += "\n------------------------------------------------------------------------------------";
107 }
108 result += "\n************************************************************************************\n";
109
110 return;
111 }
112
HdfDumpIpcStat(int32_t fd,const char * cmd)113 void HdfDumpIpcStat(int32_t fd, const char *cmd)
114 {
115 if (fd < 0) {
116 HDF_LOGE("invalid fd %{public}d", fd);
117 return;
118 }
119
120 if (cmd == nullptr) {
121 HDF_LOGE("%{public}s cmd is null", __func__);
122 return;
123 }
124
125 std::string result;
126 HDF_LOGI("%{public}s %{public}d", cmd, fd);
127 if (strcmp(cmd, "--start-stat") == 0) {
128 HdfDumpIpcStatStart(result);
129 } else if (strcmp(cmd, "--stop-stat") == 0) {
130 HdfDumpIpcStatStop(result);
131 } else if (strcmp(cmd, "--stat") == 0) {
132 HdfDumpIpcStatGet(result);
133 } else {
134 HDF_LOGE("%{public}s invalid param", __func__);
135 return;
136 }
137
138 if (!OHOS::SaveStringToFd(fd, result)) {
139 HDF_LOGE("%{public}s SaveStringToFd failed", __func__);
140 }
141
142 return;
143 }
144
HdfRegisterDumpFunc(DevHostDumpFunc dump)145 void HdfRegisterDumpFunc(DevHostDumpFunc dump)
146 {
147 g_dump = dump;
148 }
149
HdfDump(int32_t fd,const std::vector<std::u16string> & args)150 int32_t HdfDump(int32_t fd, const std::vector<std::u16string> &args)
151 {
152 if (g_dump == nullptr || fd < 0) {
153 HDF_LOGE("%{public}s g_dump fd:%{public}d", __func__, fd);
154 return HDF_FAILURE;
155 }
156
157 uint32_t argv = args.size();
158 HDF_LOGI("%{public}s argv:%{public}u", __func__, argv);
159
160 if (argv > MAX_PARA_NUM) {
161 HDF_LOGE("%{public}s argv %{public}u is invalid", __func__, argv);
162 return HDF_FAILURE;
163 }
164
165 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
166 if (data == nullptr) {
167 return HDF_FAILURE;
168 }
169
170 int32_t ret = HDF_SUCCESS;
171 std::string result;
172 const char *value = nullptr;
173
174 struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
175 if (reply == nullptr) {
176 goto FINISHED;
177 }
178
179 if (!HdfSbufWriteFileDescriptor(data, fd)) {
180 goto FINISHED;
181 }
182
183 if (!HdfSbufWriteUint32(data, argv)) {
184 goto FINISHED;
185 }
186
187 // Convert vector to sbuf structure
188 for (uint32_t i = 0; i < argv; i++) {
189 HDF_LOGI("%{public}s para:%{public}s", __func__, OHOS::Str16ToStr8(args.at(i)).data());
190 if (!HdfSbufWriteString(data, OHOS::Str16ToStr8(args.at(i)).data())) {
191 goto FINISHED;
192 }
193 }
194
195 (void)g_dump(data, reply);
196
197 value = HdfSbufReadString(reply);
198 while (value != nullptr) {
199 HDF_LOGI("%{public}s reply:%{public}s", __func__, value);
200 result.append(value);
201 value = HdfSbufReadString(reply);
202 }
203
204 if (!OHOS::SaveStringToFd(fd, result)) {
205 ret = HDF_FAILURE;
206 }
207
208 FINISHED:
209 HdfSbufRecycle(data);
210 HdfSbufRecycle(reply);
211 return ret;
212 }