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 #include "collect_device_client.h"
16
17 #include <cstring>
18 #include <iostream>
19 #include <memory>
20 #include <vector>
21
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include "hiview_logger.h"
28 #include "securec.h"
29
30 #define UNIFIED_COLLECTION_DEVICE "/dev/ucollection"
31 namespace OHOS {
32 namespace HiviewDFX {
33 DEFINE_LOG_TAG("UDeviceCli");
34 namespace {
35 constexpr int PID_ALL = 0;
36 constexpr unsigned int PROCESS_ONLY_ONE_COUNT = 1;
37 constexpr unsigned int ADD_COUNT = 30;
38 }
39
CollectDeviceClient()40 CollectDeviceClient::CollectDeviceClient(): fd_(-1)
41 {}
42
~CollectDeviceClient()43 CollectDeviceClient::~CollectDeviceClient()
44 {
45 if (fd_ > 0) {
46 close(fd_);
47 }
48 }
49
GetDeviceFd(bool readOnly)50 int CollectDeviceClient::GetDeviceFd(bool readOnly)
51 {
52 int f = 0;
53 if (readOnly) {
54 f = open(UNIFIED_COLLECTION_DEVICE, O_RDONLY);
55 } else {
56 f = open(UNIFIED_COLLECTION_DEVICE, O_WRONLY);
57 }
58
59 if (f < 0) {
60 HIVIEW_LOGE("Cannot open file=%{public}s, readOnly=%{public}d", UNIFIED_COLLECTION_DEVICE, readOnly);
61 return -1;
62 }
63 HIVIEW_LOGD("open ucollection device readOnly=%{public}d successful", readOnly);
64 return f;
65 }
66
Open()67 int CollectDeviceClient::Open()
68 {
69 fd_ = GetDeviceFd(true);
70 return (fd_ > 0) ? 0 : -1;
71 }
72
GetProcessCount()73 unsigned int CollectDeviceClient::GetProcessCount()
74 {
75 HIVIEW_LOGD("send IOCTRL_COLLECT_PROC_COUNT");
76 unsigned int processCount = 0;
77 int ret = ioctl(fd_, IOCTRL_COLLECT_PROC_COUNT, &processCount);
78 if (ret < 0) {
79 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_PROC_COUNT, ret=%{public}d", ret);
80 return 0;
81 }
82 return processCount;
83 }
84
FetchProcessCpuData()85 std::shared_ptr<ProcessCpuData> CollectDeviceClient::FetchProcessCpuData()
86 {
87 unsigned int processCount = GetProcessCount();
88 HIVIEW_LOGD("send IOCTRL_COLLECT_ALL_PROC_CPU");
89 std::shared_ptr<ProcessCpuData> data = std::make_shared<ProcessCpuData>(IOCTRL_COLLECT_ALL_PROC_CPU, PID_ALL,
90 processCount + ADD_COUNT);
91 int ret = ioctl(fd_, IOCTRL_COLLECT_ALL_PROC_CPU, data->entry_);
92 if (ret < 0) {
93 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_ALL_PROC_CPU ret=%{public}d", ret);
94 return data;
95 }
96 return data;
97 }
98
FetchProcessCpuData(int pid)99 std::shared_ptr<ProcessCpuData> CollectDeviceClient::FetchProcessCpuData(int pid)
100 {
101 HIVIEW_LOGD("send IOCTRL_COLLECT_THE_PROC_CPU");
102 std::shared_ptr<ProcessCpuData> data = std::make_shared<ProcessCpuData>(IOCTRL_COLLECT_THE_PROC_CPU, pid,
103 PROCESS_ONLY_ONE_COUNT);
104 int ret = ioctl(fd_, IOCTRL_COLLECT_THE_PROC_CPU, data->entry_);
105 if (ret < 0) {
106 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_THE_PROC_CPU ret=%{public}d", ret);
107 return data;
108 }
109 return data;
110 }
111
GetThreadCount(int pid)112 unsigned int CollectDeviceClient::GetThreadCount(int pid)
113 {
114 HIVIEW_LOGD("send IOCTRL_COLLECT_THREAD_COUNT");
115 struct ucollection_process_thread_count threadCount {pid, 0};
116 int ret = ioctl(fd_, IOCTRL_COLLECT_THREAD_COUNT, &threadCount);
117 if (ret < 0) {
118 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_PROC_THREAD_COUNT ret=%{public}d", ret);
119 return 0;
120 }
121 return threadCount.thread_count;
122 }
123
GetSelfThreadCount(int pid)124 unsigned int CollectDeviceClient::GetSelfThreadCount(int pid)
125 {
126 HIVIEW_LOGD("send IOCTRL_COLLECT_APP_THREAD_COUNT");
127 struct ucollection_process_thread_count threadCount {pid, 0};
128 int ret = ioctl(fd_, IOCTRL_COLLECT_APP_THREAD_COUNT, &threadCount);
129 if (ret < 0) {
130 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_APP_THREAD_COUNT ret=%{public}d", ret);
131 return 0;
132 }
133 return threadCount.thread_count;
134 }
135
FetchThreadCpuData(int pid)136 std::shared_ptr<ThreadCpuData> CollectDeviceClient::FetchThreadCpuData(int pid)
137 {
138 HIVIEW_LOGD("send IOCTRL_COLLECT_THE_THREAD");
139 unsigned int threadCount = GetThreadCount(pid);
140 if (threadCount <= 0) {
141 HIVIEW_LOGE("ioctl GetThreadCount error");
142 return nullptr;
143 }
144 auto data = std::make_shared<ThreadCpuData>(IOCTRL_COLLECT_THE_THREAD, pid, threadCount);
145 int ret = ioctl(fd_, IOCTRL_COLLECT_THE_THREAD, data->entry_);
146 if (ret < 0) {
147 HIVIEW_LOGE("ioctl FetchThreadData, ret=%{public}d", ret);
148 return data;
149 }
150 return data;
151 }
152
FetchSelfThreadCpuData(int pid)153 std::shared_ptr<ThreadCpuData> CollectDeviceClient::FetchSelfThreadCpuData(int pid)
154 {
155 HIVIEW_LOGD("send IOCTRL_COLLECT_APP_THREAD, cmd=%{public}zu", IOCTRL_COLLECT_APP_THREAD);
156 unsigned int threadCount = GetSelfThreadCount(pid);
157 if (threadCount <= 0) {
158 HIVIEW_LOGE("ioctl GetSelfThreadCount error");
159 return nullptr;
160 }
161 auto data = std::make_shared<ThreadCpuData>(IOCTRL_COLLECT_APP_THREAD, pid, threadCount);
162 int ret = ioctl(fd_, IOCTRL_COLLECT_APP_THREAD, data->entry_);
163 if (ret < 0) {
164 HIVIEW_LOGE("ioctl FetchSelfThreadCpuData, ret=%{public}d", ret);
165 return data;
166 }
167 return data;
168 }
169 } // HiviewDFX
170 } // OHOS
171