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