1 /*
2 * Copyright (c) 2025 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 "rs_graphic_test_profiler_thread.h"
17
18 #include <securec.h>
19 #include <sys/un.h>
20 #include <unistd.h>
21
22 #include "rs_graphic_test_utils.h"
23 #ifdef RS_PROFILER_ENABLED
24 #include "rs_profiler_packet.h"
25 #endif
26
27 namespace OHOS {
28 namespace Rosen {
29 #ifdef RS_PROFILER_ENABLED
30 constexpr int64_t INIT_WAIT_TIME = 50;
31 constexpr int64_t SOCKET_REFRESH_TIME = 20;
32 constexpr int SOCKET_CONNECT_MAX_NUM = 10000;
33 const std::string RESPOND_PAUSE_AT = "PlaybackPauseAt OK";
34 const std::string RESPOND_PLAYBACK_PREPARE = "awake_frame 0";
35
~RSGraphicTestProfilerThread()36 RSGraphicTestProfilerThread::~RSGraphicTestProfilerThread()
37 {
38 Stop();
39 }
40
Start()41 void RSGraphicTestProfilerThread::Start()
42 {
43 system("param set persist.graphic.profiler.enabled 1");
44 WaitTimeout(INIT_WAIT_TIME);
45 runnig_ = true;
46 thread_ = std::thread(&RSGraphicTestProfilerThread::MainLoop, this);
47 }
48
Stop()49 void RSGraphicTestProfilerThread::Stop()
50 {
51 system("param set persist.graphic.profiler.enabled 0");
52 if (runnig_) {
53 runnig_ = false;
54 cv_.notify_all();
55 }
56 if (socket_ != -1) {
57 close(socket_);
58 socket_ = -1;
59 }
60 if (thread_.joinable()) {
61 thread_.join();
62 }
63 }
64
SendCommand(const std::string command,int outTime)65 void RSGraphicTestProfilerThread::SendCommand(const std::string command, int outTime)
66 {
67 {
68 std::unique_lock lock(queue_mutex_);
69 message_queue_.push(command);
70 }
71 if (outTime > 0) {
72 std::unique_lock lock(wait_mutex_);
73 waitReceive_ = true;
74 cv_.wait_for(lock, std::chrono::milliseconds(outTime), [&] { return !waitReceive_; });
75 }
76 }
77
MainLoop()78 void RSGraphicTestProfilerThread::MainLoop()
79 {
80 socket_ = socket(AF_UNIX, SOCK_STREAM, 0);
81 if (socket_ == -1) {
82 std::cout << "profiler socket create failed" << std::endl;
83 return;
84 }
85
86 const std::string socketName = "render_service_5050";
87 sockaddr_un address {};
88 address.sun_family = AF_UNIX;
89 address.sun_path[0] = 0;
90 ::memmove_s(address.sun_path + 1, sizeof(address.sun_path) - 1, socketName.data(), socketName.size());
91 const size_t addressSize = offsetof(sockaddr_un, sun_path) + socketName.size() + 1;
92
93 int tryNum = 1;
94 while (connect(socket_, reinterpret_cast<struct sockaddr*>(&address), addressSize) < 0) {
95 std::cout << "profiler socket connect failed, connect:" + std::to_string(tryNum) << std::endl;
96 tryNum++;
97 if (tryNum > SOCKET_CONNECT_MAX_NUM) {
98 std::cout << "profiler socket connect failed" << std::endl;
99 close(socket_);
100 socket_ = -1;
101 return;
102 }
103 }
104 std::cout << "profiler socket connect success" << std::endl;
105 runnig_ = true;
106 while (runnig_) {
107 {
108 std::unique_lock lock(queue_mutex_);
109 cv_.wait_for(lock, std::chrono::milliseconds(SOCKET_REFRESH_TIME), [this] { return !runnig_; });
110 }
111 SendMessage();
112 RecieveMessage();
113 }
114 close(socket_);
115 }
116
SendMessage()117 void RSGraphicTestProfilerThread::SendMessage()
118 {
119 std::string message;
120 {
121 std::lock_guard<std::mutex> lock(queue_mutex_);
122 if (!message_queue_.empty()) {
123 message = message_queue_.front();
124 message_queue_.pop();
125 }
126 }
127 if (message.empty()) {
128 return;
129 }
130 Packet packet(Packet::COMMAND);
131 packet.Write(message);
132 auto data = packet.Release();
133 const char* bytes = reinterpret_cast<const char*>(data.data());
134 size_t size = data.size();
135 size_t sent = 0;
136 while (sent < size) {
137 const ssize_t sentBytes = send(socket_, bytes, size - sent, 0);
138 if ((sentBytes <= 0) && (errno != EINTR)) {
139 std::cout << "profiler socket send failed:" + std::to_string(sentBytes) << std::endl;
140 return;
141 }
142 auto actualSentBytes = static_cast<size_t>(sentBytes);
143 sent += actualSentBytes;
144 bytes += actualSentBytes;
145 }
146 }
147
RecieveMessage()148 void RSGraphicTestProfilerThread::RecieveMessage()
149 {
150 Packet packet { Packet::UNKNOWN };
151 auto wannaReceive = Packet::HEADER_SIZE;
152 RecieveHeader(packet.Begin(), wannaReceive);
153 if (wannaReceive == 0) {
154 std::cout << "profiler socket recieve header failed" << std::endl;
155 return;
156 }
157 const size_t size = packet.GetPayloadLength();
158 if (size == 0) {
159 return;
160 }
161
162 std::vector<char> data;
163 data.resize(size);
164 size_t received = 0;
165 char* bytes = static_cast<char*>(data.data());
166 while (received < size) {
167 const ssize_t receivedBytes = recv(socket_, bytes, size - received, 0);
168 if ((receivedBytes == -1) && (errno != EINTR)) {
169 std::cout << "profiler socket recieve failed" + std::to_string(receivedBytes) << std::endl;
170 return;
171 }
172 auto actualReceivedBytes = static_cast<size_t>(receivedBytes);
173 received += actualReceivedBytes;
174 bytes += actualReceivedBytes;
175 }
176
177 if (packet.GetType() == Packet::LOG) {
178 std::string out(data.begin(), data.end());
179 std::cout << out << std::endl;
180 if (waitReceive_) {
181 bool reveive = IsReceiveWaitMessage(out);
182 if (reveive) {
183 std::unique_lock lock(wait_mutex_);
184 waitReceive_ = false;
185 cv_.notify_one();
186 }
187 }
188 }
189 }
190
IsReceiveWaitMessage(const std::string & message)191 bool RSGraphicTestProfilerThread::IsReceiveWaitMessage(const std::string& message)
192 {
193 return (message == RESPOND_PAUSE_AT || message == RESPOND_PLAYBACK_PREPARE);
194 }
195
RecieveHeader(void * data,size_t & size)196 bool RSGraphicTestProfilerThread::RecieveHeader(void* data, size_t& size)
197 {
198 if (!data || (size == 0)) {
199 return true;
200 }
201
202 const ssize_t receivedBytes = recv(socket_, static_cast<char*>(data), size, 0);
203 if (receivedBytes > 0) {
204 size = static_cast<size_t>(receivedBytes);
205 } else {
206 size = 0;
207 if ((errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINTR)) {
208 return true;
209 }
210 std::cout << "profiler socket recieve header failed" << std::endl;
211 return false;
212 }
213 return true;
214 }
215 #endif
216 } // namespace Rosen
217 } // namespace OHOS
218