1 /*
2 * Copyright (c) 2023 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_screen_session.h"
17
18 #include <hitrace_meter.h>
19 #include <js_runtime_utils.h>
20
21 #include "interfaces/include/ws_common.h"
22 #include "js_screen_utils.h"
23 #include "window_manager_hilog.h"
24 #include "singleton_container.h"
25 #include "screen_manager.h"
26
27 namespace OHOS::Rosen {
28 using namespace AbilityRuntime;
29 namespace {
30 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "JsScreenSession" };
31 const std::string ON_CONNECTION_CALLBACK = "connect";
32 const std::string ON_DISCONNECTION_CALLBACK = "disconnect";
33 const std::string ON_PROPERTY_CHANGE_CALLBACK = "propertyChange";
34 const std::string ON_POWER_STATUS_CHANGE_CALLBACK = "powerStatusChange";
35 const std::string ON_SENSOR_ROTATION_CHANGE_CALLBACK = "sensorRotationChange";
36 const std::string ON_SCREEN_ORIENTATION_CHANGE_CALLBACK = "screenOrientationChange";
37 const std::string ON_SCREEN_ROTATION_LOCKED_CHANGE = "screenRotationLockedChange";
38 const std::string ON_SCREEN_DENSITY_CHANGE = "screenDensityChange";
39 const std::string ON_HOVER_STATUS_CHANGE_CALLBACK = "hoverStatusChange";
40 const std::string ON_SCREEN_CAPTURE_NOTIFY = "screenCaptureNotify";
41 const std::string ON_CAMERA_FOLD_STATUS_CHANGE_CALLBACK = "cameraStatusChange";
42 constexpr size_t ARGC_ONE = 1;
43 } // namespace
44
Create(napi_env env,const sptr<ScreenSession> & screenSession)45 napi_value JsScreenSession::Create(napi_env env, const sptr<ScreenSession>& screenSession)
46 {
47 WLOGD("Create.");
48 napi_value objValue = nullptr;
49 napi_create_object(env, &objValue);
50 if (objValue == nullptr) {
51 WLOGFE("[NAPI]Object is null!");
52 return NapiGetUndefined(env);
53 }
54
55 auto jsScreenSession = std::make_unique<JsScreenSession>(env, screenSession);
56 napi_wrap(env, objValue, jsScreenSession.release(), JsScreenSession::Finalizer, nullptr, nullptr);
57 napi_set_named_property(env, objValue, "screenId",
58 CreateJsValue(env, static_cast<int64_t>(screenSession->GetScreenId())));
59 napi_set_named_property(env, objValue, "name",
60 CreateJsValue(env, static_cast<std::string>(screenSession->GetName())));
61
62 const char* moduleName = "JsScreenSession";
63 BindNativeFunction(env, objValue, "on", moduleName, JsScreenSession::RegisterCallback);
64 BindNativeFunction(env, objValue, "setScreenRotationLocked", moduleName,
65 JsScreenSession::SetScreenRotationLocked);
66 BindNativeFunction(env, objValue, "setTouchEnabled", moduleName,
67 JsScreenSession::SetTouchEnabled);
68 BindNativeFunction(env, objValue, "loadContent", moduleName, JsScreenSession::LoadContent);
69 return objValue;
70 }
71
Finalizer(napi_env env,void * data,void * hint)72 void JsScreenSession::Finalizer(napi_env env, void* data, void* hint)
73 {
74 WLOGD("Finalizer.");
75 std::unique_ptr<JsScreenSession>(static_cast<JsScreenSession*>(data));
76 }
77
JsScreenSession(napi_env env,const sptr<ScreenSession> & screenSession)78 JsScreenSession::JsScreenSession(napi_env env, const sptr<ScreenSession>& screenSession)
79 : env_(env), screenSession_(screenSession)
80 {
81 std::string name = screenSession_ ? screenSession_->GetName() : "UNKNOWN";
82 screenScene_ = new(std::nothrow) ScreenScene(name);
83 if (screenSession_) {
84 SetScreenSceneDpiFunc func = [this](float density) {
85 TLOGI(WmsLogTag::DMS, "Screen Scene Dpi change, new density = %{public}f", density);
86 if (!screenScene_ || !screenSession_) {
87 TLOGE(WmsLogTag::DMS, "[NAPI]screenScene or screenSession is nullptr");
88 return;
89 }
90 auto screenBounds = screenSession_->GetScreenProperty().GetBounds();
91 Rect rect = { screenBounds.rect_.left_, screenBounds.rect_.top_,
92 screenBounds.rect_.width_, screenBounds.rect_.height_ };
93 screenScene_->SetDisplayDensity(density);
94 screenScene_->UpdateViewportConfig(rect, WindowSizeChangeReason::UPDATE_DPI_SYNC);
95 OnScreenDensityChange();
96 };
97 screenSession_->SetScreenSceneDpiChangeListener(func);
98 DestroyScreenSceneFunc destroyFunc = [screenScene = screenScene_]() {
99 if (screenScene) {
100 screenScene->Destroy();
101 }
102 };
103 screenSession_->SetScreenSceneDestroyListener(destroyFunc);
104 }
105 }
106
~JsScreenSession()107 JsScreenSession::~JsScreenSession()
108 {
109 WLOGI("~JsScreenSession");
110 }
111
LoadContent(napi_env env,napi_callback_info info)112 napi_value JsScreenSession::LoadContent(napi_env env, napi_callback_info info)
113 {
114 JsScreenSession* me = CheckParamsAndGetThis<JsScreenSession>(env, info);
115 return (me != nullptr) ? me->OnLoadContent(env, info) : nullptr;
116 }
117
OnLoadContent(napi_env env,napi_callback_info info)118 napi_value JsScreenSession::OnLoadContent(napi_env env, napi_callback_info info)
119 {
120 TLOGD(WmsLogTag::DMS, "[NAPI]JsScreenSession::OnLoadContent");
121 size_t argc = 4;
122 napi_value argv[4] = {nullptr}; // 4: params num
123 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
124 if (argc < 2) { // 2: params num
125 TLOGE(WmsLogTag::DMS, "[NAPI]Argc is invalid: %{public}zu", argc);
126 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_INVALID_PARAM),
127 "Input parameter is missing or invalid"));
128 return NapiGetUndefined(env);
129 }
130 std::string contentUrl;
131 napi_value context = argv[1]; // 1: context param index
132 napi_value storage = argc < 3 ? nullptr : argv[2]; // 3: params num; 2: storage param index
133 if (!ConvertFromJsValue(env, argv[0], contentUrl)) { // 0: page path param index
134 TLOGE(WmsLogTag::DMS, "[NAPI]Failed to convert parameter to content url");
135 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_INVALID_PARAM),
136 "Input parameter is missing or invalid"));
137 return NapiGetUndefined(env);
138 }
139
140 if (context == nullptr) {
141 TLOGE(WmsLogTag::DMS, "[NAPI]Failed to get context object");
142 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_STATE_ABNORMALLY)));
143 return NapiGetUndefined(env);
144 }
145 void* pointerResult = nullptr;
146 napi_unwrap(env, context, &pointerResult);
147 auto contextNativePointer = static_cast<std::weak_ptr<Context>*>(pointerResult);
148 if (contextNativePointer == nullptr) {
149 TLOGE(WmsLogTag::DMS, "[NAPI]Failed to get context pointer from js object");
150 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_STATE_ABNORMALLY)));
151 return NapiGetUndefined(env);
152 }
153 auto contextWeakPtr = *contextNativePointer;
154
155 std::shared_ptr<NativeReference> contentStorage = nullptr;
156 if (storage != nullptr) {
157 napi_ref ref = nullptr;
158 napi_create_reference(env, storage, 1, &ref);
159 contentStorage = std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref));
160 }
161
162 return ScheduleLoadContentTask(env, contentUrl, contextWeakPtr, contentStorage);
163 }
164
ScheduleLoadContentTask(napi_env env,const std::string & contentUrl,std::weak_ptr<Context> contextWeakPtr,std::shared_ptr<NativeReference> contentStorage)165 napi_value JsScreenSession::ScheduleLoadContentTask(napi_env env, const std::string& contentUrl,
166 std::weak_ptr<Context> contextWeakPtr, std::shared_ptr<NativeReference> contentStorage)
167 {
168 if (screenScene_ == nullptr) {
169 TLOGE(WmsLogTag::DMS, "[NAPI]screenScene is nullptr");
170 return NapiGetUndefined(env);
171 }
172 napi_value nativeStorage = contentStorage ? contentStorage->GetNapiValue() : nullptr;
173 screenScene_->LoadContent(contentUrl, env, nativeStorage, contextWeakPtr.lock().get());
174 if (screenSession_) {
175 screenSession_->SetScreenSceneDpi(screenSession_->GetScreenProperty().GetVirtualPixelRatio());
176 }
177 return NapiGetUndefined(env);
178 }
179
SetScreenRotationLocked(napi_env env,napi_callback_info info)180 napi_value JsScreenSession::SetScreenRotationLocked(napi_env env, napi_callback_info info)
181 {
182 JsScreenSession* me = CheckParamsAndGetThis<JsScreenSession>(env, info);
183 return (me != nullptr) ? me->OnSetScreenRotationLocked(env, info) : nullptr;
184 }
185
OnSetScreenRotationLocked(napi_env env,napi_callback_info info)186 napi_value JsScreenSession::OnSetScreenRotationLocked(napi_env env, napi_callback_info info)
187 {
188 WLOGI("JsScreenSession::OnSetScreenRotationLocked is called");
189 size_t argc = 4;
190 napi_value argv[4] = {nullptr};
191 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
192 if (argc < 1) {
193 WLOGFE("[NAPI]Argc is invalid: %{public}zu", argc);
194 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
195 return NapiGetUndefined(env);
196 }
197 bool isLocked = true;
198 napi_value nativeVal = argv[0];
199 if (nativeVal == nullptr) {
200 WLOGFE("ConvertNativeValueTo isLocked failed!");
201 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
202 return NapiGetUndefined(env);
203 }
204 napi_get_value_bool(env, nativeVal, &isLocked);
205 if (screenSession_ == nullptr) {
206 WLOGFE("Failed to register screen change listener, session is null!");
207 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
208 return NapiGetUndefined(env);
209 }
210 screenSession_->SetScreenRotationLockedFromJs(isLocked);
211 NapiAsyncTask::CompleteCallback complete =
212 [isLocked](napi_env env, NapiAsyncTask& task, int32_t status) {
213 auto res = DM_JS_TO_ERROR_CODE_MAP.at(
214 SingletonContainer::Get<ScreenManager>().SetScreenRotationLockedFromJs(isLocked));
215 if (res == DmErrorCode::DM_OK) {
216 task.Resolve(env, NapiGetUndefined(env));
217 WLOGFI("OnSetScreenRotationLocked success");
218 } else {
219 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
220 "JsScreenSession::OnSetScreenRotationLocked failed."));
221 WLOGFE("OnSetScreenRotationLocked failed");
222 }
223 };
224 napi_value result = nullptr;
225 NapiAsyncTask::Schedule("JsScreenSession::OnSetScreenRotationLocked",
226 env, CreateAsyncTaskWithLastParam(env, nullptr, nullptr, std::move(complete), &result));
227 WLOGFI("SetScreenRotationLocked %{public}u success.", static_cast<uint32_t>(isLocked));
228 return result;
229 }
230
SetTouchEnabled(napi_env env,napi_callback_info info)231 napi_value JsScreenSession::SetTouchEnabled(napi_env env, napi_callback_info info)
232 {
233 JsScreenSession* me = CheckParamsAndGetThis<JsScreenSession>(env, info);
234 return (me != nullptr) ? me->OnSetTouchEnabled(env, info) : nullptr;
235 }
236
OnSetTouchEnabled(napi_env env,napi_callback_info info)237 napi_value JsScreenSession::OnSetTouchEnabled(napi_env env, napi_callback_info info)
238 {
239 TLOGI(WmsLogTag::WMS_EVENT, "napi called");
240 size_t argc = 4;
241 napi_value argv[4] = {nullptr};
242 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
243 if (argc != ARGC_ONE) {
244 TLOGE(WmsLogTag::WMS_EVENT, "[NAPI]Argc is invalid: %{public}zu", argc);
245 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
246 return NapiGetUndefined(env);
247 }
248 bool isTouchEnabled = true;
249 napi_value nativeVal = argv[0];
250 if (nativeVal == nullptr) {
251 TLOGE(WmsLogTag::WMS_EVENT, "ConvertNativeValueTo isTouchEnabled failed!");
252 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
253 return NapiGetUndefined(env);
254 }
255 napi_get_value_bool(env, nativeVal, &isTouchEnabled);
256 if (screenSession_ == nullptr) {
257 TLOGE(WmsLogTag::WMS_EVENT, "Failed to register screen change listener, session is null!");
258 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
259 return NapiGetUndefined(env);
260 }
261 screenSession_->SetTouchEnabledFromJs(isTouchEnabled);
262 return NapiGetUndefined(env);
263 }
264
RegisterScreenChangeListener()265 void JsScreenSession::RegisterScreenChangeListener()
266 {
267 if (screenSession_ == nullptr) {
268 WLOGFE("Failed to register screen change listener, session is null!");
269 return;
270 }
271
272 screenSession_->RegisterScreenChangeListener(this);
273 WLOGFI("register screen change listener success.");
274 }
275
RegisterCallback(napi_env env,napi_callback_info info)276 napi_value JsScreenSession::RegisterCallback(napi_env env, napi_callback_info info)
277 {
278 WLOGD("Register callback.");
279 JsScreenSession* me = CheckParamsAndGetThis<JsScreenSession>(env, info);
280 return (me != nullptr) ? me->OnRegisterCallback(env, info) : nullptr;
281 }
282
UnRegisterScreenChangeListener()283 void JsScreenSession::UnRegisterScreenChangeListener()
284 {
285 if (screenSession_ == nullptr) {
286 WLOGFE("Failed to unregister screen change listener, session is null!");
287 return;
288 }
289
290 screenSession_->UnregisterScreenChangeListener(this);
291 WLOGFI("unregister screen change listener success.");
292 }
293
294
OnRegisterCallback(napi_env env,napi_callback_info info)295 napi_value JsScreenSession::OnRegisterCallback(napi_env env, napi_callback_info info)
296 {
297 WLOGI("On register callback.");
298 size_t argc = 4;
299 napi_value argv[4] = {nullptr};
300 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
301 if (argc < 2) { // 2: params num
302 WLOGFE("Argc is invalid: %{public}zu", argc);
303 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_INVALID_PARAM)));
304 return NapiGetUndefined(env);
305 }
306
307 std::string callbackType;
308 if (!ConvertFromJsValue(env, argv[0], callbackType)) {
309 WLOGFE("Failed to convert parameter to callback type.");
310 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_INVALID_PARAM)));
311 return NapiGetUndefined(env);
312 }
313
314 napi_value callback = argv[1];
315 if (!NapiIsCallable(env, callback)) {
316 WLOGFE("Failed to register callback, callback is not callable!");
317 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_INVALID_PARAM)));
318 return NapiGetUndefined(env);
319 }
320
321 if (mCallback_.count(callbackType)) {
322 WLOGFE("Failed to register callback, callback is already existed!");
323 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WSErrorCode::WS_ERROR_REPEAT_OPERATION)));
324 return NapiGetUndefined(env);
325 }
326
327 napi_ref result = nullptr;
328 napi_create_reference(env, callback, 1, &result);
329 std::shared_ptr<NativeReference> callbackRef(reinterpret_cast<NativeReference*>(result));
330 mCallback_[callbackType] = callbackRef;
331 RegisterScreenChangeListener();
332
333 return NapiGetUndefined(env);
334 }
335
CallJsCallback(const std::string & callbackType)336 void JsScreenSession::CallJsCallback(const std::string& callbackType)
337 {
338 WLOGI("Call js callback: %{public}s.", callbackType.c_str());
339 if (mCallback_.count(callbackType) == 0) {
340 WLOGFE("Callback is unregistered!");
341 return;
342 }
343
344 if (callbackType == ON_DISCONNECTION_CALLBACK) {
345 WLOGFE("Call js callback %{public}s start", callbackType.c_str());
346 UnRegisterScreenChangeListener();
347 }
348
349 auto jsCallbackRef = mCallback_[callbackType];
350 wptr<ScreenSession> screenSessionWeak(screenSession_);
351 auto complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
352 [jsCallbackRef, callbackType, screenSessionWeak](napi_env env, NapiAsyncTask& task, int32_t status) {
353 if (jsCallbackRef == nullptr) {
354 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
355 return;
356 }
357 auto method = jsCallbackRef->GetNapiValue();
358 if (method == nullptr) {
359 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
360 return;
361 }
362 if (callbackType == ON_CONNECTION_CALLBACK || callbackType == ON_DISCONNECTION_CALLBACK) {
363 auto screenSession = screenSessionWeak.promote();
364 if (screenSession == nullptr) {
365 WLOGFE("Call js callback %{public}s failed, screenSession is null!", callbackType.c_str());
366 return;
367 }
368 napi_value argv[] = { JsScreenUtils::CreateJsScreenProperty(
369 env, screenSession->GetScreenProperty()) };
370 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
371 } else {
372 napi_value argv[] = {};
373 napi_call_function(env, NapiGetUndefined(env), method, 0, argv, nullptr);
374 }
375 WLOGI("The js callback has been executed: %{public}s.", callbackType.c_str());
376 });
377
378 napi_ref callback = nullptr;
379 std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
380 NapiAsyncTask::Schedule("JsScreenSession::" + callbackType, env_,
381 std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
382 }
383
OnConnect(ScreenId screenId)384 void JsScreenSession::OnConnect(ScreenId screenId)
385 {
386 CallJsCallback(ON_CONNECTION_CALLBACK);
387 }
388
OnDisconnect(ScreenId screenId)389 void JsScreenSession::OnDisconnect(ScreenId screenId)
390 {
391 CallJsCallback(ON_DISCONNECTION_CALLBACK);
392 }
393
OnSensorRotationChange(float sensorRotation,ScreenId screenId)394 void JsScreenSession::OnSensorRotationChange(float sensorRotation, ScreenId screenId)
395 {
396 const std::string callbackType = ON_SENSOR_ROTATION_CHANGE_CALLBACK;
397 if (mCallback_.count(callbackType) == 0) {
398 WLOGFE("Callback %{public}s is unregistered!", callbackType.c_str());
399 return;
400 }
401
402 auto jsCallbackRef = mCallback_[callbackType];
403 wptr<ScreenSession> screenSessionWeak(screenSession_);
404 auto napiTask = [jsCallbackRef, callbackType, screenSessionWeak, sensorRotation, env = env_]() {
405 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "jsScreenSession::OnSensorRotationChange");
406 if (jsCallbackRef == nullptr) {
407 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
408 return;
409 }
410 auto method = jsCallbackRef->GetNapiValue();
411 if (method == nullptr) {
412 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
413 return;
414 }
415 auto screenSession = screenSessionWeak.promote();
416 if (screenSession == nullptr) {
417 WLOGFE("Call js callback %{public}s failed, screenSession is null!", callbackType.c_str());
418 return;
419 }
420 napi_value argv[] = { CreateJsValue(env, sensorRotation) };
421 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
422 };
423
424 if (env_ != nullptr) {
425 napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate);
426 if (ret != napi_status::napi_ok) {
427 WLOGFE("OnSensorRotationChange: Failed to SendEvent.");
428 }
429 } else {
430 WLOGFE("OnSensorRotationChange: env is nullptr");
431 }
432 }
433
OnScreenOrientationChange(float screenOrientation,ScreenId screenId)434 void JsScreenSession::OnScreenOrientationChange(float screenOrientation, ScreenId screenId)
435 {
436 const std::string callbackType = ON_SCREEN_ORIENTATION_CHANGE_CALLBACK;
437 WLOGI("Call js callback: %{public}s.", callbackType.c_str());
438 if (mCallback_.count(callbackType) == 0) {
439 WLOGFE("Callback %{public}s is unregistered!", callbackType.c_str());
440 return;
441 }
442
443 auto jsCallbackRef = mCallback_[callbackType];
444 wptr<ScreenSession> screenSessionWeak(screenSession_);
445 auto complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
446 [jsCallbackRef, callbackType, screenSessionWeak, screenOrientation](
447 napi_env env, NapiAsyncTask& task, int32_t status) {
448 if (jsCallbackRef == nullptr) {
449 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
450 return;
451 }
452 auto method = jsCallbackRef->GetNapiValue();
453 if (method == nullptr) {
454 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
455 return;
456 }
457 auto screenSession = screenSessionWeak.promote();
458 if (screenSession == nullptr) {
459 WLOGFE("Call js callback %{public}s failed, screenSession is null!", callbackType.c_str());
460 return;
461 }
462 napi_value argv[] = { CreateJsValue(env, screenOrientation) };
463 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
464 });
465
466 napi_ref callback = nullptr;
467 std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
468 NapiAsyncTask::Schedule("JsScreenSession::" + callbackType, env_,
469 std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
470 }
471
OnPropertyChange(const ScreenProperty & newProperty,ScreenPropertyChangeReason reason,ScreenId screenId)472 void JsScreenSession::OnPropertyChange(const ScreenProperty& newProperty, ScreenPropertyChangeReason reason,
473 ScreenId screenId)
474 {
475 const std::string callbackType = ON_PROPERTY_CHANGE_CALLBACK;
476 WLOGD("Call js callback: %{public}s.", callbackType.c_str());
477 if (mCallback_.count(callbackType) == 0) {
478 WLOGFE("Callback %{public}s is unregistered!", callbackType.c_str());
479 return;
480 }
481
482 auto jsCallbackRef = mCallback_[callbackType];
483 wptr<ScreenSession> screenSessionWeak(screenSession_);
484 auto napiTask = [jsCallbackRef, callbackType, screenSessionWeak, newProperty, reason, env = env_]() {
485 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "jsScreenSession::OnPropertyChange");
486 if (jsCallbackRef == nullptr) {
487 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
488 return;
489 }
490 auto method = jsCallbackRef->GetNapiValue();
491 if (method == nullptr) {
492 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
493 return;
494 }
495 auto screenSession = screenSessionWeak.promote();
496 if (screenSession == nullptr) {
497 WLOGFE("Call js callback %{public}s failed, screenSession is null!", callbackType.c_str());
498 return;
499 }
500 napi_value propertyChangeReason = CreateJsValue(env, static_cast<int32_t>(reason));
501 napi_value argv[] = { JsScreenUtils::CreateJsScreenProperty(env, newProperty), propertyChangeReason };
502 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
503 };
504
505 if (env_ != nullptr) {
506 napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate);
507 if (ret != napi_status::napi_ok) {
508 WLOGFE("OnPropertyChange: Failed to SendEvent.");
509 }
510 } else {
511 WLOGFE("OnPropertyChange: env is nullptr");
512 }
513 }
514
OnScreenDensityChange()515 void JsScreenSession::OnScreenDensityChange()
516 {
517 WLOGD("Call js callback: screenDensityChange.");
518 if (mCallback_.count(ON_SCREEN_DENSITY_CHANGE) == 0) {
519 WLOGFE("Callback screenDensityChange is unregistered!");
520 return;
521 }
522
523 auto jsCallbackRef = mCallback_[ON_SCREEN_DENSITY_CHANGE];
524 wptr<ScreenSession> screenSessionWeak(screenSession_);
525 auto complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
526 [jsCallbackRef, screenSessionWeak](
527 napi_env env, NapiAsyncTask& task, int32_t status) {
528 if (jsCallbackRef == nullptr) {
529 WLOGFE("Call js callback screenDensityChange failed, jsCallbackRef is null!");
530 return;
531 }
532 auto method = jsCallbackRef->GetNapiValue();
533 if (method == nullptr) {
534 WLOGFE("Call js callback screenDensityChange failed, method is null!");
535 return;
536 }
537 auto screenSession = screenSessionWeak.promote();
538 if (screenSession == nullptr) {
539 WLOGFE("Call js callback screenDensityChange failed, screenSession is null!");
540 return;
541 }
542 napi_value argv[] = {};
543 napi_call_function(env, NapiGetUndefined(env), method, 0, argv, nullptr);
544 });
545
546 napi_ref callback = nullptr;
547 std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
548 NapiAsyncTask::Schedule("JsScreenSession::screenDensityChange", env_,
549 std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
550 }
551
OnPowerStatusChange(DisplayPowerEvent event,EventStatus eventStatus,PowerStateChangeReason reason)552 void JsScreenSession::OnPowerStatusChange(DisplayPowerEvent event, EventStatus eventStatus,
553 PowerStateChangeReason reason)
554 {
555 const std::string callbackType = ON_POWER_STATUS_CHANGE_CALLBACK;
556 WLOGD("[UL_POWER]%{public}s.", callbackType.c_str());
557 if (mCallback_.count(callbackType) == 0) {
558 WLOGFW("[UL_POWER]%{public}s is unregistered!", callbackType.c_str());
559 return;
560 }
561 auto jsCallbackRef = mCallback_[callbackType];
562 wptr<ScreenSession> screenSessionWeak(screenSession_);
563 auto asyncTask = [jsCallbackRef, callbackType, screenSessionWeak, event, eventStatus, reason, env = env_]() {
564 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "jsScreenSession::OnPowerStatusChange");
565 if (jsCallbackRef == nullptr) {
566 WLOGFE("[UL_POWER]%{public}s failed, jsCallbackRef is null!", callbackType.c_str());
567 return;
568 }
569 auto method = jsCallbackRef->GetNapiValue();
570 if (method == nullptr) {
571 WLOGFE("[UL_POWER]%{public}s failed, method is null!", callbackType.c_str());
572 return;
573 }
574 auto screenSession = screenSessionWeak.promote();
575 if (screenSession == nullptr) {
576 WLOGFE("[UL_POWER]%{public}s failed, screenSession is null!", callbackType.c_str());
577 return;
578 }
579 napi_value displayPowerEvent = CreateJsValue(env, static_cast<int32_t>(event));
580 napi_value powerEventStatus = CreateJsValue(env, static_cast<int32_t>(eventStatus));
581 napi_value powerStateChangeReason = CreateJsValue(env, static_cast<int32_t>(reason));
582 napi_value argv[] = { displayPowerEvent, powerEventStatus, powerStateChangeReason };
583 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
584 };
585
586 if (env_ != nullptr) {
587 napi_status ret = napi_send_event(env_, asyncTask, napi_eprio_vip);
588 if (ret != napi_status::napi_ok) {
589 WLOGFE("OnPowerStatusChange: Failed to SendEvent.");
590 } else {
591 WLOGFI("OnPowerStatusChange: Sucess to SendEvent.");
592 }
593 } else {
594 WLOGFE("OnPowerStatusChange: env is nullptr");
595 }
596 }
597
OnScreenRotationLockedChange(bool isLocked,ScreenId screenId)598 void JsScreenSession::OnScreenRotationLockedChange(bool isLocked, ScreenId screenId)
599 {
600 const std::string callbackType = ON_SCREEN_ROTATION_LOCKED_CHANGE;
601 WLOGD("Call js callback: %{public}s isLocked:%{public}u.", callbackType.c_str(), isLocked);
602 if (mCallback_.count(callbackType) == 0) {
603 WLOGFE("Callback %{public}s is unregistered!", callbackType.c_str());
604 return;
605 }
606
607 auto jsCallbackRef = mCallback_[callbackType];
608 auto complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
609 [jsCallbackRef, callbackType, isLocked](napi_env env, NapiAsyncTask& task, int32_t status) {
610 if (jsCallbackRef == nullptr) {
611 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
612 return;
613 }
614 auto method = jsCallbackRef->GetNapiValue();
615 if (method == nullptr) {
616 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
617 return;
618 }
619 napi_value argv[] = { CreateJsValue(env, isLocked) };
620 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
621 });
622
623 napi_ref callback = nullptr;
624 std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
625 NapiAsyncTask::Schedule("JsScreenSession::" + callbackType, env_,
626 std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
627 }
628
OnHoverStatusChange(int32_t hoverStatus,ScreenId screenId)629 void JsScreenSession::OnHoverStatusChange(int32_t hoverStatus, ScreenId screenId)
630 {
631 const std::string callbackType = ON_HOVER_STATUS_CHANGE_CALLBACK;
632 WLOGI("Call js callback: %{public}s.", callbackType.c_str());
633 if (mCallback_.count(callbackType) == 0) {
634 WLOGFE("Callback %{public}s is unregistered!", callbackType.c_str());
635 return;
636 }
637
638 auto jsCallbackRef = mCallback_[callbackType];
639 wptr<ScreenSession> screenSessionWeak(screenSession_);
640 auto napiTask = [jsCallbackRef, callbackType, screenSessionWeak, hoverStatus, env = env_]() {
641 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "jsScreenSession::OnHoverStatusChange");
642 if (jsCallbackRef == nullptr) {
643 WLOGFE("Call js callback %{public}s failed, jsCallbackRef is null!", callbackType.c_str());
644 return;
645 }
646 auto method = jsCallbackRef->GetNapiValue();
647 if (method == nullptr) {
648 WLOGFE("Call js callback %{public}s failed, method is null!", callbackType.c_str());
649 return;
650 }
651 auto screenSession = screenSessionWeak.promote();
652 if (screenSession == nullptr) {
653 WLOGFE("Call js callback %{public}s failed, screenSession is null!", callbackType.c_str());
654 return;
655 }
656 napi_value argv[] = { CreateJsValue(env, hoverStatus) };
657 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
658 };
659 if (env_ != nullptr) {
660 napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate);
661 if (ret != napi_status::napi_ok) {
662 WLOGFE("OnHoverStatusChange: Failed to SendEvent.");
663 }
664 } else {
665 WLOGFE("OnHoverStatusChange: env is nullptr");
666 }
667 }
668
OnScreenCaptureNotify(ScreenId mainScreenId,int32_t uid,const std::string & clientName)669 void JsScreenSession::OnScreenCaptureNotify(ScreenId mainScreenId, int32_t uid, const std::string& clientName)
670 {
671 const std::string callbackType = ON_SCREEN_CAPTURE_NOTIFY;
672 if (mCallback_.count(callbackType) == 0) {
673 WLOGFW("Callback is unregistered!");
674 return;
675 }
676 auto jsCallbackRef = mCallback_[callbackType];
677 auto asyncTask = [jsCallbackRef, callbackType, mainScreenId, uid, clientName, env = env_]() {
678 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "jsScreenSession::OnScreenCaptureNotify");
679 if (jsCallbackRef == nullptr) {
680 WLOGFE("Call js callback failed, jsCallbackRef is null!");
681 return;
682 }
683 auto method = jsCallbackRef->GetNapiValue();
684 if (method == nullptr) {
685 WLOGFE("Call js callback failed, method is null!");
686 return;
687 }
688 napi_value mainId = CreateJsValue(env, static_cast<int64_t>(mainScreenId));
689 napi_value clientUid = CreateJsValue(env, uid);
690 napi_value client = CreateJsValue(env, clientName);
691 napi_value argv[] = { mainId, clientUid, client };
692 napi_call_function(env, NapiGetUndefined(env), method, ArraySize(argv), argv, nullptr);
693 };
694 if (env_ != nullptr) {
695 napi_status ret = napi_send_event(env_, asyncTask, napi_eprio_immediate);
696 if (ret != napi_status::napi_ok) {
697 WLOGFE("OnScreenCaptureNotify: Failed to SendEvent.");
698 }
699 } else {
700 WLOGFE("OnScreenCaptureNotify: env is nullptr");
701 }
702 }
703 } // namespace OHOS::Rosen
704