1 /*
2 * Copyright (c) 2023-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 "connect_inspector.h"
17 #include <mutex>
18 #include "common/log_wrapper.h"
19 namespace OHOS::ArkCompiler::Toolchain {
20 std::mutex g_connectMutex;
21 std::unique_ptr<ConnectInspector> g_inspector = nullptr;
22 static constexpr char CONNECTED_MESSAGE[] = "connected";
23 static constexpr char OPEN_MESSAGE[] = "layoutOpen";
24 static constexpr char CLOSE_MESSAGE[] = "layoutClose";
25 static constexpr char REQUEST_MESSAGE[] = "tree";
26 static constexpr char STOPDEBUGGER_MESSAGE[] = "stopDebugger";
27 static constexpr char OPEN_ARKUI_STATE_PROFILER[] = "ArkUIStateProfilerOpen";
28 static constexpr char CLOSE_ARKUI_STATE_PROFILER[] = "ArkUIStateProfilerClose";
29 static constexpr char START_RECORD_MESSAGE[] = "rsNodeStartRecord";
30 static constexpr char STOP_RECORD_MESSAGE[] = "rsNodeStopRecord";
31 std::function<void(bool)> g_setConnectCallBack;
32
HandleDebugManager(void* const server)33 void* HandleDebugManager(void* const server)
34 {
35 if (server == nullptr) {
36 LOGE("HandleDebugManager server nullptr");
37 return nullptr;
38 }
39 #if defined(IOS_PLATFORM) || defined(MAC_PLATFORM)
40 pthread_setname_np("OS_DbgConThread");
41 #else
42 pthread_setname_np(pthread_self(), "OS_DbgConThread");
43 #endif
44
45 static_cast<ConnectServer*>(server)->RunServer();
46 return nullptr;
47 }
48
OnConnectedMessage(const std::string& message)49 void OnConnectedMessage(const std::string& message)
50 {
51 if (message.find(CONNECTED_MESSAGE, 0) != std::string::npos) {
52 g_inspector->waitingForDebugger_ = false;
53 if (g_setConnectCallBack != nullptr) {
54 g_setConnectCallBack(true);
55 }
56 for (auto& info : g_inspector->infoBuffer_) {
57 g_inspector->connectServer_->SendMessage(info.second);
58 }
59 }
60 }
61
OnOpenMessage(const std::string& message)62 void OnOpenMessage(const std::string& message)
63 {
64 if (message.find(OPEN_MESSAGE, 0) != std::string::npos) {
65 if (g_inspector->setSwitchStatus_ != nullptr) {
66 LOGI("layoutOpen start");
67 g_inspector->setSwitchStatus_(true);
68 }
69 }
70 }
71
OnInspectorRecordMessage(const std::string& message)72 void OnInspectorRecordMessage(const std::string& message)
73 {
74 if (message.find(START_RECORD_MESSAGE, 0) != std::string::npos) {
75 if (g_inspector->startRecord_ != nullptr && !g_inspector->isRecording_) {
76 LOGI("record start");
77 g_inspector->startRecord_();
78 g_inspector->isRecording_ = true;
79 }
80 }
81
82 if (message.find(STOP_RECORD_MESSAGE, 0) != std::string::npos) {
83 if (g_inspector->stopRecord_ != nullptr && g_inspector->isRecording_) {
84 LOGI("record stop");
85 g_inspector->stopRecord_();
86 g_inspector->isRecording_ = false;
87 }
88 }
89 }
90
OnMessage(const std::string& message)91 void OnMessage(const std::string& message)
92 {
93 std::lock_guard<std::mutex> lock(g_connectMutex);
94 if (message.empty()) {
95 LOGE("message is empty");
96 return;
97 }
98
99 LOGI("ConnectServer OnMessage: %{public}s", message.c_str());
100 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
101 g_inspector->ideMsgQueue_.push(message);
102 OnConnectedMessage(message);
103
104 OnOpenMessage(message);
105 if (message.find(CLOSE_MESSAGE, 0) != std::string::npos) {
106 if (g_setConnectCallBack != nullptr) {
107 g_setConnectCallBack(false);
108 }
109 if (g_inspector->setSwitchStatus_ != nullptr) {
110 LOGI("layoutClose start");
111 g_inspector->setSwitchStatus_(false);
112 }
113 }
114 if (message.find(OPEN_ARKUI_STATE_PROFILER, 0) != std::string::npos) {
115 if (g_inspector->setArkUIStateProfilerStatus_ != nullptr) {
116 LOGI("state profiler open");
117 g_inspector->setArkUIStateProfilerStatus_(true);
118 }
119 }
120 if (message.find(CLOSE_ARKUI_STATE_PROFILER, 0) != std::string::npos) {
121 if (g_inspector->setArkUIStateProfilerStatus_ != nullptr) {
122 LOGI("state profiler close");
123 g_inspector->setArkUIStateProfilerStatus_(false);
124 }
125 }
126 if (message.find(REQUEST_MESSAGE, 0) != std::string::npos) {
127 if (g_inspector->createLayoutInfo_ != nullptr) {
128 LOGI("tree start");
129 g_inspector->createLayoutInfo_(g_inspector->instanceId_);
130 }
131 }
132 if (message.find(STOPDEBUGGER_MESSAGE, 0) != std::string::npos) {
133 g_inspector->waitingForDebugger_ = true;
134 if (g_inspector->setDebugMode_ != nullptr) {
135 LOGI("stopDebugger start");
136 g_inspector->setDebugMode_();
137 }
138 }
139 OnInspectorRecordMessage(message);
140 }
141 }
142
SetSwitchCallBack(const std::function<void(bool)>& setSwitchStatus, const std::function<void(int32_t)>& createLayoutInfo, int32_t instanceId)143 void SetSwitchCallBack(const std::function<void(bool)>& setSwitchStatus,
144 const std::function<void(int32_t)>& createLayoutInfo, int32_t instanceId)
145 {
146 std::lock_guard<std::mutex> lock(g_connectMutex);
147 if (g_inspector == nullptr) {
148 g_inspector = std::make_unique<ConnectInspector>();
149 }
150 g_inspector->setSwitchStatus_ = setSwitchStatus;
151 g_inspector->createLayoutInfo_ = createLayoutInfo;
152 g_inspector->instanceId_ = instanceId;
153 }
154
SetConnectCallback(const std::function<void(bool)>& callback)155 void SetConnectCallback(const std::function<void(bool)>& callback)
156 {
157 g_setConnectCallBack = callback;
158 }
159
160 // stop debugger but the application continues to run
SetDebugModeCallBack(const std::function<void()>& setDebugMode)161 void SetDebugModeCallBack(const std::function<void()>& setDebugMode)
162 {
163 std::lock_guard<std::mutex> lock(g_connectMutex);
164 if (g_inspector != nullptr) {
165 g_inspector->setDebugMode_ = setDebugMode;
166 }
167 }
168
ResetService()169 void ResetService()
170 {
171 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
172 g_inspector->connectServer_->StopServer();
173 g_inspector->connectServer_.reset();
174 }
175 }
176
StartServerForSocketPair(int socketfd)177 bool StartServerForSocketPair(int socketfd)
178 {
179 LOGI("StartServerForSocketPair, socketfd = %{private}d", socketfd);
180 if (g_inspector == nullptr) {
181 g_inspector = std::make_unique<ConnectInspector>();
182 }
183 if (g_inspector->connectServer_ != nullptr) {
184 LOGW("ConnectServer is not nullptr!");
185 return true;
186 }
187 g_inspector->connectServer_ = std::make_unique<ConnectServer>(socketfd,
188 std::bind(&OnMessage, std::placeholders::_1));
189
190 pthread_t tid;
191 if (pthread_create(&tid, nullptr, &HandleDebugManager,
192 static_cast<void*>(g_inspector->connectServer_.get())) != 0) {
193 LOGE("pthread_create fail!");
194 ResetService();
195 return false;
196 }
197 return true;
198 }
199
StartServer(const std::string& componentName)200 void StartServer(const std::string& componentName)
201 {
202 LOGI("StartServer, componentName = %{private}s", componentName.c_str());
203 g_inspector = std::make_unique<ConnectInspector>();
204 #ifdef PANDA_TARGET_ARM32
205 g_inspector->connectServer_ = std::make_unique<ConnectServer>(componentName,
206 std::bind(&OnMessage, std::placeholders::_1));
207
208 pthread_t tid;
209 if (pthread_create(&tid, nullptr, &HandleDebugManager,
210 static_cast<void*>(g_inspector->connectServer_.get())) != 0) {
211 LOGE("pthread_create fail!");
212 ResetService();
213 return;
214 }
215 #endif
216 }
217
StopServer([[maybe_unused]] const std::string& componentName)218 void StopServer([[maybe_unused]] const std::string& componentName)
219 {
220 LOGI("StopServer, componentName = %{private}s", componentName.c_str());
221 ResetService();
222 }
223
StoreMessage(int32_t instanceId, const std::string& message)224 void StoreMessage(int32_t instanceId, const std::string& message)
225 {
226 std::lock_guard<std::mutex> lock(g_connectMutex);
227 if (g_inspector == nullptr) {
228 g_inspector = std::make_unique<ConnectInspector>();
229 }
230 if (g_inspector->infoBuffer_.count(instanceId) == 1) {
231 LOGE("The message with the current instance id has existed.");
232 return;
233 }
234 g_inspector->infoBuffer_[instanceId] = message;
235 }
236
StoreInspectorInfo(const std::string& jsonTreeStr, const std::string& jsonSnapshotStr)237 void StoreInspectorInfo(const std::string& jsonTreeStr, const std::string& jsonSnapshotStr)
238 {
239 std::lock_guard<std::mutex> lock(g_connectMutex);
240 g_inspector->layoutInspectorInfo_.tree = jsonTreeStr;
241 g_inspector->layoutInspectorInfo_.snapShot = jsonSnapshotStr;
242 }
243
RemoveMessage(int32_t instanceId)244 void RemoveMessage(int32_t instanceId)
245 {
246 std::lock_guard<std::mutex> lock(g_connectMutex);
247 if (g_inspector == nullptr) {
248 return;
249 }
250 if (g_inspector->infoBuffer_.count(instanceId) != 1) {
251 LOGE("The message with the current instance id does not exist.");
252 return;
253 }
254 g_inspector->infoBuffer_.erase(instanceId);
255 }
256
SendLayoutMessage(const std::string& message)257 void SendLayoutMessage(const std::string& message)
258 {
259 LOGI("SendLayoutMessage start to send message");
260 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
261 g_inspector->connectServer_->SendMessage(message);
262 }
263 }
264
SendMessage(const std::string& message)265 void SendMessage(const std::string& message)
266 {
267 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr && !g_inspector->waitingForDebugger_) {
268 g_inspector->connectServer_->SendMessage(message);
269 }
270 }
271
WaitForConnection()272 bool WaitForConnection()
273 {
274 if (g_inspector == nullptr) {
275 return true;
276 }
277 return g_inspector->waitingForDebugger_;
278 }
279
280 // profiler methods
281
SendProfilerMessage(const std::string &message)282 void SendProfilerMessage(const std::string &message)
283 {
284 LOGI("SendStateProfilerMessage start to send message");
285 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
286 g_inspector->connectServer_->SendMessage(message);
287 }
288 }
289
SetProfilerCallback(const std::function<void(bool)> &setArkUIStateProfilerStatus)290 void SetProfilerCallback(const std::function<void(bool)> &setArkUIStateProfilerStatus)
291 {
292 std::lock_guard<std::mutex> lock(g_connectMutex);
293 if (g_inspector == nullptr) {
294 g_inspector = std::make_unique<ConnectInspector>();
295 }
296 g_inspector->setArkUIStateProfilerStatus_ = setArkUIStateProfilerStatus;
297 }
298
SetRecordCallback(const std::function<void(void)> &startRecordFunc, const std::function<void(void)> &stopRecordFunc)299 void SetRecordCallback(const std::function<void(void)> &startRecordFunc,
300 const std::function<void(void)> &stopRecordFunc)
301 {
302 std::lock_guard<std::mutex> lock(g_connectMutex);
303 if (g_inspector == nullptr) {
304 g_inspector = std::make_unique<ConnectInspector>();
305 }
306 g_inspector->startRecord_ = startRecordFunc;
307 g_inspector->stopRecord_ = stopRecordFunc;
308 }
309 } // OHOS::ArkCompiler::Toolchain
310