• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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