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 fdsan_close_with_tag(fd_, logLabelDomain);
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 if (fd_ < 0) {
71 return -1;
72 }
73 fdsan_exchange_owner_tag(fd_, 0, logLabelDomain);
74 return 0;
75 }
76
GetProcessCount()77 unsigned int CollectDeviceClient::GetProcessCount()
78 {
79 HIVIEW_LOGD("send IOCTRL_COLLECT_PROC_COUNT");
80 unsigned int processCount = 0;
81 int ret = ioctl(fd_, IOCTRL_COLLECT_PROC_COUNT, &processCount);
82 if (ret < 0) {
83 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_PROC_COUNT, ret=%{public}d", ret);
84 return 0;
85 }
86 return processCount;
87 }
88
FetchProcessCpuData()89 std::shared_ptr<ProcessCpuData> CollectDeviceClient::FetchProcessCpuData()
90 {
91 unsigned int processCount = GetProcessCount();
92 HIVIEW_LOGD("send IOCTRL_COLLECT_ALL_PROC_CPU");
93 std::shared_ptr<ProcessCpuData> data = std::make_shared<ProcessCpuData>(IOCTRL_COLLECT_ALL_PROC_CPU, PID_ALL,
94 processCount + ADD_COUNT);
95 int ret = ioctl(fd_, IOCTRL_COLLECT_ALL_PROC_CPU, data->entry_);
96 if (ret < 0) {
97 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_ALL_PROC_CPU ret=%{public}d", ret);
98 return data;
99 }
100 return data;
101 }
102
FetchProcessCpuData(int pid)103 std::shared_ptr<ProcessCpuData> CollectDeviceClient::FetchProcessCpuData(int pid)
104 {
105 HIVIEW_LOGD("send IOCTRL_COLLECT_THE_PROC_CPU");
106 std::shared_ptr<ProcessCpuData> data = std::make_shared<ProcessCpuData>(IOCTRL_COLLECT_THE_PROC_CPU, pid,
107 PROCESS_ONLY_ONE_COUNT);
108 int ret = ioctl(fd_, IOCTRL_COLLECT_THE_PROC_CPU, data->entry_);
109 if (ret < 0) {
110 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_THE_PROC_CPU ret=%{public}d", ret);
111 return data;
112 }
113 return data;
114 }
115
GetThreadCount(int pid)116 unsigned int CollectDeviceClient::GetThreadCount(int pid)
117 {
118 HIVIEW_LOGD("send IOCTRL_COLLECT_THREAD_COUNT");
119 struct ucollection_process_thread_count threadCount {pid, 0};
120 int ret = ioctl(fd_, IOCTRL_COLLECT_THREAD_COUNT, &threadCount);
121 if (ret < 0) {
122 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_PROC_THREAD_COUNT ret=%{public}d", ret);
123 return 0;
124 }
125 return threadCount.thread_count;
126 }
127
GetSelfThreadCount(int pid)128 unsigned int CollectDeviceClient::GetSelfThreadCount(int pid)
129 {
130 HIVIEW_LOGD("send IOCTRL_COLLECT_APP_THREAD_COUNT");
131 struct ucollection_process_thread_count threadCount {pid, 0};
132 int ret = ioctl(fd_, IOCTRL_COLLECT_APP_THREAD_COUNT, &threadCount);
133 if (ret < 0) {
134 HIVIEW_LOGE("ioctl IOCTRL_COLLECT_APP_THREAD_COUNT ret=%{public}d", ret);
135 return 0;
136 }
137 return threadCount.thread_count;
138 }
139
FetchThreadCpuData(int pid)140 std::shared_ptr<ThreadCpuData> CollectDeviceClient::FetchThreadCpuData(int pid)
141 {
142 HIVIEW_LOGD("send IOCTRL_COLLECT_THE_THREAD");
143 unsigned int threadCount = GetThreadCount(pid);
144 if (threadCount <= 0) {
145 HIVIEW_LOGE("ioctl GetThreadCount error");
146 return nullptr;
147 }
148 auto data = std::make_shared<ThreadCpuData>(IOCTRL_COLLECT_THE_THREAD, pid, threadCount);
149 int ret = ioctl(fd_, IOCTRL_COLLECT_THE_THREAD, data->entry_);
150 if (ret < 0) {
151 HIVIEW_LOGE("ioctl FetchThreadData, ret=%{public}d", ret);
152 return data;
153 }
154 return data;
155 }
156
FetchSelfThreadCpuData(int pid)157 std::shared_ptr<ThreadCpuData> CollectDeviceClient::FetchSelfThreadCpuData(int pid)
158 {
159 HIVIEW_LOGD("send IOCTRL_COLLECT_APP_THREAD, cmd=%{public}zu", IOCTRL_COLLECT_APP_THREAD);
160 unsigned int threadCount = GetSelfThreadCount(pid);
161 if (threadCount <= 0) {
162 HIVIEW_LOGE("ioctl GetSelfThreadCount error");
163 return nullptr;
164 }
165 auto data = std::make_shared<ThreadCpuData>(IOCTRL_COLLECT_APP_THREAD, pid, threadCount);
166 int ret = ioctl(fd_, IOCTRL_COLLECT_APP_THREAD, data->entry_);
167 if (ret < 0) {
168 HIVIEW_LOGE("ioctl FetchSelfThreadCpuData, ret=%{public}d", ret);
169 return data;
170 }
171 return data;
172 }
173 } // HiviewDFX
174 } // OHOS
175