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