• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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