1 /*
2 * Copyright (c) 2022 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_server_manager.h"
17
18 #include <dlfcn.h>
19 #include <unistd.h>
20
21 #include "hilog_wrapper.h"
22
23 namespace OHOS::AbilityRuntime {
24 namespace {
GetInstanceMapMessage(const std::string & messageType,int32_t instanceId,const std::string & instanceName)25 std::string GetInstanceMapMessage(const std::string& messageType, int32_t instanceId, const std::string& instanceName)
26 {
27 std::string message;
28 message.append("{\"type\":\"");
29 message.append(messageType);
30 message.append("\",\"instanceId\":");
31 message.append(std::to_string(instanceId));
32 message.append(",\"name\":\"");
33 message.append(instanceName);
34 message.append("\",\"tid\":");
35 message.append(std::to_string(gettid()));
36 message.append("}");
37 return message;
38 }
39 }
40
41 using StartServer = void (*)(const std::string&);
42 using SendMessage = void (*)(const std::string&);
43 using SendLayoutMessage = void (*)(const std::string&);
44 using StopServer = void (*)(const std::string&);
45 using StoreMessage = void (*)(int32_t, const std::string&);
46 using StoreInspectorInfo = void (*)(const std::string&, const std::string&);
47 using SetSwitchCallBack = void (*)(const std::function<void(bool)> &setStatus,
48 const std::function<void(int32_t)> &createLayoutInfo, int32_t instanceId);
49 using RemoveMessage = void (*)(int32_t);
50 using WaitForDebugger = bool (*)();
51
~ConnectServerManager()52 ConnectServerManager::~ConnectServerManager()
53 {
54 StopConnectServer();
55 }
56
Get()57 ConnectServerManager& ConnectServerManager::Get()
58 {
59 static ConnectServerManager connectServerManager;
60 return connectServerManager;
61 }
62
StartConnectServer(const std::string & bundleName)63 void ConnectServerManager::StartConnectServer(const std::string& bundleName)
64 {
65 HILOG_DEBUG("ConnectServerManager::StartConnectServer Start connect server");
66 handlerConnectServerSo_ = dlopen("libconnectserver_debugger.z.so", RTLD_LAZY);
67 if (handlerConnectServerSo_ == nullptr) {
68 HILOG_ERROR("ConnectServerManager::StartConnectServer failed to open register library");
69 return;
70 }
71 auto startServer = reinterpret_cast<StartServer>(dlsym(handlerConnectServerSo_, "StartServer"));
72 if (startServer == nullptr) {
73 HILOG_ERROR("ConnectServerManager::StartConnectServer failed to find symbol 'StartServer'");
74 return;
75 }
76 bundleName_ = bundleName;
77 startServer(bundleName_);
78 }
79
StopConnectServer()80 void ConnectServerManager::StopConnectServer()
81 {
82 HILOG_DEBUG("ConnectServerManager::StopConnectServer Stop connect server");
83 if (handlerConnectServerSo_ == nullptr) {
84 HILOG_ERROR("ConnectServerManager::StopConnectServer handlerConnectServerSo_ is nullptr");
85 return;
86 }
87 auto stopServer = reinterpret_cast<StopServer>(dlsym(handlerConnectServerSo_, "StopServer"));
88 if (stopServer != nullptr) {
89 stopServer(bundleName_);
90 } else {
91 HILOG_ERROR("ConnectServerManager::StopConnectServer failed to find symbol 'StopServer'");
92 }
93 dlclose(handlerConnectServerSo_);
94 handlerConnectServerSo_ = nullptr;
95 }
96
AddInstance(int32_t instanceId,const std::string & instanceName)97 bool ConnectServerManager::AddInstance(int32_t instanceId, const std::string& instanceName)
98 {
99 HILOG_DEBUG("ConnectServerManager::AddInstance Add instance to connect server");
100 if (handlerConnectServerSo_ == nullptr) {
101 HILOG_ERROR("ConnectServerManager::AddInstance handlerConnectServerSo_ is nullptr");
102 return false;
103 }
104
105 auto waitForDebugger = reinterpret_cast<WaitForDebugger>(dlsym(handlerConnectServerSo_, "WaitForDebugger"));
106 if (waitForDebugger == nullptr) {
107 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'WaitForDebugger'");
108 return false;
109 }
110
111 {
112 std::lock_guard<std::mutex> lock(mutex_);
113 auto result = instanceMap_.try_emplace(instanceId, instanceName);
114 if (!result.second) {
115 HILOG_WARN("ConnectServerManager::AddInstance Instance %{public}d already added", instanceId);
116 return false;
117 }
118 }
119
120 auto setSwitchCallBack = reinterpret_cast<SetSwitchCallBack>(
121 dlsym(handlerConnectServerSo_, "SetSwitchCallBack"));
122 if (setSwitchCallBack == nullptr) {
123 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'setSwitchCallBack'");
124 return false;
125 }
126 setSwitchCallBack([this](bool status) { setStatus_(status); },
127 [this](int32_t containerId) { createLayoutInfo_(containerId); }, instanceId);
128
129 // Get the message including information of new instance, which will be send to IDE.
130 std::string message = GetInstanceMapMessage("addInstance", instanceId, instanceName);
131
132 if (waitForDebugger()) {
133 // if not connected, message will be stored and sent later when "connected" coming.
134 auto storeMessage = reinterpret_cast<StoreMessage>(dlsym(handlerConnectServerSo_, "StoreMessage"));
135 if (storeMessage == nullptr) {
136 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'StoreMessage'");
137 return false;
138 }
139 storeMessage(instanceId, message);
140 return false;
141 }
142
143 // WaitForDebugger() means the connection state of the connect server
144 auto sendMessage = reinterpret_cast<SendMessage>(dlsym(handlerConnectServerSo_, "SendMessage"));
145 if (sendMessage == nullptr) {
146 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'SendMessage'");
147 return false;
148 }
149 // if connected, message will be sent immediately.
150 sendMessage(message);
151 return true;
152 }
153
RemoveInstance(int32_t instanceId)154 void ConnectServerManager::RemoveInstance(int32_t instanceId)
155 {
156 HILOG_DEBUG("ConnectServerManager::RemoveInstance Remove instance to connect server");
157 if (handlerConnectServerSo_ == nullptr) {
158 HILOG_ERROR("ConnectServerManager::RemoveInstance handlerConnectServerSo_ is nullptr");
159 return;
160 }
161
162 std::string instanceName;
163
164 {
165 std::lock_guard<std::mutex> lock(mutex_);
166 auto it = instanceMap_.find(instanceId);
167 if (it == instanceMap_.end()) {
168 HILOG_WARN("ConnectServerManager::RemoveInstance Instance %{public}d is not found", instanceId);
169 return;
170 }
171
172 instanceName = std::move(it->second);
173 instanceMap_.erase(it);
174 }
175
176 auto waitForDebugger = reinterpret_cast<WaitForDebugger>(dlsym(handlerConnectServerSo_, "WaitForDebugger"));
177 if (waitForDebugger == nullptr) {
178 HILOG_ERROR("ConnectServerManager::RemoveInstance failed to find symbol 'WaitForDebugger'");
179 return;
180 }
181
182 // Get the message including information of deleted instance, which will be send to IDE.
183 std::string message = GetInstanceMapMessage("destroyInstance", instanceId, instanceName);
184
185 if (waitForDebugger()) {
186 auto removeMessage = reinterpret_cast<RemoveMessage>(dlsym(handlerConnectServerSo_, "RemoveMessage"));
187 if (removeMessage == nullptr) {
188 HILOG_ERROR("ConnectServerManager::RemoveInstance failed to find symbol 'RemoveMessage'");
189 return;
190 }
191 removeMessage(instanceId);
192 return;
193 }
194
195 auto sendMessage = reinterpret_cast<SendMessage>(dlsym(handlerConnectServerSo_, "SendMessage"));
196 if (sendMessage == nullptr) {
197 HILOG_ERROR("ConnectServerManager::RemoveInstance failed to find symbol 'SendMessage'");
198 return;
199 }
200 sendMessage(message);
201 }
202
SendInspector(const std::string & jsonTreeStr,const std::string & jsonSnapshotStr)203 void ConnectServerManager::SendInspector(const std::string& jsonTreeStr, const std::string& jsonSnapshotStr)
204 {
205 HILOG_INFO("ConnectServerManager SendInspector Start");
206 auto sendLayoutMessage = reinterpret_cast<SendMessage>(dlsym(handlerConnectServerSo_, "SendLayoutMessage"));
207 if (sendLayoutMessage == nullptr) {
208 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'sendLayoutMessage'");
209 return;
210 }
211
212 sendLayoutMessage(jsonTreeStr);
213 sendLayoutMessage(jsonSnapshotStr);
214 auto storeInspectorInfo = reinterpret_cast<StoreInspectorInfo>(
215 dlsym(handlerConnectServerSo_, "StoreInspectorInfo"));
216 if (storeInspectorInfo == nullptr) {
217 HILOG_ERROR("ConnectServerManager::AddInstance failed to find symbol 'StoreInspectorInfo'");
218 return;
219 }
220 storeInspectorInfo(jsonTreeStr, jsonSnapshotStr);
221 }
222
SetLayoutInspectorCallback(const std::function<void (int32_t)> & createLayoutInfo,const std::function<void (bool)> & setStatus)223 void ConnectServerManager::SetLayoutInspectorCallback(
224 const std::function<void(int32_t)>& createLayoutInfo, const std::function<void(bool)>& setStatus)
225 {
226 createLayoutInfo_ = createLayoutInfo;
227 setStatus_ = setStatus;
228 }
229
GetLayoutInspectorCallback()230 std::function<void(int32_t)> ConnectServerManager::GetLayoutInspectorCallback()
231 {
232 return createLayoutInfo_;
233 }
234
235 } // namespace OHOS::AbilityRuntime