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