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 "rs_profiler_network.h"
17
18 #include <fstream>
19 #include <memory>
20 #include <thread>
21
22 #include "rs_profiler_archive.h"
23 #include "rs_profiler_cache.h"
24 #include "rs_profiler_capturedata.h"
25 #include "rs_profiler_file.h"
26 #include "rs_profiler_log.h"
27 #include "rs_profiler_packet.h"
28 #include "rs_profiler_socket.h"
29 #include "rs_profiler_utils.h"
30
31 #include "pipeline/main_thread/rs_main_thread.h"
32
33 namespace OHOS::Rosen {
34
35 std::atomic<bool> Network::isRunning_ = false;
36 std::atomic<bool> Network::forceShutdown_ = false;
37 std::atomic<bool> Network::blockBinary_ = false;
38 std::chrono::steady_clock::time_point Network::ping_;
39
40 std::mutex Network::incomingMutex_ {};
41 std::queue<std::vector<std::string>> Network::incoming_ {};
42
43 std::mutex Network::outgoingMutex_ {};
44 std::queue<std::vector<char>> Network::outgoing_ {};
45
AwakeRenderServiceThread()46 static void AwakeRenderServiceThread()
47 {
48 RSMainThread::Instance()->SetAccessibilityConfigChanged();
49 RSMainThread::Instance()->RequestNextVSync();
50 RSMainThread::Instance()->PostTask([]() {
51 RSMainThread::Instance()->SetAccessibilityConfigChanged();
52 RSMainThread::Instance()->RequestNextVSync();
53 });
54 }
55
IsRunning()56 bool Network::IsRunning()
57 {
58 return isRunning_;
59 }
60
ResetPing()61 void Network::ResetPing()
62 {
63 ping_ = std::chrono::steady_clock::now();
64 }
65
Ping(const Socket & socket)66 void Network::Ping(const Socket& socket)
67 {
68 if (!socket.Connected()) {
69 return;
70 }
71
72 using namespace std::chrono_literals;
73 const std::chrono::milliseconds period = 1s;
74 const auto now = std::chrono::steady_clock::now();
75 if (now <= ping_ + period) {
76 return;
77 }
78
79 Packet packet(Packet::COMMAND);
80 packet.Write("ping");
81 SendPacket(packet);
82 }
83
Run()84 void Network::Run()
85 {
86 constexpr uint16_t port = 5050;
87
88 Socket* socket = nullptr;
89
90 isRunning_ = true;
91 forceShutdown_ = false;
92
93 while (isRunning_) {
94 if (!socket) {
95 socket = new Socket();
96 }
97
98 const SocketState state = socket->GetState();
99 if (forceShutdown_) {
100 HRPW("Network: Run: Force shutdown");
101 Shutdown(socket);
102 forceShutdown_ = false;
103 } else if (state == SocketState::INITIAL) {
104 socket->Open(port);
105 } else if (state == SocketState::CREATE) {
106 socket->AcceptClient();
107 if (!socket->Connected()) {
108 usleep(20000); // 20000: sleep 20ms to reduce power consumption on standing by
109 }
110 } else if (state == SocketState::CONNECTED) {
111 Ping(*socket); // add ping packet to a queue
112 Send(*socket);
113 Receive(*socket);
114 } else if (state == SocketState::SHUTDOWN) {
115 HRPW("Network: Run: Socket state got SHUTDOWN");
116 Shutdown(socket);
117 }
118 }
119
120 delete socket;
121 }
122
Stop()123 void Network::Stop()
124 {
125 isRunning_ = false;
126 }
127
SendPacket(Packet & packet)128 void Network::SendPacket(Packet& packet)
129 {
130 if (isRunning_) {
131 const std::lock_guard<std::mutex> guard(outgoingMutex_);
132 outgoing_.emplace(packet.Release());
133 }
134 }
135
SendPath(const std::string & path,PackageID id)136 void Network::SendPath(const std::string& path, PackageID id)
137 {
138 if (!path.empty()) {
139 std::string out;
140 out += static_cast<char>(id);
141 out += path;
142 SendBinary(out);
143 }
144 }
145
SendRdcPath(const std::string & path)146 void Network::SendRdcPath(const std::string& path)
147 {
148 SendPath(path, PackageID::RS_PROFILER_RDC_BINARY);
149 }
150
SendDclPath(const std::string & path)151 void Network::SendDclPath(const std::string& path)
152 {
153 SendPath(path, PackageID::RS_PROFILER_DCL_BINARY);
154 }
155
SendMskpPath(const std::string & path)156 void Network::SendMskpPath(const std::string& path)
157 {
158 SendPath(path, PackageID::RS_PROFILER_MSKP_FILEPATH);
159 }
160
SendBetaRecordPath(const std::string & path)161 void Network::SendBetaRecordPath(const std::string& path)
162 {
163 SendPath(path, PackageID::RS_PROFILER_BETAREC_FILEPATH);
164 }
165
SendSkp(const void * data,size_t size)166 void Network::SendSkp(const void* data, size_t size)
167 {
168 if (data && (size > 0)) {
169 std::vector<char> buffer;
170 buffer.reserve(size + 1);
171 buffer.push_back(static_cast<char>(PackageID::RS_PROFILER_SKP_BINARY));
172 buffer.insert(buffer.end(), static_cast<const char*>(data), static_cast<const char*>(data) + size);
173 SendBinary(buffer);
174 }
175 }
176
SendCaptureData(const RSCaptureData & data)177 void Network::SendCaptureData(const RSCaptureData& data)
178 {
179 std::vector<char> out;
180 DataWriter archive(out);
181 char headerType = static_cast<char>(PackageID::RS_PROFILER_GFX_METRICS);
182 archive.Serialize(headerType);
183
184 const_cast<RSCaptureData&>(data).Serialize(archive);
185
186 // if no data is serialized, we end up with just 1 char header
187 if (out.size() > 1) {
188 SendBinary(out);
189 }
190 }
191
SendRSTreeDumpJSON(const std::string & jsonstr)192 void Network::SendRSTreeDumpJSON(const std::string& jsonstr)
193 {
194 Packet packet { Packet::BINARY };
195 packet.Write(static_cast<char>(PackageID::RS_PROFILER_RSTREE_DUMP_JSON));
196 packet.Write(jsonstr);
197 SendPacket(packet);
198 }
199
SendRSTreePerfNodeList(const std::unordered_set<uint64_t> & perfNodesList)200 void Network::SendRSTreePerfNodeList(const std::unordered_set<uint64_t>& perfNodesList)
201 {
202 Packet packet { Packet::BINARY };
203 packet.Write(static_cast<char>(PackageID::RS_PROFILER_RSTREE_PERF_NODE_LIST));
204 packet.Write(perfNodesList);
205 SendPacket(packet);
206 }
207
SendRSTreeSingleNodePerf(uint64_t id,uint64_t nanosec)208 void Network::SendRSTreeSingleNodePerf(uint64_t id, uint64_t nanosec)
209 {
210 Packet packet { Packet::BINARY };
211 packet.Write(static_cast<char>(PackageID::RS_PROFILER_RSTREE_SINGLE_NODE_PERF));
212 packet.Write(id);
213 packet.Write(nanosec);
214 SendPacket(packet);
215 }
216
SetBlockBinary(bool blockFlag)217 void Network::SetBlockBinary(bool blockFlag)
218 {
219 blockBinary_ = blockFlag;
220 }
221
SendBinary(const void * data,size_t size)222 void Network::SendBinary(const void* data, size_t size)
223 {
224 if (blockBinary_) {
225 return;
226 }
227 if (data && (size > 0)) {
228 Packet packet { Packet::BINARY };
229 packet.Write(data, size);
230 SendPacket(packet);
231 }
232 }
233
SendBinary(const std::vector<char> & data)234 void Network::SendBinary(const std::vector<char>& data)
235 {
236 SendBinary(data.data(), data.size());
237 }
238
SendBinary(const std::string & data)239 void Network::SendBinary(const std::string& data)
240 {
241 SendBinary(data.data(), data.size());
242 }
243
SendMessage(const std::string & message)244 void Network::SendMessage(const std::string& message)
245 {
246 if (!message.empty()) {
247 Packet packet { Packet::LOG };
248 packet.Write(message);
249 SendPacket(packet);
250 }
251 }
252
ResetSendQueue()253 void Network::ResetSendQueue()
254 {
255 const std::lock_guard<std::mutex> guard(outgoingMutex_);
256 outgoing_ = {};
257 }
258
PushCommand(const std::vector<std::string> & args)259 void Network::PushCommand(const std::vector<std::string>& args)
260 {
261 if (!args.empty()) {
262 const std::lock_guard<std::mutex> guard(incomingMutex_);
263 incoming_.emplace(args);
264 }
265 }
266
ResetCommandQueue()267 void Network::ResetCommandQueue()
268 {
269 const std::lock_guard<std::mutex> guard(incomingMutex_);
270 incoming_ = {};
271 }
272
PopCommand(std::vector<std::string> & args)273 bool Network::PopCommand(std::vector<std::string>& args)
274 {
275 args.clear();
276
277 incomingMutex_.lock();
278 if (!incoming_.empty()) {
279 args.swap(incoming_.front());
280 incoming_.pop();
281 }
282 incomingMutex_.unlock();
283
284 return !args.empty();
285 }
286
ProcessCommand(const char * data,size_t size)287 void Network::ProcessCommand(const char* data, size_t size)
288 {
289 const std::vector<std::string> args = Utils::Split({ data, size });
290 if (args.empty()) {
291 return;
292 }
293
294 PushCommand(args);
295 AwakeRenderServiceThread();
296 }
297
Send(Socket & socket)298 void Network::Send(Socket& socket)
299 {
300 std::vector<char> data;
301
302 while (socket.Connected()) {
303 data.clear();
304
305 outgoingMutex_.lock();
306 if (!outgoing_.empty()) {
307 data.swap(outgoing_.front());
308 outgoing_.pop();
309 }
310 outgoingMutex_.unlock();
311
312 if (data.empty()) {
313 break;
314 }
315
316 if (socket.SendWhenReady(data.data(), data.size())) {
317 ResetPing();
318 }
319 }
320 }
321
ProcessBinary(const std::vector<char> & data)322 void Network::ProcessBinary(const std::vector<char>& data)
323 {
324 if (data.empty()) {
325 return;
326 }
327
328 std::istringstream stream(data.data(), data.size());
329 std::string path;
330 stream >> path;
331
332 const auto offset = std::min(path.size() + 1, data.size());
333 const auto size = data.size() - offset;
334 if (size == 0) {
335 HRPE("Network: Receive file: Invalid file size");
336 return;
337 }
338
339 HRPI("Receive file: %s %.2fMB (%zu)", path.data(), Utils::Megabytes(size), size);
340 if (auto file = Utils::FileOpen(path, "wb")) {
341 Utils::FileWrite(file, data.data() + offset, size);
342 Utils::FileClose(file);
343 HRPI("Network: Receive file: Done");
344 } else {
345 HRPE("Network: Receive file: Cannot open file: %s", path.data());
346 }
347 }
348
ForceShutdown()349 void Network::ForceShutdown()
350 {
351 forceShutdown_ = true;
352 }
353
Shutdown(Socket * & socket)354 void Network::Shutdown(Socket*& socket)
355 {
356 delete socket;
357 socket = nullptr;
358
359 ResetSendQueue();
360 ResetCommandQueue();
361
362 RSSystemProperties::SetProfilerDisabled();
363 HRPE("Network: Shutdown: persist.graphic.profiler.enabled 0");
364 }
365
Receive(Socket & socket)366 void Network::Receive(Socket& socket)
367 {
368 if (!socket.Connected()) {
369 return;
370 }
371 constexpr int timeWait = 10;
372 if (socket.PollReceive(timeWait) == 0) {
373 // no data for 10 ms
374 return;
375 }
376
377 Packet packet { Packet::UNKNOWN };
378 auto wannaReceive = Packet::HEADER_SIZE;
379 socket.Receive(packet.Begin(), wannaReceive);
380
381 if (wannaReceive == 0) {
382 HRPW("Network: Receive: Invalid header");
383 return;
384 }
385
386 const size_t size = packet.GetPayloadLength();
387 if (size == 0) {
388 return;
389 }
390
391 std::vector<char> data;
392 data.resize(size);
393 socket.ReceiveWhenReady(data.data(), data.size());
394
395 if (packet.IsBinary()) {
396 ProcessBinary(data);
397 } else if (packet.IsCommand()) {
398 ProcessCommand(data.data(), data.size());
399 }
400
401 ResetPing();
402 }
403
404 } // namespace OHOS::Rosen