• 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_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