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 <shared_mutex>
18 #include "log_wrapper.h"
19
20 namespace OHOS::ArkCompiler::Toolchain {
21 std::shared_mutex g_mutex;
22 std::unique_ptr<ConnectInspector> g_inspector = nullptr;
23
HandleDebugManager(void * const server)24 void* HandleDebugManager(void* const server)
25 {
26 if (server == nullptr) {
27 LOGE("HandleDebugManager server nullptr");
28 return nullptr;
29 }
30 static_cast<ConnectServer*>(server)->RunServer();
31 return nullptr;
32 }
33
OnMessage(const std::string & message)34 void OnMessage(const std::string& message)
35 {
36 std::shared_lock<std::shared_mutex> lock(g_mutex);
37 if (message.empty()) {
38 LOGE("message is empty");
39 return;
40 }
41
42 LOGI("ConnectServer OnMessage: %{public}s", message.c_str());
43 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
44 g_inspector->ideMsgQueue_.push(message);
45 std::string checkMessage = "connected";
46 std::string openMessage = "layoutOpen";
47 std::string closeMessage = "layoutClose";
48 std::string requestMessage = "tree";
49 if (message.find(checkMessage, 0) != std::string::npos) {
50 g_inspector->waitingForDebugger_ = false;
51 for (auto& info : g_inspector->infoBuffer_) {
52 g_inspector->connectServer_->SendMessage(info.second);
53 }
54 }
55 if (message.find(openMessage, 0) != std::string::npos) {
56 if (g_inspector->setSwitchStatus_ != nullptr) {
57 LOGI("layoutOpen start");
58 g_inspector->setSwitchStatus_(true);
59 }
60 }
61 if (message.find(closeMessage, 0) != std::string::npos) {
62 if (g_inspector->setSwitchStatus_ != nullptr) {
63 LOGI("layoutClose start");
64 g_inspector->setSwitchStatus_(false);
65 }
66 }
67 if (message.find(requestMessage, 0) != std::string::npos) {
68 if (g_inspector->createLayoutInfo_ != nullptr) {
69 LOGI("tree start");
70 g_inspector->createLayoutInfo_(g_inspector->instanceId_);
71 }
72 }
73 }
74 }
75
SetSwitchCallBack(const std::function<void (bool)> & setSwitchStatus,const std::function<void (int32_t)> & createLayoutInfo,int32_t instanceId)76 void SetSwitchCallBack(const std::function<void(bool)>& setSwitchStatus,
77 const std::function<void(int32_t)>& createLayoutInfo, int32_t instanceId)
78 {
79 if (g_inspector != nullptr) {
80 g_inspector->setSwitchStatus_ = setSwitchStatus;
81 g_inspector->createLayoutInfo_ = createLayoutInfo;
82 g_inspector->instanceId_ = instanceId;
83 }
84 }
85
ResetService()86 void ResetService()
87 {
88 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
89 g_inspector->connectServer_->StopServer();
90 g_inspector->connectServer_.reset();
91 }
92 }
93
StartServer(const std::string & componentName)94 void StartServer(const std::string& componentName)
95 {
96 g_inspector = std::make_unique<ConnectInspector>();
97 g_inspector->connectServer_ = std::make_unique<ConnectServer>(componentName,
98 std::bind(&OnMessage, std::placeholders::_1));
99
100 pthread_t tid;
101 if (pthread_create(&tid, nullptr, &HandleDebugManager,
102 static_cast<void*>(g_inspector->connectServer_.get())) != 0) {
103 LOGE("pthread_create fail!");
104 ResetService();
105 return;
106 }
107 }
108
StopServer(const std::string & componentName)109 void StopServer([[maybe_unused]] const std::string& componentName)
110 {
111 ResetService();
112 }
113
StoreMessage(int32_t instanceId,const std::string & message)114 void StoreMessage(int32_t instanceId, const std::string& message)
115 {
116 std::unique_lock<std::shared_mutex> lock(g_mutex);
117 if (g_inspector->infoBuffer_.count(instanceId) == 1) {
118 LOGE("The message with the current instance id has existed.");
119 return;
120 }
121 g_inspector->infoBuffer_[instanceId] = message;
122 }
123
StoreInspectorInfo(const std::string & jsonTreeStr,const std::string & jsonSnapshotStr)124 void StoreInspectorInfo(const std::string& jsonTreeStr, const std::string& jsonSnapshotStr)
125 {
126 std::unique_lock<std::shared_mutex> lock(g_mutex);
127 g_inspector->layoutInspectorInfo_.tree = jsonTreeStr;
128 g_inspector->layoutInspectorInfo_.snapShot = jsonSnapshotStr;
129 }
130
RemoveMessage(int32_t instanceId)131 void RemoveMessage(int32_t instanceId)
132 {
133 std::unique_lock<std::shared_mutex> lock(g_mutex);
134 if (g_inspector->infoBuffer_.count(instanceId) != 1) {
135 LOGE("The message with the current instance id does not exist.");
136 return;
137 }
138 g_inspector->infoBuffer_.erase(instanceId);
139 }
140
SendLayoutMessage(const std::string & message)141 void SendLayoutMessage(const std::string& message)
142 {
143 LOGI("SendLayoutMessage start to send message");
144 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr) {
145 g_inspector->connectServer_->SendMessage(message);
146 }
147 }
148
SendMessage(const std::string & message)149 void SendMessage(const std::string& message)
150 {
151 if (g_inspector != nullptr && g_inspector->connectServer_ != nullptr && !g_inspector->waitingForDebugger_) {
152 g_inspector->connectServer_->SendMessage(message);
153 }
154 }
155
WaitForDebugger()156 bool WaitForDebugger()
157 {
158 if (g_inspector == nullptr) {
159 return true;
160 }
161 return g_inspector->waitingForDebugger_;
162 }
163 } // OHOS::ArkCompiler::Toolchain