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" 19namespace OHOS::ArkCompiler::Toolchain { 20std::mutex g_connectMutex; 21std::unique_ptr<ConnectInspector> g_inspector = nullptr; 22static constexpr char CONNECTED_MESSAGE[] = "connected"; 23static constexpr char OPEN_MESSAGE[] = "layoutOpen"; 24static constexpr char CLOSE_MESSAGE[] = "layoutClose"; 25static constexpr char REQUEST_MESSAGE[] = "tree"; 26static constexpr char STOPDEBUGGER_MESSAGE[] = "stopDebugger"; 27static constexpr char OPEN_ARKUI_STATE_PROFILER[] = "ArkUIStateProfilerOpen"; 28static constexpr char CLOSE_ARKUI_STATE_PROFILER[] = "ArkUIStateProfilerClose"; 29static constexpr char START_RECORD_MESSAGE[] = "rsNodeStartRecord"; 30static constexpr char STOP_RECORD_MESSAGE[] = "rsNodeStopRecord"; 31std::function<void(bool)> g_setConnectCallBack; 32 33void* 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 49void 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 62void 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 72void 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 91void 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 143void 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 155void SetConnectCallback(const std::function<void(bool)>& callback) 156{ 157 g_setConnectCallBack = callback; 158} 159 160// stop debugger but the application continues to run 161void 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 169void ResetService() 170{ 171 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) { 172 g_inspector->connectServer_->StopServer(); 173 g_inspector->connectServer_.reset(); 174 } 175} 176 177bool 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 200void 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 218void StopServer([[maybe_unused]] const std::string& componentName) 219{ 220 LOGI("StopServer, componentName = %{private}s", componentName.c_str()); 221 ResetService(); 222} 223 224void 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 237void 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 244void 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 257void 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 265void 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 272bool WaitForConnection() 273{ 274 if (g_inspector == nullptr) { 275 return true; 276 } 277 return g_inspector->waitingForDebugger_; 278} 279 280// profiler methods 281 282void 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 290void 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 299void 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