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