• 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("}");
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