1 /*
2 * Copyright (c) 2021 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 "window_manager_service_client_impl.h"
17
18 #include <cerrno>
19 #include <mutex>
20 #include <poll.h>
21 #include <sys/eventfd.h>
22 #include <unistd.h>
23
24 #include "window_manager_hilog.h"
25 #include "window_manager_service_proxy.h"
26
27 namespace OHOS {
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WMServiceClientImpl"};
30 }
31
GetInstance()32 sptr<WindowManagerServiceClientImpl> WindowManagerServiceClientImpl::GetInstance()
33 {
34 if (instance == nullptr) {
35 static std::mutex mutex;
36 std::lock_guard<std::mutex> lock(mutex);
37 if (instance == nullptr) {
38 instance = new WindowManagerServiceClientImpl();
39 }
40 }
41 return instance;
42 }
43
44 namespace {
OnReply(void *,struct wms *,uint32_t a)45 void OnReply(void *, struct wms *, uint32_t a)
46 {
47 WindowManagerServiceProxy::OnReply(static_cast<wms_error>(a));
48 }
49
OnDisplayChange(void *,struct wms *,uint32_t a,const char * b,uint32_t c,int32_t d,int32_t e,uint32_t f)50 void OnDisplayChange(void *, struct wms *,
51 uint32_t a, const char *b, uint32_t c, int32_t d, int32_t e, uint32_t f)
52 {
53 WindowManagerServiceProxy::OnDisplayChange(a, b, static_cast<wms_screen_status>(c), d, e,
54 static_cast<wms_screen_type>(f));
55 }
56
OnDisplayPower(void *,struct wms *,uint32_t a,int32_t b)57 void OnDisplayPower(void *, struct wms *, uint32_t a, int32_t b)
58 {
59 WindowManagerServiceProxy::OnDisplayPower(a, b);
60 }
61
OnDisplayBacklight(void *,struct wms *,uint32_t a,uint32_t b)62 void OnDisplayBacklight(void *, struct wms *, uint32_t a, uint32_t b)
63 {
64 WindowManagerServiceProxy::OnDisplayBacklight(a, b);
65 }
66
OnDisplayModeChange(void *,struct wms *,uint32_t a)67 void OnDisplayModeChange(void *, struct wms *, uint32_t a)
68 {
69 WindowManagerServiceProxy::OnDisplayModeChange(a);
70 }
71
OnGlobalWindowStatus(void *,struct wms *,uint32_t a,uint32_t b,uint32_t c)72 void OnGlobalWindowStatus(void *, struct wms *, uint32_t a, uint32_t b, uint32_t c)
73 {
74 WindowManagerServiceProxy::OnGlobalWindowStatus(a, b, c);
75 }
76
OnScreenShotDone(void *,struct wms *,uint32_t a,int32_t b,int32_t c,int32_t d,int32_t e,uint32_t f,uint32_t g,uint32_t h)77 void OnScreenShotDone(void *, struct wms *,
78 uint32_t a, int32_t b, int32_t c, int32_t d, int32_t e, uint32_t f, uint32_t g, uint32_t h)
79 {
80 WindowManagerServiceProxy::OnScreenShot(WMS_ERROR_OK, a, b, c, d, e, f, g, h);
81 }
82
OnScreenShotError(void *,struct wms *,uint32_t a,uint32_t b)83 void OnScreenShotError(void *, struct wms *, uint32_t a, uint32_t b)
84 {
85 WindowManagerServiceProxy::OnScreenShot(static_cast<wms_error>(a), b, -1, 0, 0, 0, 0, 0, 0);
86 }
87
OnWindowShotDone(void *,struct wms *,uint32_t a,int32_t b,int32_t c,int32_t d,int32_t e,uint32_t f,uint32_t g,uint32_t h)88 void OnWindowShotDone(void *, struct wms *,
89 uint32_t a, int32_t b, int32_t c, int32_t d, int32_t e, uint32_t f, uint32_t g, uint32_t h)
90 {
91 WindowManagerServiceProxy::OnWindowShot(WMS_ERROR_OK, a, b, c, d, e, f, g, h);
92 }
93
OnWindowShotError(void *,struct wms *,uint32_t a,uint32_t b)94 void OnWindowShotError(void *, struct wms *, uint32_t a, uint32_t b)
95 {
96 WindowManagerServiceProxy::OnWindowShot(static_cast<wms_error>(a), b, -1, 0, 0, 0, 0, 0, 0);
97 }
98
RegistryGlobal(void * ppwms,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)99 void RegistryGlobal(void *ppwms, struct wl_registry *registry,
100 uint32_t id, const char *interface, uint32_t version)
101 {
102 if (ppwms == nullptr) {
103 return;
104 }
105
106 if (strcmp(interface, "wms") == 0) {
107 auto &pwms = *static_cast<struct wms**>(ppwms);
108 constexpr uint32_t wmsVersion = 1;
109 pwms = (struct wms *)wl_registry_bind(registry, id, &wms_interface, wmsVersion);
110 const struct wms_listener listener = {
111 OnReply,
112 OnDisplayChange,
113 OnDisplayPower,
114 OnDisplayBacklight,
115 OnDisplayModeChange,
116 nullptr,
117 nullptr,
118 OnGlobalWindowStatus,
119 OnScreenShotDone,
120 OnScreenShotError,
121 OnWindowShotDone,
122 OnWindowShotError,
123 nullptr,
124 };
125 if (pwms != nullptr) {
126 wms_add_listener(pwms, &listener, nullptr);
127 }
128 }
129 }
130 } // namespace
131
StartDispatchThread()132 void WindowManagerServiceClientImpl::StartDispatchThread()
133 {
134 startOnceFlag = std::make_unique<std::once_flag>();
135 startPromise = new Promise<bool>();
136
137 dispatchThread = std::make_unique<std::thread>(
138 std::bind(&WindowManagerServiceClientImpl::DispatchThreadMain, this));
139
140 startPromise->Await();
141 }
142
StopDispatchThread()143 void WindowManagerServiceClientImpl::StopDispatchThread()
144 {
145 InterruptDispatchThread();
146 dispatchThread->join();
147 }
148
DispatchThreadMain()149 void WindowManagerServiceClientImpl::DispatchThreadMain()
150 {
151 WMLOGFI("dispatch loop start");
152 interruptFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
153 int32_t displayFd = wl_display_get_fd(display);
154
155 while (true) {
156 if (startOnceFlag != nullptr) {
157 static const auto onceFunc = [this]() {
158 if (startPromise != nullptr) {
159 startPromise->Resolve(true);
160 }
161 };
162 std::call_once(*startOnceFlag, onceFunc);
163 }
164
165 while (wl_display_prepare_read(display) != 0) {
166 wl_display_dispatch_pending(display);
167 }
168
169 if (wl_display_flush(display) == -1) {
170 WMLOGFE("wl_display_flush return -1");
171 break;
172 }
173
174 struct pollfd pfd[] = {
175 { .fd = displayFd, .events = POLLIN, },
176 { .fd = interruptFd, .events = POLLIN, },
177 };
178
179 int32_t ret = 0;
180 do {
181 ret = poll(pfd, sizeof(pfd) / sizeof(*pfd), -1);
182 } while (ret == -1 && errno == EINTR);
183
184 if (ret == -1) {
185 WMLOGFE("poll return -1");
186 wl_display_cancel_read(display);
187 break;
188 }
189
190 if ((uint32_t)pfd[1].revents & POLLIN) {
191 WMLOGFI("return by interrupt");
192 wl_display_cancel_read(display);
193 return;
194 }
195
196 if ((uint32_t)pfd[0].revents & POLLIN) {
197 wl_display_read_events(display);
198 if (wl_display_dispatch_pending(display) == -1) {
199 WMLOGFE("wl_display_dispatch_pending return -1");
200 break;
201 }
202 }
203 }
204 WMLOGFI("return %{public}d, errno: %{public}d", wl_display_get_error(display), errno);
205 }
206
InterruptDispatchThread()207 void WindowManagerServiceClientImpl::InterruptDispatchThread()
208 {
209 if (interruptFd == -1) {
210 return;
211 }
212 uint64_t buf = 1;
213 int32_t ret = 0;
214 WMLOGFD("send interrupt");
215
216 do {
217 ret = write(interruptFd, &buf, sizeof(buf));
218 } while (ret == -1 && errno == EINTR);
219 }
220
Init()221 GSError WindowManagerServiceClientImpl::Init()
222 {
223 WMLOGFI("init");
224 if (wmservice != nullptr) {
225 return GSERROR_OK;
226 }
227
228 if (display == nullptr) {
229 display = wl_display_connect(nullptr);
230 if (display == nullptr) {
231 WMLOGFE("Create display failed!");
232 return GSERROR_CONNOT_CONNECT_WESTON;
233 }
234 }
235
236 if (registry == nullptr) {
237 registry = wl_display_get_registry(display);
238 if (registry == nullptr) {
239 WMLOGFE("wl_display_get_registry failed");
240 return GSERROR_API_FAILED;
241 }
242 }
243
244 struct wl_registry_listener listener = { RegistryGlobal };
245 if (wl_registry_add_listener(registry, &listener, &wms) == -1) {
246 WMLOGFE("wl_registry_add_listener failed");
247 return GSERROR_API_FAILED;
248 }
249
250 if (wl_display_roundtrip(display) == -1) {
251 WMLOGFE("wl_display_roundtrip failed");
252 return GSERROR_API_FAILED;
253 }
254
255 if (wl_display_roundtrip(display) == -1) {
256 WMLOGFE("wl_display_roundtrip failed");
257 return GSERROR_API_FAILED;
258 }
259
260 if (wms == nullptr) {
261 WMLOGFE("weston not have wms module");
262 return GSERROR_CONNOT_CONNECT_SERVER;
263 }
264
265 auto gret = IAnimationService::Init();
266 if (gret != GSERROR_OK) {
267 WMLOGFW("animationService init failed: %{public}s", GSErrorStr(gret).c_str());
268 }
269
270 auto as = IAnimationService::Get();
271 wmservice = new WindowManagerServiceProxy(wms, display, as);
272 StartDispatchThread();
273 return GSERROR_OK;
274 }
275
Deinit()276 GSError WindowManagerServiceClientImpl::Deinit()
277 {
278 WMLOGFI("deinit");
279 if (display == nullptr) {
280 return GSERROR_OK;
281 }
282 StopDispatchThread();
283 wms_destroy(wms);
284 wms = nullptr;
285 wl_registry_destroy(registry);
286 registry = nullptr;
287 wl_display_roundtrip(display);
288 wl_display_disconnect(display);
289 display = nullptr;
290 return GSERROR_OK;
291 }
292
GetService() const293 sptr<IWindowManagerService> WindowManagerServiceClientImpl::GetService() const
294 {
295 return wmservice;
296 }
297
~WindowManagerServiceClientImpl()298 WindowManagerServiceClientImpl::~WindowManagerServiceClientImpl()
299 {
300 Deinit();
301 }
302 }
303