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_screen_manager.h"
17
18 #include <cinttypes>
19 #include <vector>
20 #include <new>
21 #include "js_runtime_utils.h"
22 #include "js_screen.h"
23 #include "js_screen_listener.h"
24 #include "native_engine/native_reference.h"
25 #include "screen_manager.h"
26 #include "singleton_container.h"
27 #include "surface_utils.h"
28 #include "window_manager_hilog.h"
29
30 namespace OHOS {
31 namespace Rosen {
32 using namespace AbilityRuntime;
33 constexpr size_t ARGC_ONE = 1;
34 constexpr size_t ARGC_TWO = 2;
35 constexpr size_t ARGC_THREE = 3;
36 constexpr int32_t INDEX_ZERO = 0;
37 constexpr int32_t INDEX_ONE = 1;
38 constexpr int32_t INDEX_TWO = 2;
39 constexpr uint32_t MAX_SCREENS_NUM = 1000;
40 namespace {
41 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsScreenManager"};
42 }
43
44 class JsScreenManager {
45 public:
JsScreenManager(napi_env env)46 explicit JsScreenManager(napi_env env) {
47 }
48
49 ~JsScreenManager() = default;
50
Finalizer(napi_env env,void * data,void * hint)51 static void Finalizer(napi_env env, void* data, void* hint)
52 {
53 WLOGI("JsScreenManager::Finalizer is called");
54 std::unique_ptr<JsScreenManager>(static_cast<JsScreenManager*>(data));
55 }
56
GetAllScreens(napi_env env,napi_callback_info info)57 static napi_value GetAllScreens(napi_env env, napi_callback_info info)
58 {
59 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
60 return (me != nullptr) ? me->OnGetAllScreens(env, info) : nullptr;
61 }
62
RegisterScreenManagerCallback(napi_env env,napi_callback_info info)63 static napi_value RegisterScreenManagerCallback(napi_env env, napi_callback_info info)
64 {
65 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
66 return (me != nullptr) ? me->OnRegisterScreenManagerCallback(env, info) : nullptr;
67 }
68
UnregisterScreenMangerCallback(napi_env env,napi_callback_info info)69 static napi_value UnregisterScreenMangerCallback(napi_env env, napi_callback_info info)
70 {
71 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
72 return (me != nullptr) ? me->OnUnregisterScreenManagerCallback(env, info) : nullptr;
73 }
74
MakeMirror(napi_env env,napi_callback_info info)75 static napi_value MakeMirror(napi_env env, napi_callback_info info)
76 {
77 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
78 return (me != nullptr) ? me->OnMakeMirror(env, info) : nullptr;
79 }
80
MakeMirrorWithRegion(napi_env env,napi_callback_info info)81 static napi_value MakeMirrorWithRegion(napi_env env, napi_callback_info info)
82 {
83 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
84 return (me != nullptr) ? me->OnMakeMirrorWithRegion(env, info) : nullptr;
85 }
86
MakeExpand(napi_env env,napi_callback_info info)87 static napi_value MakeExpand(napi_env env, napi_callback_info info)
88 {
89 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
90 return (me != nullptr) ? me->OnMakeExpand(env, info) : nullptr;
91 }
92
StopMirror(napi_env env,napi_callback_info info)93 static napi_value StopMirror(napi_env env, napi_callback_info info)
94 {
95 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
96 return (me != nullptr) ? me->OnStopMirror(env, info) : nullptr;
97 }
98
StopExpand(napi_env env,napi_callback_info info)99 static napi_value StopExpand(napi_env env, napi_callback_info info)
100 {
101 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
102 return (me != nullptr) ? me->OnStopExpand(env, info) : nullptr;
103 }
104
CreateVirtualScreen(napi_env env,napi_callback_info info)105 static napi_value CreateVirtualScreen(napi_env env, napi_callback_info info)
106 {
107 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
108 return (me != nullptr) ? me->OnCreateVirtualScreen(env, info) : nullptr;
109 }
110
DestroyVirtualScreen(napi_env env,napi_callback_info info)111 static napi_value DestroyVirtualScreen(napi_env env, napi_callback_info info)
112 {
113 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
114 return (me != nullptr) ? me->OnDestroyVirtualScreen(env, info) : nullptr;
115 }
116
SetVirtualScreenSurface(napi_env env,napi_callback_info info)117 static napi_value SetVirtualScreenSurface(napi_env env, napi_callback_info info)
118 {
119 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
120 return (me != nullptr) ? me->OnSetVirtualScreenSurface(env, info) : nullptr;
121 }
122
IsScreenRotationLocked(napi_env env,napi_callback_info info)123 static napi_value IsScreenRotationLocked(napi_env env, napi_callback_info info)
124 {
125 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
126 return (me != nullptr) ? me->OnIsScreenRotationLocked(env, info) : nullptr;
127 }
128
SetScreenRotationLocked(napi_env env,napi_callback_info info)129 static napi_value SetScreenRotationLocked(napi_env env, napi_callback_info info)
130 {
131 JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(env, info);
132 return (me != nullptr) ? me->OnSetScreenRotationLocked(env, info) : nullptr;
133 }
134 private:
135 std::map<std::string, std::map<std::unique_ptr<NativeReference>, sptr<JsScreenListener>>> jsCbMap_;
136 std::mutex mtx_;
137
OnGetAllScreens(napi_env env,napi_callback_info info)138 napi_value OnGetAllScreens(napi_env env, napi_callback_info info)
139 {
140 WLOGI("OnGetAllScreens is called");
141 NapiAsyncTask::CompleteCallback complete =
142 [this](napi_env env, NapiAsyncTask& task, int32_t status) {
143 std::vector<sptr<Screen>> screens;
144 auto res = DM_JS_TO_ERROR_CODE_MAP.at(SingletonContainer::Get<ScreenManager>().GetAllScreens(screens));
145 if (res != DmErrorCode::DM_OK) {
146 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
147 "JsScreenManager::OnGetAllScreens failed."));
148 } else if (!screens.empty()) {
149 task.Resolve(env, CreateJsScreenVectorObject(env, screens));
150 WLOGI("JsScreenManager::OnGetAllScreens success");
151 } else {
152 task.Reject(env, CreateJsError(env,
153 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN),
154 "JsScreenManager::OnGetAllScreens failed."));
155 }
156 };
157 size_t argc = 4;
158 napi_value argv[4] = {nullptr};
159 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
160 napi_value lastParam = nullptr;
161 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
162 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
163 lastParam = argv[ARGC_ONE - 1];
164 }
165 napi_value result = nullptr;
166 NapiAsyncTask::Schedule("JsScreenManager::OnGetAllScreens",
167 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
168 return result;
169 }
170
CreateJsScreenVectorObject(napi_env env,std::vector<sptr<Screen>> & screens)171 napi_value CreateJsScreenVectorObject(napi_env env, std::vector<sptr<Screen>>& screens)
172 {
173 napi_value arrayValue = nullptr;
174 napi_create_array_with_length(env, screens.size(), &arrayValue);
175 if (arrayValue == nullptr) {
176 WLOGFE("Failed to get screens");
177 return NapiGetUndefined(env);
178 }
179 size_t i = 0;
180 for (auto& screen : screens) {
181 if (screen == nullptr) {
182 continue;
183 }
184 napi_set_element(env, arrayValue, i++, CreateJsScreenObject(env, screen));
185 }
186 return arrayValue;
187 }
188
IfCallbackRegistered(napi_env env,const std::string & type,napi_value jsListenerObject)189 bool IfCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject)
190 {
191 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
192 WLOGI("JsScreenManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str());
193 return false;
194 }
195
196 for (auto& iter : jsCbMap_[type]) {
197 bool isEquals = false;
198 napi_strict_equals(env, jsListenerObject, iter.first->GetNapiValue(), &isEquals);
199 if (isEquals) {
200 WLOGFE("JsScreenManager::IfCallbackRegistered callback already registered!");
201 return true;
202 }
203 }
204 return false;
205 }
206
RegisterScreenListenerWithType(napi_env env,const std::string & type,napi_value value)207 DmErrorCode RegisterScreenListenerWithType(napi_env env, const std::string& type, napi_value value)
208 {
209 if (IfCallbackRegistered(env, type, value)) {
210 WLOGFE("JsScreenManager::RegisterScreenListenerWithType callback already registered!");
211 return DmErrorCode::DM_ERROR_INVALID_CALLING;
212 }
213 std::unique_ptr<NativeReference> callbackRef;
214 napi_ref result = nullptr;
215 napi_create_reference(env, value, 1, &result);
216 callbackRef.reset(reinterpret_cast<NativeReference*>(result));
217 sptr<JsScreenListener> screenListener = new(std::nothrow) JsScreenListener(env);
218 if (screenListener == nullptr) {
219 WLOGFE("screenListener is nullptr");
220 return DmErrorCode::DM_ERROR_INVALID_SCREEN;
221 }
222 if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
223 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(
224 SingletonContainer::Get<ScreenManager>().RegisterScreenListener(screenListener));
225 if (ret != DmErrorCode::DM_OK) {
226 return ret;
227 }
228 WLOGI("JsScreenManager::RegisterScreenListenerWithType success");
229 } else {
230 WLOGFE("JsScreenManager::RegisterScreenListenerWithType failed method: %{public}s not support!",
231 type.c_str());
232 return DmErrorCode::DM_ERROR_INVALID_CALLING;
233 }
234 screenListener->AddCallback(type, value);
235 jsCbMap_[type][std::move(callbackRef)] = screenListener;
236 return DmErrorCode::DM_OK;
237 }
238
UnregisterAllScreenListenerWithType(const std::string & type)239 DmErrorCode UnregisterAllScreenListenerWithType(const std::string& type)
240 {
241 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
242 WLOGFE("JsScreenManager::UnregisterAllScreenListenerWithType methodName %{public}s not registered!",
243 type.c_str());
244 return DmErrorCode::DM_OK;
245 }
246 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
247 it->second->RemoveAllCallback();
248 if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
249 sptr<ScreenManager::IScreenListener> thisListener(it->second);
250 SingletonContainer::Get<ScreenManager>().UnregisterScreenListener(thisListener);
251 WLOGI("JsScreenManager::UnregisterAllScreenListenerWithType success");
252 }
253 jsCbMap_[type].erase(it++);
254 }
255 jsCbMap_.erase(type);
256 return DmErrorCode::DM_OK;
257 }
258
UnRegisterScreenListenerWithType(napi_env env,const std::string & type,napi_value value)259 DmErrorCode UnRegisterScreenListenerWithType(napi_env env, const std::string& type, napi_value value)
260 {
261 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
262 WLOGI("JsScreenManager::UnRegisterScreenListenerWithType methodName %{public}s not registered!",
263 type.c_str());
264 return DmErrorCode::DM_OK;
265 }
266 if (value == nullptr) {
267 WLOGFE("JsScreenManager::UnRegisterScreenListenerWithType value is nullptr");
268 return DmErrorCode::DM_ERROR_INVALID_SCREEN;
269 }
270 DmErrorCode ret = DmErrorCode::DM_OK;
271 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
272 bool isEquals = false;
273 napi_strict_equals(env, value, it->first->GetNapiValue(), &isEquals);
274 if (isEquals) {
275 it->second->RemoveCallback(env, type, value);
276 if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
277 sptr<ScreenManager::IScreenListener> thisListener(it->second);
278 ret = DM_JS_TO_ERROR_CODE_MAP.at(
279 SingletonContainer::Get<ScreenManager>().UnregisterScreenListener(thisListener));
280 }
281 jsCbMap_[type].erase(it++);
282 break;
283 } else {
284 it++;
285 }
286 }
287 if (jsCbMap_[type].empty()) {
288 jsCbMap_.erase(type);
289 }
290 if (ret == DmErrorCode::DM_OK) {
291 WLOGFI("JsScreenManager::UnRegisterScreenListenerWithType success");
292 }
293 return ret;
294 }
295
NapiIsCallable(napi_env env,napi_value value)296 bool NapiIsCallable(napi_env env, napi_value value)
297 {
298 bool result = false;
299 napi_is_callable(env, value, &result);
300 return result;
301 }
302
NapiThrowError(napi_env env,DmErrorCode errCode,std::string msg="")303 napi_value NapiThrowError(napi_env env, DmErrorCode errCode, std::string msg = "")
304 {
305 napi_throw(env, CreateJsError(env, static_cast<int32_t>(errCode), msg));
306 return NapiGetUndefined(env);
307 }
308
OnRegisterScreenManagerCallback(napi_env env,napi_callback_info info)309 napi_value OnRegisterScreenManagerCallback(napi_env env, napi_callback_info info)
310 {
311 WLOGI("JsScreenManager::OnRegisterScreenManagerCallback is called");
312 size_t argc = 4;
313 napi_value argv[4] = {nullptr};
314 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
315 if (argc < ARGC_TWO) {
316 WLOGFE("Invalid args count, need 2 args!");
317 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, 2 args is needed.");
318 }
319 std::string cbType;
320 if (!ConvertFromJsValue(env, argv[0], cbType)) {
321 WLOGFE("Failed to convert parameter to eventType");
322 std::string errMsg = "Failed to convert parameter to eventType";
323 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
324 }
325 napi_value value = argv[INDEX_ONE];
326 if (value == nullptr) {
327 WLOGI("JsScreenManager::OnRegisterScreenManagerCallback argv[1] is nullptr");
328 std::string errMsg = "OnRegisterScreenManagerCallback error, argv[1] is nullptr";
329 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
330 }
331 if (!NapiIsCallable(env, value)) {
332 WLOGI("JsScreenManager::OnRegisterScreenManagerCallback argv[1] is not callable");
333 std::string errMsg = "OnRegisterScreenManagerCallback error, argv[1] is not callable";
334 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
335 }
336 std::lock_guard<std::mutex> lock(mtx_);
337 DmErrorCode ret = RegisterScreenListenerWithType(env, cbType, value);
338 if (ret != DmErrorCode::DM_OK) {
339 WLOGFE("JsScreenManager::OnRegisterScreenManagerCallback failed");
340 napi_throw(env, CreateJsError(env, static_cast<int32_t>(ret)));
341 }
342 return NapiGetUndefined(env);
343 }
344
OnUnregisterScreenManagerCallback(napi_env env,napi_callback_info info)345 napi_value OnUnregisterScreenManagerCallback(napi_env env, napi_callback_info info)
346 {
347 WLOGI("JsScreenManager::OnUnregisterScreenCallback is called");
348 size_t argc = 4;
349 napi_value argv[4] = {nullptr};
350 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
351 if (argc < ARGC_ONE) {
352 WLOGFE("Invalid args count, need one arg at least!");
353 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need one arg at least!");
354 }
355 std::string cbType;
356 if (!ConvertFromJsValue(env, argv[0], cbType)) {
357 WLOGFE("Failed to convert parameter to eventType");
358 std::string errMsg = "Failed to convert parameter to eventType";
359 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
360 }
361 std::lock_guard<std::mutex> lock(mtx_);
362 if (argc == ARGC_ONE) {
363 DmErrorCode ret = UnregisterAllScreenListenerWithType(cbType);
364 if (ret != DmErrorCode::DM_OK) {
365 WLOGFE("unregister all callback failed");
366 napi_throw(env, CreateJsError(env, static_cast<int32_t>(ret)));
367 }
368 } else {
369 napi_value value = argv[INDEX_ONE];
370 if ((value == nullptr) || (!NapiIsCallable(env, value))) {
371 DmErrorCode ret = UnregisterAllScreenListenerWithType(cbType);
372 if (ret != DmErrorCode::DM_OK) {
373 WLOGFE("JsScreenManager::OnUnRegisterAllScreenManagerCallback failed");
374 napi_throw(env, CreateJsError(env, static_cast<int32_t>(ret)));
375 }
376 } else {
377 DmErrorCode ret = UnRegisterScreenListenerWithType(env, cbType, value);
378 if (ret != DmErrorCode::DM_OK) {
379 WLOGFE("JsScreenManager::OnUnRegisterScreenManagerCallback failed");
380 napi_throw(env, CreateJsError(env, static_cast<int32_t>(ret)));
381 }
382 }
383 }
384 return NapiGetUndefined(env);
385 }
386
OnMakeMirror(napi_env env,napi_callback_info info)387 napi_value OnMakeMirror(napi_env env, napi_callback_info info)
388 {
389 WLOGI("OnMakeMirror is called");
390 size_t argc = 4;
391 napi_value argv[4] = {nullptr};
392 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
393 if (argc < ARGC_TWO) {
394 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need 2 args at least!");
395 }
396
397 int64_t mainScreenId;
398 if (!ConvertFromJsValue(env, argv[0], mainScreenId)) {
399 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to int");
400 }
401 napi_value array = argv[INDEX_ONE];
402 if (array == nullptr) {
403 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to get mirrorScreen, is nullptr");
404 }
405 uint32_t size = 0;
406 napi_get_array_length(env, array, &size);
407 std::vector<ScreenId> screenIds;
408 for (uint32_t i = 0; i < size; i++) {
409 uint32_t screenId;
410 napi_value value = nullptr;
411 napi_get_element(env, array, i, &value);
412 if (!ConvertFromJsValue(env, value, screenId)) {
413 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to ScreenId");
414 }
415 screenIds.emplace_back(static_cast<ScreenId>(screenId));
416 }
417
418 NapiAsyncTask::CompleteCallback complete =
419 [mainScreenId, screenIds](napi_env env, NapiAsyncTask& task, int32_t status) {
420 ScreenId screenGroupId = INVALID_SCREEN_ID;
421 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(
422 SingletonContainer::Get<ScreenManager>().MakeMirror(mainScreenId, screenIds, screenGroupId));
423 if (ret == DmErrorCode::DM_OK) {
424 task.Resolve(env, CreateJsValue(env, static_cast<uint32_t>(screenGroupId)));
425 } else {
426 task.Reject(env,
427 CreateJsError(env, static_cast<int32_t>(ret), "JsScreenManager::OnMakeMirror failed."));
428 }
429 };
430 napi_value lastParam = nullptr;
431 if (argc >= ARGC_THREE && argv[ARGC_THREE - 1] != nullptr &&
432 GetType(env, argv[ARGC_THREE - 1]) == napi_function) {
433 lastParam = argv[ARGC_THREE - 1];
434 }
435 napi_value result = nullptr;
436 NapiAsyncTask::Schedule("JsScreenManager::OnMakeMirror",
437 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
438 return result;
439 }
440
OnMakeMirrorWithRegion(napi_env env,napi_callback_info info)441 napi_value OnMakeMirrorWithRegion(napi_env env, napi_callback_info info)
442 {
443 WLOGI("OnMakeMirrorWithRegion is called");
444 size_t argc = 4;
445 napi_value argv[4] = {nullptr};
446 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
447 if (argc < ARGC_THREE) {
448 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need 3 args at least!");
449 }
450 int64_t mainScreenId;
451 if (!ConvertFromJsValue(env, argv[INDEX_ZERO], mainScreenId)) {
452 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to mainScreenId");
453 }
454 napi_value array = argv[INDEX_ONE];
455 if (array == nullptr) {
456 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to get mirrorScreen, is nullptr");
457 }
458 uint32_t size = 0;
459 napi_get_array_length(env, array, &size);
460 std::vector<ScreenId> mirrorScreenIds;
461 for (uint32_t i = 0; i < size; i++) {
462 uint32_t screenId;
463 napi_value value = nullptr;
464 napi_get_element(env, array, i, &value);
465 if (!ConvertFromJsValue(env, value, screenId)) {
466 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to ScreenId");
467 }
468 mirrorScreenIds.emplace_back(static_cast<ScreenId>(screenId));
469 }
470 DMRect mainScreenRegion;
471 if (GetRectFromJs(env, argv[INDEX_TWO], mainScreenRegion) == -1) {
472 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert to mainScreenRegion");
473 }
474 napi_value lastParam = nullptr;
475 napi_value result = nullptr;
476 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
477 auto asyncTask = [mainScreenId, mirrorScreenIds, mainScreenRegion, env, task = napiAsyncTask.get()]() {
478 ScreenId screenGroupId = INVALID_SCREEN_ID;
479 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(SingletonContainer::Get<ScreenManager>().MakeMirror(mainScreenId,
480 mirrorScreenIds, mainScreenRegion, screenGroupId));
481 if (ret == DmErrorCode::DM_OK) {
482 task->Resolve(env, CreateJsValue(env, static_cast<uint32_t>(screenGroupId)));
483 } else {
484 task->Reject(env,
485 CreateJsError(env, static_cast<int32_t>(ret), "JsScreenManager::OnMakeMirrorWithRegion failed."));
486 }
487 };
488 NapiSendDmsEvent(env, asyncTask, napiAsyncTask);
489 return result;
490 }
491
OnMakeExpand(napi_env env,napi_callback_info info)492 napi_value OnMakeExpand(napi_env env, napi_callback_info info)
493 {
494 WLOGI("OnMakeExpand is called");
495 size_t argc = 4;
496 napi_value argv[4] = {nullptr};
497 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
498 if (argc < ARGC_ONE) {
499 WLOGFE("Invalid args count, need one arg at least!");
500 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need one arg at least!");
501 }
502
503 napi_value array = argv[0];
504 if (array == nullptr) {
505 WLOGFE("Failed to get options, options is nullptr");
506 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to get options, options is nullptr");
507 }
508 uint32_t size = 0;
509 napi_get_array_length(env, array, &size);
510 std::vector<ExpandOption> options;
511 for (uint32_t i = 0; i < size; ++i) {
512 napi_value object = nullptr;
513 napi_get_element(env, array, i, &object);
514 ExpandOption expandOption;
515 int32_t res = GetExpandOptionFromJs(env, object, expandOption);
516 if (res == -1) {
517 WLOGE("expandoption param %{public}d error!", i);
518 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "expandoption param error!");
519 }
520 options.emplace_back(expandOption);
521 }
522
523 NapiAsyncTask::CompleteCallback complete =
524 [options](napi_env env, NapiAsyncTask& task, int32_t status) {
525 ScreenId screenGroupId = INVALID_SCREEN_ID;
526 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(
527 SingletonContainer::Get<ScreenManager>().MakeExpand(options, screenGroupId));
528 if (ret == DmErrorCode::DM_OK) {
529 task.Resolve(env, CreateJsValue(env, static_cast<uint32_t>(screenGroupId)));
530 WLOGI("MakeExpand success");
531 } else {
532 task.Reject(env,
533 CreateJsError(env, static_cast<int32_t>(ret), "JsScreenManager::OnMakeExpand failed."));
534 WLOGFE("MakeExpand failed");
535 }
536 };
537 napi_value lastParam = nullptr;
538 if (argc >= ARGC_TWO && argv[ARGC_TWO - 1] != nullptr && GetType(env, argv[ARGC_TWO - 1]) == napi_function) {
539 lastParam = argv[ARGC_TWO - 1];
540 }
541 napi_value result = nullptr;
542 NapiAsyncTask::Schedule("JsScreenManager::OnMakeExpand",
543 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
544 return result;
545 }
546
OnStopMirror(napi_env env,napi_callback_info info)547 napi_value OnStopMirror(napi_env env, napi_callback_info info)
548 {
549 WLOGI("OnStopMirror is called");
550 size_t argc = 4;
551 napi_value argv[4] = {nullptr};
552 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
553 if (argc < ARGC_ONE) {
554 WLOGFE("Invalid args count, need one arg at least!");
555 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need one arg at least!");
556 }
557
558 napi_value array = argv[0];
559 if (array == nullptr) {
560 WLOGFE("Failed to get mirrorScreen, mirrorScreen is nullptr");
561 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to get mirrorScreen, is nullptr");
562 }
563 uint32_t size = 0;
564 napi_get_array_length(env, array, &size);
565 if (size > MAX_SCREENS_NUM) {
566 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "size of mirrorScreen is greater than 1000");
567 }
568 std::vector<ScreenId> screenIds;
569 for (uint32_t i = 0; i < size; i++) {
570 uint32_t screenId;
571 napi_value value = nullptr;
572 napi_get_element(env, array, i, &value);
573 if (!ConvertFromJsValue(env, value, screenId)) {
574 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to ScreenId");
575 }
576 screenIds.emplace_back(static_cast<ScreenId>(screenId));
577 }
578
579 NapiAsyncTask::CompleteCallback complete =
580 [ screenIds](napi_env env, NapiAsyncTask& task, int32_t status) {
581 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(
582 SingletonContainer::Get<ScreenManager>().StopMirror(screenIds));
583 if (ret == DmErrorCode::DM_OK) {
584 task.Resolve(env, NapiGetUndefined(env));
585 } else {
586 task.Reject(env,
587 CreateJsError(env, static_cast<int32_t>(ret), "JsScreenManager::OnStopMirror failed."));
588 }
589 };
590 napi_value lastParam = nullptr;
591 if (argc >= ARGC_TWO && argv[ARGC_TWO - 1] != nullptr && GetType(env, argv[ARGC_TWO - 1]) == napi_function) {
592 lastParam = argv[ARGC_TWO - 1];
593 }
594 napi_value result = nullptr;
595 NapiAsyncTask::Schedule("JsScreenManager::OnStopMirror",
596 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
597 return result;
598 }
599
OnStopExpand(napi_env env,napi_callback_info info)600 napi_value OnStopExpand(napi_env env, napi_callback_info info)
601 {
602 WLOGI("OnStopExpand is called");
603 size_t argc = 4;
604 napi_value argv[4] = {nullptr};
605 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
606 if (argc < ARGC_ONE) {
607 WLOGFE("Invalid args count, need one arg at least!");
608 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Invalid args count, need one arg at least!");
609 }
610
611 napi_value array = argv[0];
612 if (array == nullptr) {
613 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to get expandScreen, is nullptr");
614 }
615 uint32_t size = 0;
616 napi_get_array_length(env, array, &size);
617 if (size > MAX_SCREENS_NUM) {
618 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "size of expandScreen is greater than 1000");
619 }
620 std::vector<ScreenId> screenIds;
621 for (uint32_t i = 0; i < size; i++) {
622 uint32_t screenId;
623 napi_value value = nullptr;
624 napi_get_element(env, array, i, &value);
625 if (!ConvertFromJsValue(env, value, screenId)) {
626 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, "Failed to convert parameter to ScreenId");
627 }
628 screenIds.emplace_back(static_cast<ScreenId>(screenId));
629 }
630
631 NapiAsyncTask::CompleteCallback complete =
632 [screenIds](napi_env env, NapiAsyncTask& task, int32_t status) {
633 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(
634 SingletonContainer::Get<ScreenManager>().StopExpand(screenIds));
635 if (ret == DmErrorCode::DM_OK) {
636 task.Resolve(env, NapiGetUndefined(env));
637 WLOGI("MakeExpand success");
638 } else {
639 task.Reject(env,
640 CreateJsError(env, static_cast<int32_t>(ret), "JsScreenManager::OnStopExpand failed."));
641 WLOGFE("MakeExpand failed");
642 }
643 };
644 napi_value lastParam = nullptr;
645 if (argc >= ARGC_TWO && argv[ARGC_TWO - 1] != nullptr && GetType(env, argv[ARGC_TWO - 1]) == napi_function) {
646 lastParam = argv[ARGC_TWO - 1];
647 }
648 napi_value result = nullptr;
649 NapiAsyncTask::Schedule("JsScreenManager::OnStopExpand",
650 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
651 return result;
652 }
653
GetExpandOptionFromJs(napi_env env,napi_value optionObject,ExpandOption & option)654 static int32_t GetExpandOptionFromJs(napi_env env, napi_value optionObject, ExpandOption& option)
655 {
656 napi_value screedIdValue = nullptr;
657 napi_value startXValue = nullptr;
658 napi_value startYValue = nullptr;
659 uint32_t screenId;
660 uint32_t startX;
661 uint32_t startY;
662 napi_get_named_property(env, optionObject, "screenId", &screedIdValue);
663 napi_get_named_property(env, optionObject, "startX", &startXValue);
664 napi_get_named_property(env, optionObject, "startY", &startYValue);
665 if (!ConvertFromJsValue(env, screedIdValue, screenId)) {
666 WLOGFE("Failed to convert screedIdValue to callbackType");
667 return -1;
668 }
669 if (!ConvertFromJsValue(env, startXValue, startX)) {
670 WLOGFE("Failed to convert startXValue to callbackType");
671 return -1;
672 }
673 if (!ConvertFromJsValue(env, startYValue, startY)) {
674 WLOGFE("Failed to convert startYValue to callbackType");
675 return -1;
676 }
677 option = {screenId, startX, startY};
678 return 0;
679 }
680
GetRectFromJs(napi_env env,napi_value optionObject,DMRect & rect)681 static int32_t GetRectFromJs(napi_env env, napi_value optionObject, DMRect& rect)
682 {
683 napi_value leftValue = nullptr;
684 napi_value topValue = nullptr;
685 napi_value widthValue = nullptr;
686 napi_value heightValue = nullptr;
687 int32_t left;
688 int32_t top;
689 uint32_t width;
690 uint32_t height;
691 napi_get_named_property(env, optionObject, "left", &leftValue);
692 napi_get_named_property(env, optionObject, "top", &topValue);
693 napi_get_named_property(env, optionObject, "width", &widthValue);
694 napi_get_named_property(env, optionObject, "height", &heightValue);
695 if (!ConvertFromJsValue(env, leftValue, left)) {
696 WLOGFE("Failed to convert leftValue to callbackType");
697 return -1;
698 }
699 if (!ConvertFromJsValue(env, topValue, top)) {
700 WLOGFE("Failed to convert topValue to callbackType");
701 return -1;
702 }
703 if (!ConvertFromJsValue(env, widthValue, width)) {
704 WLOGFE("Failed to convert widthValue to callbackType");
705 return -1;
706 }
707 if (!ConvertFromJsValue(env, heightValue, height)) {
708 WLOGFE("Failed to convert heightValue to callbackType");
709 return -1;
710 }
711 rect = {left, top, width, height};
712 return 0;
713 }
714
OnCreateVirtualScreen(napi_env env,napi_callback_info info)715 napi_value OnCreateVirtualScreen(napi_env env, napi_callback_info info)
716 {
717 WLOGI("JsScreenManager::OnCreateVirtualScreen is called");
718 DmErrorCode errCode = DmErrorCode::DM_OK;
719 VirtualScreenOption option;
720 size_t argc = 4;
721 std::string errMsg = "";
722 napi_value argv[4] = {nullptr};
723 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
724 if (argc < ARGC_ONE) {
725 errMsg = "Invalid args count, need one arg at least!";
726 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
727 } else {
728 napi_value object = argv[0];
729 if (object == nullptr) {
730 errMsg = "Failed to get options, options is nullptr";
731 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
732 } else {
733 errCode = GetVirtualScreenOptionFromJs(env, object, option);
734 }
735 }
736 if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) {
737 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
738 }
739 NapiAsyncTask::CompleteCallback complete =
740 [option](napi_env env, NapiAsyncTask& task, int32_t status) {
741 auto screenId = SingletonContainer::Get<ScreenManager>().CreateVirtualScreen(option);
742 auto screen = SingletonContainer::Get<ScreenManager>().GetScreenById(screenId);
743 if (screen == nullptr) {
744 DmErrorCode ret = DmErrorCode::DM_ERROR_INVALID_SCREEN;
745 if (screenId == ERROR_ID_NOT_SYSTEM_APP) {
746 ret = DmErrorCode::DM_ERROR_NOT_SYSTEM_APP;
747 }
748 task.Reject(env, CreateJsError(env, static_cast<int32_t>(ret), "CreateVirtualScreen failed."));
749 WLOGFE("ScreenManager::CreateVirtualScreen failed.");
750 return;
751 }
752 task.Resolve(env, CreateJsScreenObject(env, screen));
753 WLOGI("JsScreenManager::OnCreateVirtualScreen success");
754 };
755 napi_value lastParam = nullptr;
756 if (argc >= ARGC_TWO && argv[ARGC_TWO - 1] != nullptr &&
757 GetType(env, argv[ARGC_TWO - 1]) == napi_function) {
758 lastParam = argv[ARGC_TWO - 1];
759 }
760 napi_value result = nullptr;
761 NapiAsyncTask::Schedule("JsScreenManager::OnCreateVirtualScreen",
762 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
763 return result;
764 }
765
GetVirtualScreenOptionFromJs(napi_env env,napi_value optionObject,VirtualScreenOption & option)766 DmErrorCode GetVirtualScreenOptionFromJs(napi_env env, napi_value optionObject, VirtualScreenOption& option)
767 {
768 napi_value name = nullptr;
769 napi_get_named_property(env, optionObject, "name", &name);
770 if (!ConvertFromJsValue(env, name, option.name_)) {
771 WLOGFE("Failed to convert parameter to name.");
772 return DmErrorCode::DM_ERROR_INVALID_PARAM;
773 }
774 napi_value width = nullptr;
775 napi_get_named_property(env, optionObject, "width", &width);
776 if (!ConvertFromJsValue(env, width, option.width_)) {
777 WLOGFE("Failed to convert parameter to width.");
778 return DmErrorCode::DM_ERROR_INVALID_PARAM;
779 }
780 napi_value height = nullptr;
781 napi_get_named_property(env, optionObject, "height", &height);
782 if (!ConvertFromJsValue(env, height, option.height_)) {
783 WLOGFE("Failed to convert parameter to height.");
784 return DmErrorCode::DM_ERROR_INVALID_PARAM;
785 }
786 napi_value density = nullptr;
787 napi_get_named_property(env, optionObject, "density", &density);
788 double densityValue;
789 if (!ConvertFromJsValue(env, density, densityValue)) {
790 WLOGFE("Failed to convert parameter to density.");
791 return DmErrorCode::DM_ERROR_INVALID_PARAM;
792 }
793 option.density_ = static_cast<float>(densityValue);
794
795 napi_value surfaceIdNapiValue = nullptr;
796 napi_get_named_property(env, optionObject, "surfaceId", &surfaceIdNapiValue);
797 if (!GetSurfaceFromJs(env, surfaceIdNapiValue, option.surface_)) {
798 return DmErrorCode::DM_ERROR_INVALID_PARAM;
799 }
800 return DmErrorCode::DM_OK;
801 }
802
GetSurfaceFromJs(napi_env env,napi_value surfaceIdNapiValue,sptr<Surface> & surface)803 bool GetSurfaceFromJs(napi_env env, napi_value surfaceIdNapiValue, sptr<Surface>& surface)
804 {
805 if (surfaceIdNapiValue == nullptr || GetType(env, surfaceIdNapiValue) != napi_string) {
806 WLOGFE("Failed to convert parameter to surface. Invalidate params.");
807 return false;
808 }
809
810 char buffer[PATH_MAX];
811 size_t length = 0;
812 uint64_t surfaceId = 0;
813 if (napi_get_value_string_utf8(env, surfaceIdNapiValue, buffer, PATH_MAX, &length) != napi_ok) {
814 WLOGFE("Failed to convert parameter to surface.");
815 return false;
816 }
817 std::istringstream inputStream(buffer);
818 inputStream >> surfaceId;
819 surface = SurfaceUtils::GetInstance()->GetSurface(surfaceId);
820 if (surface == nullptr) {
821 WLOGI("GetSurfaceFromJs failed, surfaceId:%{public}" PRIu64"", surfaceId);
822 }
823 return true;
824 }
825
OnDestroyVirtualScreen(napi_env env,napi_callback_info info)826 napi_value OnDestroyVirtualScreen(napi_env env, napi_callback_info info)
827 {
828 WLOGI("JsScreenManager::OnDestroyVirtualScreen is called");
829 DmErrorCode errCode = DmErrorCode::DM_OK;
830 int64_t screenId = -1LL;
831 std::string errMsg = "";
832 size_t argc = 4;
833 napi_value argv[4] = {nullptr};
834 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
835 if (argc < ARGC_ONE) {
836 WLOGFE("[NAPI]Argc is invalid: %{public}zu", argc);
837 errMsg = "Invalid args count, need one arg at least!";
838 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
839 } else {
840 if (!ConvertFromJsValue(env, argv[0], screenId)) {
841 WLOGFE("Failed to convert parameter to screen id.");
842 errMsg = "Failed to convert parameter to screen id.";
843 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
844 }
845 }
846 if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || screenId == -1LL) {
847 WLOGFE("JsScreenManager::OnDestroyVirtualScreen failed, Invalidate params.");
848 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
849 }
850 NapiAsyncTask::CompleteCallback complete =
851 [screenId](napi_env env, NapiAsyncTask& task, int32_t status) {
852 auto res = DM_JS_TO_ERROR_CODE_MAP.at(
853 SingletonContainer::Get<ScreenManager>().DestroyVirtualScreen(screenId));
854 if (res != DmErrorCode::DM_OK) {
855 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
856 "ScreenManager::DestroyVirtualScreen failed."));
857 WLOGFE("ScreenManager::DestroyVirtualScreen failed.");
858 return;
859 }
860 task.Resolve(env, NapiGetUndefined(env));
861 WLOGI("JsScreenManager::OnDestroyVirtualScreen success");
862 };
863 napi_value lastParam = nullptr;
864 if (argc >= ARGC_TWO && argv[ARGC_TWO - 1] != nullptr &&
865 GetType(env, argv[ARGC_TWO - 1]) == napi_function) {
866 lastParam = argv[ARGC_TWO - 1];
867 }
868 napi_value result = nullptr;
869 NapiAsyncTask::Schedule("JsScreenManager::OnDestroyVirtualScreen",
870 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
871 return result;
872 }
873
OnSetVirtualScreenSurface(napi_env env,napi_callback_info info)874 napi_value OnSetVirtualScreenSurface(napi_env env, napi_callback_info info)
875 {
876 WLOGI("JsScreenManager::OnSetVirtualScreenSurface is called");
877 DmErrorCode errCode = DmErrorCode::DM_OK;
878 int64_t screenId = -1LL;
879 sptr<Surface> surface;
880 size_t argc = 4;
881 std::string errMsg = "";
882 napi_value argv[4] = {nullptr};
883 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
884 if (argc < ARGC_TWO) {
885 WLOGFE("[NAPI]Argc is invalid: %{public}zu", argc);
886 errMsg = "Invalid args count, need 2 args at least!";
887 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
888 } else {
889 if (!ConvertFromJsValue(env, argv[0], screenId)) {
890 errMsg = "Failed to convert parameter to screen id.";
891 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
892 }
893 if (!GetSurfaceFromJs(env, argv[1], surface)) {
894 errMsg = "Failed to convert parameter.";
895 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
896 }
897 }
898 if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || surface == nullptr) {
899 WLOGFE("JsScreenManager::OnSetVirtualScreenSurface failed, Invalidate params.");
900 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
901 }
902 NapiAsyncTask::CompleteCallback complete =
903 [screenId, surface](napi_env env, NapiAsyncTask& task, int32_t status) {
904 auto res = DM_JS_TO_ERROR_CODE_MAP.at(
905 SingletonContainer::Get<ScreenManager>().SetVirtualScreenSurface(screenId, surface));
906 if (res != DmErrorCode::DM_OK) {
907 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
908 "ScreenManager::SetVirtualScreenSurface failed."));
909 WLOGFE("ScreenManager::SetVirtualScreenSurface failed.");
910 return;
911 }
912 task.Resolve(env, NapiGetUndefined(env));
913 WLOGI("JsScreenManager::OnSetVirtualScreenSurface success");
914 };
915 napi_value lastParam = nullptr;
916 if (argc >= ARGC_THREE && argv[ARGC_THREE - 1] != nullptr &&
917 GetType(env, argv[ARGC_THREE - 1]) == napi_function) {
918 lastParam = argv[ARGC_THREE - 1];
919 }
920 napi_value result = nullptr;
921 NapiAsyncTask::Schedule("JsScreenManager::OnSetVirtualScreenSurface",
922 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
923 return result;
924 }
925
OnIsScreenRotationLocked(napi_env env,napi_callback_info info)926 napi_value OnIsScreenRotationLocked(napi_env env, napi_callback_info info)
927 {
928 size_t argc = 4;
929 napi_value argv[4] = {nullptr};
930 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
931 WLOGI("OnIsScreenRotationLocked is called");
932 NapiAsyncTask::CompleteCallback complete =
933 [](napi_env env, NapiAsyncTask& task, int32_t status) {
934 bool isLocked = false;
935 auto res = DM_JS_TO_ERROR_CODE_MAP.at(
936 SingletonContainer::Get<ScreenManager>().IsScreenRotationLocked(isLocked));
937 if (res == DmErrorCode::DM_OK) {
938 task.Resolve(env, CreateJsValue(env, isLocked));
939 WLOGFI("OnIsScreenRotationLocked success");
940 } else {
941 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
942 "JsScreenManager::OnIsScreenRotationLocked failed."));
943 WLOGFE("OnIsScreenRotationLocked failed");
944 }
945 };
946 napi_value lastParam = nullptr;
947 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
948 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
949 lastParam = argv[ARGC_ONE - 1];
950 }
951 napi_value result = nullptr;
952 NapiAsyncTask::Schedule("JsScreenManager::OnIsScreenRotationLocked",
953 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
954 return result;
955 }
956
OnSetScreenRotationLocked(napi_env env,napi_callback_info info)957 napi_value OnSetScreenRotationLocked(napi_env env, napi_callback_info info)
958 {
959 WLOGI("JsScreenManager::OnSetScreenRotationLocked is called");
960 DmErrorCode errCode = DmErrorCode::DM_OK;
961 size_t argc = 4;
962 std::string errMsg = "";
963 napi_value argv[4] = {nullptr};
964 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
965 if (argc < ARGC_ONE) {
966 WLOGFE("[NAPI]Argc is invalid: %{public}zu", argc);
967 errMsg = "Invalid args count, need one arg at least!";
968 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
969 }
970 bool isLocked = false;
971 if (errCode == DmErrorCode::DM_OK) {
972 napi_value nativeVal = argv[0];
973 if (nativeVal == nullptr) {
974 WLOGFE("[NAPI]Failed to convert parameter to isLocked");
975 errMsg = "Failed to convert parameter to isLocked.";
976 errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
977 } else {
978 napi_get_value_bool(env, nativeVal, &isLocked);
979 }
980 }
981 if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) {
982 WLOGFE("JsScreenManager::OnSetScreenRotationLocked failed, Invalidate params.");
983 return NapiThrowError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
984 }
985
986 NapiAsyncTask::CompleteCallback complete =
987 [isLocked](napi_env env, NapiAsyncTask& task, int32_t status) {
988 auto res = DM_JS_TO_ERROR_CODE_MAP.at(
989 SingletonContainer::Get<ScreenManager>().SetScreenRotationLocked(isLocked));
990 if (res == DmErrorCode::DM_OK) {
991 task.Resolve(env, NapiGetUndefined(env));
992 WLOGFI("OnSetScreenRotationLocked success");
993 } else {
994 task.Reject(env, CreateJsError(env, static_cast<int32_t>(res),
995 "JsScreenManager::OnSetScreenRotationLocked failed."));
996 WLOGFE("OnSetScreenRotationLocked failed");
997 }
998 };
999 napi_value lastParam = (argc <= ARGC_ONE) ? nullptr :
1000 ((argv[ARGC_TWO - 1] != nullptr && GetType(env, argv[ARGC_TWO - 1]) == napi_function) ?
1001 argv[1] : nullptr);
1002 napi_value result = nullptr;
1003 NapiAsyncTask::Schedule("JsScreenManager::OnSetScreenRotationLocked",
1004 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1005 return result;
1006 }
1007
NapiSendDmsEvent(napi_env env,std::function<void ()> asyncTask,std::unique_ptr<AbilityRuntime::NapiAsyncTask> & napiAsyncTask)1008 void NapiSendDmsEvent(napi_env env, std::function<void()> asyncTask,
1009 std::unique_ptr<AbilityRuntime::NapiAsyncTask>& napiAsyncTask)
1010 {
1011 if (!env) {
1012 WLOGFE("env is null");
1013 return;
1014 }
1015 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
1016 napiAsyncTask->Reject(env, CreateJsError(env,
1017 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
1018 } else {
1019 napiAsyncTask.release();
1020 WLOGFE("send event success");
1021 }
1022 }
1023
CreateEmptyAsyncTask(napi_env env,napi_value lastParam,napi_value * result)1024 std::unique_ptr<NapiAsyncTask> CreateEmptyAsyncTask(napi_env env, napi_value lastParam, napi_value* result)
1025 {
1026 napi_valuetype type = napi_undefined;
1027 napi_typeof(env, lastParam, &type);
1028 if (lastParam == nullptr || type != napi_function) {
1029 napi_deferred nativeDeferred = nullptr;
1030 napi_create_promise(env, &nativeDeferred, result);
1031 return std::make_unique<NapiAsyncTask>(nativeDeferred, std::unique_ptr<NapiAsyncTask::ExecuteCallback>(),
1032 std::unique_ptr<NapiAsyncTask::CompleteCallback>());
1033 } else {
1034 napi_get_undefined(env, result);
1035 napi_ref callbackRef = nullptr;
1036 napi_create_reference(env, lastParam, 1, &callbackRef);
1037 return std::make_unique<NapiAsyncTask>(callbackRef, std::unique_ptr<NapiAsyncTask::ExecuteCallback>(),
1038 std::unique_ptr<NapiAsyncTask::CompleteCallback>());
1039 }
1040 }
1041 };
1042
InitScreenOrientation(napi_env env)1043 napi_value InitScreenOrientation(napi_env env)
1044 {
1045 WLOGD("JsScreenManager::InitScreenOrientation called");
1046
1047 if (env == nullptr) {
1048 WLOGFE("env is nullptr");
1049 return nullptr;
1050 }
1051
1052 napi_value objValue = nullptr;
1053 napi_create_object(env, &objValue);
1054 if (objValue == nullptr) {
1055 WLOGFE("Failed to get object");
1056 return nullptr;
1057 }
1058
1059 napi_set_named_property(env, objValue, "UNSPECIFIED",
1060 CreateJsValue(env, static_cast<int32_t>(Orientation::UNSPECIFIED)));
1061 napi_set_named_property(env, objValue, "VERTICAL",
1062 CreateJsValue(env, static_cast<int32_t>(Orientation::VERTICAL)));
1063 napi_set_named_property(env, objValue, "HORIZONTAL",
1064 CreateJsValue(env, static_cast<int32_t>(Orientation::HORIZONTAL)));
1065 napi_set_named_property(env, objValue, "REVERSE_VERTICAL",
1066 CreateJsValue(env, static_cast<int32_t>(Orientation::REVERSE_VERTICAL)));
1067 napi_set_named_property(env, objValue, "REVERSE_HORIZONTAL",
1068 CreateJsValue(env, static_cast<int32_t>(Orientation::REVERSE_HORIZONTAL)));
1069 return objValue;
1070 }
1071
InitScreenSourceMode(napi_env env)1072 napi_value InitScreenSourceMode(napi_env env)
1073 {
1074 WLOGD("JsScreenManager::InitScreenSourceMode called");
1075
1076 if (env == nullptr) {
1077 WLOGFE("env is nullptr");
1078 return nullptr;
1079 }
1080
1081 napi_value objValue = nullptr;
1082 napi_create_object(env, &objValue);
1083 if (objValue == nullptr) {
1084 WLOGFE("Failed to get object");
1085 return nullptr;
1086 }
1087
1088 napi_set_named_property(env, objValue, "SCREEN_MAIN",
1089 CreateJsValue(env, static_cast<uint32_t>(ScreenSourceMode::SCREEN_MAIN)));
1090 napi_set_named_property(env, objValue, "SCREEN_MIRROR",
1091 CreateJsValue(env, static_cast<uint32_t>(ScreenSourceMode::SCREEN_MIRROR)));
1092 napi_set_named_property(env, objValue, "SCREEN_EXTEND",
1093 CreateJsValue(env, static_cast<uint32_t>(ScreenSourceMode::SCREEN_EXTEND)));
1094 napi_set_named_property(env, objValue, "SCREEN_ALONE",
1095 CreateJsValue(env, static_cast<uint32_t>(ScreenSourceMode::SCREEN_ALONE)));
1096 return objValue;
1097 }
1098
InitDisplayErrorCode(napi_env env)1099 napi_value InitDisplayErrorCode(napi_env env)
1100 {
1101 WLOGD("JsDisplayManager::InitDisplayErrorCode called");
1102
1103 if (env == nullptr) {
1104 WLOGFE("env is nullptr");
1105 return nullptr;
1106 }
1107
1108 napi_value objValue = nullptr;
1109 napi_create_object(env, &objValue);
1110 if (objValue == nullptr) {
1111 WLOGFE("Failed to get object");
1112 return nullptr;
1113 }
1114
1115 napi_set_named_property(env, objValue, "DM_ERROR_NO_PERMISSION",
1116 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_NO_PERMISSION)));
1117 napi_set_named_property(env, objValue, "DM_ERROR_NOT_SYSTEM_APP",
1118 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_NOT_SYSTEM_APP)));
1119 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_PARAM",
1120 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
1121 napi_set_named_property(env, objValue, "DM_ERROR_DEVICE_NOT_SUPPORT",
1122 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT)));
1123 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_SCREEN",
1124 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN)));
1125 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_CALLING",
1126 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_CALLING)));
1127 napi_set_named_property(env, objValue, "DM_ERROR_SYSTEM_INNORMAL",
1128 CreateJsValue(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL)));
1129 return objValue;
1130 }
1131
InitDisplayError(napi_env env)1132 napi_value InitDisplayError(napi_env env)
1133 {
1134 WLOGD("JsDisplayManager::InitDisplayError called");
1135
1136 if (env == nullptr) {
1137 WLOGFE("env is nullptr");
1138 return nullptr;
1139 }
1140
1141 napi_value objValue = nullptr;
1142 napi_create_object(env, &objValue);
1143 if (objValue == nullptr) {
1144 WLOGFE("Failed to get object");
1145 return nullptr;
1146 }
1147
1148 napi_set_named_property(env, objValue, "DM_ERROR_INIT_DMS_PROXY_LOCKED",
1149 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED)));
1150 napi_set_named_property(env, objValue, "DM_ERROR_IPC_FAILED",
1151 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_IPC_FAILED)));
1152 napi_set_named_property(env, objValue, "DM_ERROR_REMOTE_CREATE_FAILED",
1153 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_REMOTE_CREATE_FAILED)));
1154 napi_set_named_property(env, objValue, "DM_ERROR_NULLPTR",
1155 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_NULLPTR)));
1156 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_PARAM",
1157 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_INVALID_PARAM)));
1158 napi_set_named_property(env, objValue, "DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED",
1159 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED)));
1160 napi_set_named_property(env, objValue, "DM_ERROR_DEATH_RECIPIENT",
1161 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_DEATH_RECIPIENT)));
1162 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_MODE_ID",
1163 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_INVALID_MODE_ID)));
1164 napi_set_named_property(env, objValue, "DM_ERROR_WRITE_DATA_FAILED",
1165 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_WRITE_DATA_FAILED)));
1166 napi_set_named_property(env, objValue, "DM_ERROR_RENDER_SERVICE_FAILED",
1167 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_RENDER_SERVICE_FAILED)));
1168 napi_set_named_property(env, objValue, "DM_ERROR_UNREGISTER_AGENT_FAILED",
1169 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_UNREGISTER_AGENT_FAILED)));
1170 napi_set_named_property(env, objValue, "DM_ERROR_INVALID_CALLING",
1171 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_INVALID_CALLING)));
1172 napi_set_named_property(env, objValue, "DM_ERROR_UNKNOWN",
1173 CreateJsValue(env, static_cast<int32_t>(DMError::DM_ERROR_UNKNOWN)));
1174 return objValue;
1175 }
1176
JsScreenManagerInit(napi_env env,napi_value exportObj)1177 napi_value JsScreenManagerInit(napi_env env, napi_value exportObj)
1178 {
1179 WLOGD("JsScreenManagerInit is called");
1180
1181 if (env == nullptr || exportObj == nullptr) {
1182 WLOGFE("JsScreenManagerInit env or exportObj is nullptr");
1183 return nullptr;
1184 }
1185
1186 std::unique_ptr<JsScreenManager> jsScreenManager = std::make_unique<JsScreenManager>(env);
1187 napi_wrap(env, exportObj, jsScreenManager.release(), JsScreenManager::Finalizer, nullptr, nullptr);
1188 napi_set_named_property(env, exportObj, "Orientation", InitScreenOrientation(env));
1189 napi_set_named_property(env, exportObj, "ScreenSourceMode", InitScreenSourceMode(env));
1190 napi_set_named_property(env, exportObj, "DmErrorCode", InitDisplayErrorCode(env));
1191 napi_set_named_property(env, exportObj, "DMError", InitDisplayError(env));
1192
1193 const char *moduleName = "JsScreenManager";
1194 BindNativeFunction(env, exportObj, "getAllScreens", moduleName, JsScreenManager::GetAllScreens);
1195 BindNativeFunction(env, exportObj, "on", moduleName, JsScreenManager::RegisterScreenManagerCallback);
1196 BindNativeFunction(env, exportObj, "off", moduleName, JsScreenManager::UnregisterScreenMangerCallback);
1197 BindNativeFunction(env, exportObj, "makeMirror", moduleName, JsScreenManager::MakeMirror);
1198 BindNativeFunction(env, exportObj, "makeMirrorWithRegion", moduleName, JsScreenManager::MakeMirrorWithRegion);
1199 BindNativeFunction(env, exportObj, "makeExpand", moduleName, JsScreenManager::MakeExpand);
1200 BindNativeFunction(env, exportObj, "stopMirror", moduleName, JsScreenManager::StopMirror);
1201 BindNativeFunction(env, exportObj, "stopExpand", moduleName, JsScreenManager::StopExpand);
1202 BindNativeFunction(env, exportObj, "createVirtualScreen", moduleName, JsScreenManager::CreateVirtualScreen);
1203 BindNativeFunction(env, exportObj, "destroyVirtualScreen", moduleName, JsScreenManager::DestroyVirtualScreen);
1204 BindNativeFunction(env, exportObj, "setVirtualScreenSurface", moduleName,
1205 JsScreenManager::SetVirtualScreenSurface);
1206 BindNativeFunction(env, exportObj, "setScreenRotationLocked", moduleName,
1207 JsScreenManager::SetScreenRotationLocked);
1208 BindNativeFunction(env, exportObj, "isScreenRotationLocked", moduleName,
1209 JsScreenManager::IsScreenRotationLocked);
1210 return NapiGetUndefined(env);
1211 }
1212 } // namespace Rosen
1213 } // namespace OHOS
1214