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