• 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 "js_display_listener.h"
17 
18 #include <hitrace_meter.h>
19 
20 #include "dm_common.h"
21 #include "js_runtime_utils.h"
22 #include "window_manager_hilog.h"
23 #include "js_display.h"
24 
25 namespace OHOS {
26 namespace Rosen {
27 using namespace AbilityRuntime;
28 
JsDisplayListener(napi_env env)29 JsDisplayListener::JsDisplayListener(napi_env env) : env_(env), weakRef_(wptr<JsDisplayListener> (this))
30 {
31     TLOGI(WmsLogTag::DMS, "Constructor execution");
32     napi_add_env_cleanup_hook(env_, CleanEnv, this);
33 }
34 
~JsDisplayListener()35 JsDisplayListener::~JsDisplayListener()
36 {
37     TLOGI(WmsLogTag::DMS, "Destructor execution");
38     napi_remove_env_cleanup_hook(env_, CleanEnv, this);
39     env_ = nullptr;
40 }
41 
CleanEnv(void * obj)42 void JsDisplayListener::CleanEnv(void* obj)
43 {
44     JsDisplayListener* thisObj = reinterpret_cast<JsDisplayListener*>(obj);
45     if (!thisObj) {
46         TLOGE(WmsLogTag::DMS, "obj is nullptr");
47         return;
48     }
49     TLOGI(WmsLogTag::DMS, "env_ is invalid, set to nullptr");
50     thisObj->env_ = nullptr;
51 }
52 
AddCallback(const std::string & type,napi_value jsListenerObject)53 void JsDisplayListener::AddCallback(const std::string& type, napi_value jsListenerObject)
54 {
55     TLOGD(WmsLogTag::DMS, "called");
56     std::unique_ptr<NativeReference> callbackRef;
57     if (env_ == nullptr) {
58         TLOGE(WmsLogTag::DMS, "env_ nullptr");
59         return;
60     }
61     napi_ref result = nullptr;
62     napi_create_reference(env_, jsListenerObject, 1, &result);
63     callbackRef.reset(reinterpret_cast<NativeReference*>(result));
64     std::lock_guard<std::mutex> lock(mtx_);
65     jsCallBack_[type].emplace_back(std::move(callbackRef));
66     TLOGD(WmsLogTag::DMS, "success jsCallBack_ size: %{public}u!",
67         static_cast<uint32_t>(jsCallBack_[type].size()));
68 }
69 
RemoveAllCallback()70 void JsDisplayListener::RemoveAllCallback()
71 {
72     std::lock_guard<std::mutex> lock(mtx_);
73     jsCallBack_.clear();
74 }
75 
RemoveCallback(napi_env env,const std::string & type,napi_value jsListenerObject)76 void JsDisplayListener::RemoveCallback(napi_env env, const std::string& type, napi_value jsListenerObject)
77 {
78     std::lock_guard<std::mutex> lock(mtx_);
79     auto it = jsCallBack_.find(type);
80     if (it == jsCallBack_.end()) {
81         TLOGE(WmsLogTag::DMS, "no callback to remove");
82         return;
83     }
84     auto& listeners = it->second;
85     for (auto iter = listeners.begin(); iter != listeners.end();) {
86         bool isEquals = false;
87         napi_strict_equals(env, jsListenerObject, (*iter)->GetNapiValue(), &isEquals);
88         if (isEquals) {
89             listeners.erase(iter);
90         } else {
91             iter++;
92         }
93     }
94     TLOGI(WmsLogTag::DMS, "success jsCallBack_ size: %{public}u!",
95         static_cast<uint32_t>(listeners.size()));
96 }
97 
CallJsMethod(const std::string & methodName,napi_value const * argv,size_t argc)98 void JsDisplayListener::CallJsMethod(const std::string& methodName, napi_value const * argv, size_t argc)
99 {
100     if (methodName.empty()) {
101         TLOGE(WmsLogTag::DMS, "empty method name str, call method failed");
102         return;
103     }
104     TLOGD(WmsLogTag::DMS, "CallJsMethod methodName = %{public}s", methodName.c_str());
105     if (env_ == nullptr) {
106         TLOGE(WmsLogTag::DMS, "env_ nullptr");
107         return;
108     }
109     for (auto& callback : jsCallBack_[methodName]) {
110         napi_value method = callback->GetNapiValue();
111         if (method == nullptr) {
112             TLOGE(WmsLogTag::DMS, "Failed to get method callback from object");
113             continue;
114         }
115         napi_call_function(env_, NapiGetUndefined(env_), method, argc, argv, nullptr);
116     }
117 }
118 
OnCreate(DisplayId id)119 void JsDisplayListener::OnCreate(DisplayId id)
120 {
121     std::lock_guard<std::mutex> lock(mtx_);
122     TLOGI(WmsLogTag::DMS, "called, displayId: %{public}d", static_cast<uint32_t>(id));
123     if (jsCallBack_.empty()) {
124         TLOGE(WmsLogTag::DMS, "not register!");
125         return;
126     }
127     if (jsCallBack_.find(EVENT_ADD) == jsCallBack_.end()) {
128         TLOGE(WmsLogTag::DMS, "not this event, return");
129         return;
130     }
131     auto napiTask = [self = weakRef_, id, env = env_]() {
132         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnCreate");
133         auto thisListener = self.promote();
134         if (thisListener == nullptr || env == nullptr) {
135             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
136             return;
137         }
138         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
139         thisListener->CallJsMethod(EVENT_ADD, argv, ArraySize(argv));
140     };
141 
142     if (env_ != nullptr) {
143         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnCreate");
144         if (ret != napi_status::napi_ok) {
145             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
146         }
147     } else {
148         TLOGE(WmsLogTag::DMS, "env is nullptr");
149     }
150 }
151 
OnDestroy(DisplayId id)152 void JsDisplayListener::OnDestroy(DisplayId id)
153 {
154     std::lock_guard<std::mutex> lock(mtx_);
155     TLOGI(WmsLogTag::DMS, "called, displayId: %{public}d", static_cast<uint32_t>(id));
156     if (jsCallBack_.empty()) {
157         TLOGE(WmsLogTag::DMS, "not register!");
158         return;
159     }
160     if (jsCallBack_.find(EVENT_REMOVE) == jsCallBack_.end()) {
161         TLOGE(WmsLogTag::DMS, "not this event, return");
162         return;
163     }
164     auto napiTask = [self = weakRef_, id, env = env_]() {
165         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnDestroy");
166         auto thisListener = self.promote();
167         if (thisListener == nullptr || env == nullptr) {
168             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
169             return;
170         }
171         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
172         thisListener->CallJsMethod(EVENT_REMOVE, argv, ArraySize(argv));
173     };
174 
175     if (env_ != nullptr) {
176         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnDestroy");
177         if (ret != napi_status::napi_ok) {
178             TLOGE(WmsLogTag::DMS, "OFailed to SendEvent.");
179         }
180     } else {
181         TLOGE(WmsLogTag::DMS, " env is nullptr");
182     }
183 }
184 
OnChange(DisplayId id)185 void JsDisplayListener::OnChange(DisplayId id)
186 {
187     std::lock_guard<std::mutex> lock(mtx_);
188     TLOGD(WmsLogTag::DMS, "Jcalled, displayId: %{public}d", static_cast<uint32_t>(id));
189     if (jsCallBack_.empty()) {
190         TLOGE(WmsLogTag::DMS, "not register!");
191         return;
192     }
193     if (jsCallBack_.find(EVENT_CHANGE) == jsCallBack_.end()) {
194         TLOGD(WmsLogTag::DMS, "not this event, return");
195         return;
196     }
197     auto napiTask = [self = weakRef_, id, env = env_]() {
198         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnChange");
199         auto thisListener = self.promote();
200         if (thisListener == nullptr || env == nullptr) {
201             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
202             return;
203         }
204         napi_value argv[] = {CreateJsValue(env, static_cast<uint32_t>(id))};
205         thisListener->CallJsMethod(EVENT_CHANGE, argv, ArraySize(argv));
206     };
207 
208     if (env_ != nullptr) {
209         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnChange");
210         if (ret != napi_status::napi_ok) {
211             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
212         }
213     } else {
214         TLOGE(WmsLogTag::DMS, "env is nullptr");
215     }
216 }
217 
OnPrivateWindow(bool hasPrivate)218 void JsDisplayListener::OnPrivateWindow(bool hasPrivate)
219 {
220     std::lock_guard<std::mutex> lock(mtx_);
221     TLOGI(WmsLogTag::DMS, "called, private status: %{public}u", static_cast<uint32_t>(hasPrivate));
222     if (jsCallBack_.empty()) {
223         TLOGE(WmsLogTag::DMS, "not register!");
224         return;
225     }
226     if (jsCallBack_.find(EVENT_PRIVATE_MODE_CHANGE) == jsCallBack_.end()) {
227         TLOGE(WmsLogTag::DMS, "OnPrivateWindow not this event, return");
228         return;
229     }
230     auto napiTask = [self = weakRef_, hasPrivate, env = env_]() {
231         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnPrivateWindow");
232         auto thisListener = self.promote();
233         if (thisListener == nullptr || env == nullptr) {
234             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
235             return;
236         }
237         napi_value argv[] = {CreateJsValue(env, hasPrivate)};
238         thisListener->CallJsMethod(EVENT_PRIVATE_MODE_CHANGE, argv, ArraySize(argv));
239     };
240 
241     if (env_ != nullptr) {
242         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnPrivateWindow");
243         if (ret != napi_status::napi_ok) {
244             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
245         }
246     } else {
247         TLOGE(WmsLogTag::DMS, "env is nullptr");
248     }
249 }
250 
OnFoldStatusChanged(FoldStatus foldStatus)251 void JsDisplayListener::OnFoldStatusChanged(FoldStatus foldStatus)
252 {
253     std::lock_guard<std::mutex> lock(mtx_);
254     TLOGI(WmsLogTag::DMS, "called, foldStatus: %{public}u", static_cast<uint32_t>(foldStatus));
255     if (jsCallBack_.empty()) {
256         TLOGE(WmsLogTag::DMS, "not register!");
257         return;
258     }
259     if (jsCallBack_.find(EVENT_FOLD_STATUS_CHANGED) == jsCallBack_.end()) {
260         TLOGE(WmsLogTag::DMS, "not this event, return");
261         return;
262     }
263     auto napiTask = [self = weakRef_, foldStatus, env = env_] () {
264         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnFoldStatusChanged");
265         auto thisListener = self.promote();
266         if (thisListener == nullptr || env == nullptr) {
267             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
268             return;
269         }
270         napi_value argv[] = {CreateJsValue(env, foldStatus)};
271         thisListener->CallJsMethod(EVENT_FOLD_STATUS_CHANGED, argv, ArraySize(argv));
272     };
273 
274     if (env_ != nullptr) {
275         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnFoldStatusChanged");
276         if (ret != napi_status::napi_ok) {
277             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
278         }
279     } else {
280         TLOGE(WmsLogTag::DMS, "env is nullptr");
281     }
282 }
283 
OnFoldAngleChanged(std::vector<float> foldAngles)284 void JsDisplayListener::OnFoldAngleChanged(std::vector<float> foldAngles)
285 {
286     std::lock_guard<std::mutex> lock(mtx_);
287     if (jsCallBack_.empty()) {
288         TLOGE(WmsLogTag::DMS, "not register!");
289         return;
290     }
291     if (jsCallBack_.find(EVENT_FOLD_ANGLE_CHANGED) == jsCallBack_.end()) {
292         TLOGE(WmsLogTag::DMS, "not this event, return");
293         return;
294     }
295     auto napiTask = [self = weakRef_, foldAngles, env = env_]() {
296         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnFoldAngleChanged");
297         auto thisListener = self.promote();
298         if (thisListener == nullptr || env == nullptr) {
299             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
300             return;
301         }
302         napi_value argv[] = {CreateNativeArray(env, foldAngles)};
303         thisListener->CallJsMethod(EVENT_FOLD_ANGLE_CHANGED, argv, ArraySize(argv));
304     };
305 
306     if (env_ != nullptr) {
307         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnFoldAngleChanged");
308         if (ret != napi_status::napi_ok) {
309             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
310         }
311     } else {
312         TLOGE(WmsLogTag::DMS, "env is nullptr");
313     }
314 }
315 
OnCaptureStatusChanged(bool isCapture)316 void JsDisplayListener::OnCaptureStatusChanged(bool isCapture)
317 {
318     std::lock_guard<std::mutex> lock(mtx_);
319     if (jsCallBack_.empty()) {
320         TLOGE(WmsLogTag::DMS, "not register!");
321         return;
322     }
323     if (jsCallBack_.find(EVENT_CAPTURE_STATUS_CHANGED) == jsCallBack_.end()) {
324         TLOGE(WmsLogTag::DMS, "not this event, return");
325         return;
326     }
327     auto napiTask = [self = weakRef_, isCapture, env = env_]() {
328         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnCaptureStatusChanged");
329         auto thisListener = self.promote();
330         if (thisListener == nullptr || env == nullptr) {
331             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
332             return;
333         }
334         napi_value argv[] = {CreateJsValue(env, isCapture)};
335         thisListener->CallJsMethod(EVENT_CAPTURE_STATUS_CHANGED, argv, ArraySize(argv));
336     };
337 
338     if (env_ != nullptr) {
339         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnCaptureStatusChanged");
340         if (ret != napi_status::napi_ok) {
341             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
342         }
343     } else {
344         TLOGE(WmsLogTag::DMS, "env is nullptr");
345     }
346 }
347 
OnDisplayModeChanged(FoldDisplayMode displayMode)348 void JsDisplayListener::OnDisplayModeChanged(FoldDisplayMode displayMode)
349 {
350     std::lock_guard<std::mutex> lock(mtx_);
351     TLOGI(WmsLogTag::DMS, "called, displayMode: %{public}u", static_cast<uint32_t>(displayMode));
352     if (jsCallBack_.empty()) {
353         TLOGE(WmsLogTag::DMS, "not register!");
354         return;
355     }
356     if (jsCallBack_.find(EVENT_DISPLAY_MODE_CHANGED) == jsCallBack_.end()) {
357         TLOGE(WmsLogTag::DMS, "not this event, return");
358         return;
359     }
360     auto napiTask = [self = weakRef_, displayMode, env = env_] () {
361         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnDisplayModeChanged");
362         auto thisListener = self.promote();
363         if (thisListener == nullptr || env == nullptr) {
364             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
365             return;
366         }
367         napi_value argv[] = {CreateJsValue(env, displayMode)};
368         thisListener->CallJsMethod(EVENT_DISPLAY_MODE_CHANGED, argv, ArraySize(argv));
369     };
370 
371     if (env_ != nullptr) {
372         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnDisplayModeChanged");
373         if (ret != napi_status::napi_ok) {
374             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
375         }
376     } else {
377         TLOGE(WmsLogTag::DMS, "env is nullptr");
378     }
379 }
380 
OnAvailableAreaChanged(DMRect area)381 void JsDisplayListener::OnAvailableAreaChanged(DMRect area)
382 {
383     std::lock_guard<std::mutex> lock(mtx_);
384     TLOGI(WmsLogTag::DMS, "called");
385     if (jsCallBack_.empty()) {
386         TLOGE(WmsLogTag::DMS, "not register!");
387         return;
388     }
389     if (jsCallBack_.find(EVENT_AVAILABLE_AREA_CHANGED) == jsCallBack_.end()) {
390         TLOGE(WmsLogTag::DMS, "not this event, return");
391         return;
392     }
393     auto napiTask = [self = weakRef_, area, env = env_]() {
394         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplayListener::OnAvailableAreaChanged");
395         auto thisListener = self.promote();
396         if (thisListener == nullptr || env == nullptr) {
397             TLOGNE(WmsLogTag::DMS, "[NAPI]this listener or env is nullptr");
398             return;
399         }
400         napi_value argv[] = {CreateJsRectObject(env, area)};
401         thisListener->CallJsMethod(EVENT_AVAILABLE_AREA_CHANGED, argv, ArraySize(argv));
402     };
403 
404     if (env_ != nullptr) {
405         napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate, "OnAvailableAreaChanged");
406         if (ret != napi_status::napi_ok) {
407             TLOGE(WmsLogTag::DMS, "Failed to SendEvent.");
408         }
409     } else {
410         TLOGE(WmsLogTag::DMS, "env is nullptr");
411     }
412 }
413 } // namespace Rosen
414 } // namespace OHOS
415