• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 void 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     g_inspector->connectServer_ = std::make_unique<ConnectServer>(socketfd,
184         std::bind(&OnMessage, std::placeholders::_1));
185 
186     pthread_t tid;
187     if (pthread_create(&tid, nullptr, &HandleDebugManager,
188         static_cast<void*>(g_inspector->connectServer_.get())) != 0) {
189         LOGE("pthread_create fail!");
190         ResetService();
191         return;
192     }
193 }
194 
StartServer(const std::string & componentName)195 void StartServer(const std::string& componentName)
196 {
197     LOGI("StartServer, componentName = %{private}s", componentName.c_str());
198     g_inspector = std::make_unique<ConnectInspector>();
199 #ifdef PANDA_TARGET_ARM32
200     g_inspector->connectServer_ = std::make_unique<ConnectServer>(componentName,
201         std::bind(&OnMessage, std::placeholders::_1));
202 
203     pthread_t tid;
204     if (pthread_create(&tid, nullptr, &HandleDebugManager,
205         static_cast<void*>(g_inspector->connectServer_.get())) != 0) {
206         LOGE("pthread_create fail!");
207         ResetService();
208         return;
209     }
210 #endif
211 }
212 
StopServer(const std::string & componentName)213 void StopServer([[maybe_unused]] const std::string& componentName)
214 {
215     LOGI("StopServer, componentName = %{private}s", componentName.c_str());
216     ResetService();
217 }
218 
StoreMessage(int32_t instanceId,const std::string & message)219 void StoreMessage(int32_t instanceId, const std::string& message)
220 {
221     std::lock_guard<std::mutex> lock(g_connectMutex);
222     if (g_inspector == nullptr) {
223         g_inspector = std::make_unique<ConnectInspector>();
224     }
225     if (g_inspector->infoBuffer_.count(instanceId) == 1) {
226         LOGE("The message with the current instance id has existed.");
227         return;
228     }
229     g_inspector->infoBuffer_[instanceId] = message;
230 }
231 
StoreInspectorInfo(const std::string & jsonTreeStr,const std::string & jsonSnapshotStr)232 void StoreInspectorInfo(const std::string& jsonTreeStr, const std::string& jsonSnapshotStr)
233 {
234     std::lock_guard<std::mutex> lock(g_connectMutex);
235     if (g_inspector == nullptr) {
236         g_inspector = std::make_unique<ConnectInspector>();
237     }
238     g_inspector->layoutInspectorInfo_.tree = jsonTreeStr;
239     g_inspector->layoutInspectorInfo_.snapShot = jsonSnapshotStr;
240 }
241 
RemoveMessage(int32_t instanceId)242 void RemoveMessage(int32_t instanceId)
243 {
244     std::lock_guard<std::mutex> lock(g_connectMutex);
245     if (g_inspector == nullptr) {
246         return;
247     }
248     if (g_inspector->infoBuffer_.count(instanceId) != 1) {
249         LOGE("The message with the current instance id does not exist.");
250         return;
251     }
252     g_inspector->infoBuffer_.erase(instanceId);
253 }
254 
SendLayoutMessage(const std::string & message)255 void SendLayoutMessage(const std::string& message)
256 {
257     LOGI("SendLayoutMessage start to send message");
258     if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
259         g_inspector->connectServer_->SendMessage(message);
260     }
261 }
262 
SendMessage(const std::string & message)263 void SendMessage(const std::string& message)
264 {
265     if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr && !g_inspector->waitingForDebugger_) {
266         g_inspector->connectServer_->SendMessage(message);
267     }
268 }
269 
WaitForConnection()270 bool WaitForConnection()
271 {
272     if (g_inspector == nullptr) {
273         return true;
274     }
275     return g_inspector->waitingForDebugger_;
276 }
277 
278 // profiler methods
279 
SendProfilerMessage(const std::string & message)280 void SendProfilerMessage(const std::string &message)
281 {
282     LOGI("SendStateProfilerMessage start to send message");
283     if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
284         g_inspector->connectServer_->SendMessage(message);
285     }
286 }
287 
SetProfilerCallback(const std::function<void (bool)> & setArkUIStateProfilerStatus)288 void SetProfilerCallback(const std::function<void(bool)> &setArkUIStateProfilerStatus)
289 {
290     std::lock_guard<std::mutex> lock(g_connectMutex);
291     if (g_inspector == nullptr) {
292         g_inspector = std::make_unique<ConnectInspector>();
293     }
294     g_inspector->setArkUIStateProfilerStatus_ = setArkUIStateProfilerStatus;
295 }
296 
SetRecordCallback(const std::function<void (void)> & startRecordFunc,const std::function<void (void)> & stopRecordFunc)297 void SetRecordCallback(const std::function<void(void)> &startRecordFunc,
298     const std::function<void(void)> &stopRecordFunc)
299 {
300     std::lock_guard<std::mutex> lock(g_connectMutex);
301     if (g_inspector == nullptr) {
302         g_inspector = std::make_unique<ConnectInspector>();
303     }
304     g_inspector->startRecord_ = startRecordFunc;
305     g_inspector->stopRecord_ = stopRecordFunc;
306 }
307 } // OHOS::ArkCompiler::Toolchain
308