1 /*
2 * Copyright (c) 2025 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 #include "window_inspector.h"
16
17 #include <dlfcn.h>
18
19 #include "nlohmann/json.hpp"
20
21 #include "window_manager_hilog.h"
22
23 namespace OHOS::Rosen {
24 namespace {
25 constexpr char ARK_CONNECT_LIB_PATH[] = "libark_connect_inspector.z.so";
26 constexpr char SET_WMS_CALLBACK[] = "SetWMSCallback";
27 constexpr char SEND_WMS_MESSAGE[] = "SendMessage";
28 const std::string METHOD_NAME = "WMS.windowList";
29 const std::string COMMAND_NAME = "getCurrentProcessWindowList";
30
CreateArkUIInspectorJson(const std::vector<WindowListInfo> & windowListInfo,std::string & jsonStr)31 void CreateArkUIInspectorJson(
32 const std::vector<WindowListInfo>& windowListInfo, std::string& jsonStr)
33 {
34 nlohmann::ordered_json jsonWindowListInfo;
35 jsonWindowListInfo["type"] = "window";
36 jsonWindowListInfo["content"] = nlohmann::json::array();
37 for (const auto& info : windowListInfo) {
38 nlohmann::ordered_json jsonWindowInfo;
39 jsonWindowInfo["windowName"] = info.windowName;
40 jsonWindowInfo["winId"] = std::to_string(info.windowId);
41 jsonWindowInfo["type"] = std::to_string(info.windowType);
42 nlohmann::ordered_json jsonRectInfo;
43 jsonRectInfo["startX"] = std::to_string(info.windowRect.posX_);
44 jsonRectInfo["startY"] = std::to_string(info.windowRect.posY_);
45 jsonRectInfo["width"] = std::to_string(info.windowRect.width_);
46 jsonRectInfo["height"] = std::to_string(info.windowRect.height_);
47 jsonWindowInfo["rect"] = jsonRectInfo;
48
49 jsonWindowListInfo["content"].push_back(std::move(jsonWindowInfo));
50 }
51 jsonStr = jsonWindowListInfo.dump();
52 }
53 } // namespace
54
GetInstance()55 WindowInspector& WindowInspector::GetInstance()
56 {
57 static WindowInspector instance;
58 return instance;
59 }
60
WindowInspector()61 WindowInspector::WindowInspector()
62 {
63 ConnectServer();
64 }
65
ConnectServer()66 void WindowInspector::ConnectServer()
67 {
68 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "start connect");
69 handlerConnectServerSo_ = dlopen(ARK_CONNECT_LIB_PATH, RTLD_NOLOAD);
70 if (handlerConnectServerSo_ == nullptr) {
71 handlerConnectServerSo_ = dlopen(ARK_CONNECT_LIB_PATH, RTLD_NOW);
72 TLOGW(WmsLogTag::WMS_ATTRIBUTE, "noload fail: %{public}s", ARK_CONNECT_LIB_PATH);
73 }
74 if (handlerConnectServerSo_ == nullptr) {
75 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "can't open %{public}s", ARK_CONNECT_LIB_PATH);
76 return;
77 }
78 setWMSCallbackFunc_ = reinterpret_cast<SetWMSCallbackFunc>(dlsym(handlerConnectServerSo_, SET_WMS_CALLBACK));
79 sendWMSMessageFunc_ = reinterpret_cast<SendWMSMessageFunc>(dlsym(handlerConnectServerSo_, SEND_WMS_MESSAGE));
80 if (setWMSCallbackFunc_ == nullptr || sendWMSMessageFunc_ == nullptr) {
81 setWMSCallbackFunc_ = nullptr;
82 sendWMSMessageFunc_ = nullptr;
83 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "load failed: %{public}s", dlerror());
84 return;
85 }
86 setWMSCallbackFunc_([this](const char* message) {
87 std::string jsonWindowListInfo;
88 if (ProcessArkUIInspectorMessage(message, jsonWindowListInfo)) {
89 SendMessageToIDE(jsonWindowListInfo);
90 }
91 });
92 isConnectServerSuccess_ = true;
93 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "end connect");
94 }
95
IsConnectServerSuccess() const96 bool WindowInspector::IsConnectServerSuccess() const
97 {
98 return isConnectServerSuccess_;
99 }
100
RegisterGetWMSWindowListCallback(uint32_t windowId,GetWMSWindowListCallback && func)101 void WindowInspector::RegisterGetWMSWindowListCallback(
102 uint32_t windowId, GetWMSWindowListCallback&& func)
103 {
104 if (!IsConnectServerSuccess()) {
105 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}u connect failed", windowId);
106 return;
107 }
108 std::unique_lock<std::mutex> lock(callbackMutex_);
109 auto [_, result] = getWMSWindowListCallbacks_.insert_or_assign(windowId, std::move(func));
110 if (result) {
111 TLOGW(WmsLogTag::WMS_ATTRIBUTE, "callback has registered");
112 }
113 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}u", windowId);
114 }
115
UnregisterGetWMSWindowListCallback(uint32_t windowId)116 void WindowInspector::UnregisterGetWMSWindowListCallback(uint32_t windowId)
117 {
118 std::unique_lock<std::mutex> lock(callbackMutex_);
119 auto result = getWMSWindowListCallbacks_.erase(windowId);
120 if (result == 0) {
121 TLOGW(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}u callback not registered", windowId);
122 }
123 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}u", windowId);
124 }
125
ProcessArkUIInspectorMessage(const std::string & message,std::string & jsonStr)126 bool WindowInspector::ProcessArkUIInspectorMessage(const std::string& message, std::string& jsonStr)
127 {
128 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "receive callback");
129 nlohmann::json jsonMessage = nlohmann::json::parse(message, nullptr, false);
130 if (jsonMessage.is_discarded()) {
131 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "json::parse err");
132 return false;
133 }
134 if (!jsonMessage.contains("method") || jsonMessage["method"].get<std::string>() != METHOD_NAME) {
135 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "received method err");
136 return false;
137 }
138 if (!jsonMessage.contains("params") || !jsonMessage["params"].contains("command") ||
139 jsonMessage["params"]["command"].get<std::string>() != COMMAND_NAME) {
140 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "received params.command err");
141 return false;
142 }
143 std::vector<WindowListInfo> windowListInfoVec;
144 {
145 std::unique_lock<std::mutex> lock(callbackMutex_);
146 for (auto& [_, func] : getWMSWindowListCallbacks_) {
147 if (auto windowListInfo = func()) {
148 windowListInfoVec.push_back(std::move(windowListInfo.value()));
149 }
150 }
151 }
152 if (windowListInfoVec.empty()) {
153 TLOGE(WmsLogTag::WMS_ATTRIBUTE, "has no window");
154 return false;
155 }
156 CreateArkUIInspectorJson(windowListInfoVec, jsonStr);
157 return true;
158 }
159
SendMessageToIDE(const std::string & jsonStr)160 void WindowInspector::SendMessageToIDE(const std::string& jsonStr)
161 {
162 sendWMSMessageFunc_(jsonStr);
163 TLOGI(WmsLogTag::WMS_ATTRIBUTE, "%{public}s", jsonStr.c_str());
164 }
165 } // namespace Rosen::OHOS