• 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_ONE = 1;
37 namespace {
38     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsScreenManager"};
39 }
40 
41 class JsScreenManager {
42 public:
JsScreenManager(NativeEngine * engine)43 explicit JsScreenManager(NativeEngine* engine) {
44 }
45 
46 ~JsScreenManager() = default;
47 
Finalizer(NativeEngine * engine,void * data,void * hint)48 static void Finalizer(NativeEngine* engine, void* data, void* hint)
49 {
50     WLOGFI("JsScreenManager::Finalizer is called");
51     std::unique_ptr<JsScreenManager>(static_cast<JsScreenManager*>(data));
52 }
53 
GetAllScreens(NativeEngine * engine,NativeCallbackInfo * info)54 static NativeValue* GetAllScreens(NativeEngine* engine, NativeCallbackInfo* info)
55 {
56     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
57     return (me != nullptr) ? me->OnGetAllScreens(*engine, *info) : nullptr;
58 }
59 
RegisterScreenManagerCallback(NativeEngine * engine,NativeCallbackInfo * info)60 static NativeValue* RegisterScreenManagerCallback(NativeEngine* engine, NativeCallbackInfo* info)
61 {
62     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
63     return (me != nullptr) ? me->OnRegisterScreenMangerCallback(*engine, *info) : nullptr;
64 }
65 
UnregisterScreenMangerCallback(NativeEngine * engine,NativeCallbackInfo * info)66 static NativeValue* UnregisterScreenMangerCallback(NativeEngine* engine, NativeCallbackInfo* info)
67 {
68     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
69     return (me != nullptr) ? me->OnUnregisterScreenManagerCallback(*engine, *info) : nullptr;
70 }
71 
MakeMirror(NativeEngine * engine,NativeCallbackInfo * info)72 static NativeValue* MakeMirror(NativeEngine* engine, NativeCallbackInfo* info)
73 {
74     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
75     return (me != nullptr) ? me->OnMakeMirror(*engine, *info) : nullptr;
76 }
77 
MakeExpand(NativeEngine * engine,NativeCallbackInfo * info)78 static NativeValue* MakeExpand(NativeEngine* engine, NativeCallbackInfo* info)
79 {
80     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
81     return (me != nullptr) ? me->OnMakeExpand(*engine, *info) : nullptr;
82 }
83 
CreateVirtualScreen(NativeEngine * engine,NativeCallbackInfo * info)84 static NativeValue* CreateVirtualScreen(NativeEngine* engine, NativeCallbackInfo* info)
85 {
86     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
87     return (me != nullptr) ? me->OnCreateVirtualScreen(*engine, *info) : nullptr;
88 }
89 
DestroyVirtualScreen(NativeEngine * engine,NativeCallbackInfo * info)90 static NativeValue* DestroyVirtualScreen(NativeEngine* engine, NativeCallbackInfo* info)
91 {
92     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
93     return (me != nullptr) ? me->OnDestroyVirtualScreen(*engine, *info) : nullptr;
94 }
95 
SetVirtualScreenSurface(NativeEngine * engine,NativeCallbackInfo * info)96 static NativeValue* SetVirtualScreenSurface(NativeEngine* engine, NativeCallbackInfo* info)
97 {
98     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
99     return (me != nullptr) ? me->OnSetVirtualScreenSurface(*engine, *info) : nullptr;
100 }
101 
IsScreenRotationLocked(NativeEngine * engine,NativeCallbackInfo * info)102 static NativeValue* IsScreenRotationLocked(NativeEngine* engine, NativeCallbackInfo* info)
103 {
104     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
105     return (me != nullptr) ? me->OnIsScreenRotationLocked(*engine, *info) : nullptr;
106 }
107 
SetScreenRotationLocked(NativeEngine * engine,NativeCallbackInfo * info)108 static NativeValue* SetScreenRotationLocked(NativeEngine* engine, NativeCallbackInfo* info)
109 {
110     JsScreenManager* me = CheckParamsAndGetThis<JsScreenManager>(engine, info);
111     return (me != nullptr) ? me->OnSetScreenRotationLocked(*engine, *info) : nullptr;
112 }
113 private:
114 std::map<std::string, std::map<std::unique_ptr<NativeReference>, sptr<JsScreenListener>>> jsCbMap_;
115 std::mutex mtx_;
116 
OnGetAllScreens(NativeEngine & engine,NativeCallbackInfo & info)117 NativeValue* OnGetAllScreens(NativeEngine& engine, NativeCallbackInfo& info)
118 {
119     WLOGFI("OnGetAllScreens is called");
120     AsyncTask::CompleteCallback complete =
121         [this](NativeEngine& engine, AsyncTask& task, int32_t status) {
122             std::vector<sptr<Screen>> screens = SingletonContainer::Get<ScreenManager>().GetAllScreens();
123             if (!screens.empty()) {
124                 task.Resolve(engine, CreateJsScreenVectorObject(engine, screens));
125                 WLOGFI("JsScreenManager::OnGetAllScreens success");
126             } else {
127                 task.Reject(engine, CreateJsError(engine,
128                     static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN),
129                     "JsScreenManager::OnGetAllScreens failed."));
130             }
131         };
132     NativeValue* lastParam = nullptr;
133     if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr &&
134         info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) {
135         lastParam = info.argv[ARGC_ONE - 1];
136     }
137     NativeValue* result = nullptr;
138     AsyncTask::Schedule("JsScreenManager::OnGetAllScreens",
139         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
140     return result;
141 }
142 
CreateJsScreenVectorObject(NativeEngine & engine,std::vector<sptr<Screen>> & screens)143 NativeValue* CreateJsScreenVectorObject(NativeEngine& engine, std::vector<sptr<Screen>>& screens)
144 {
145     NativeValue* arrayValue = engine.CreateArray(screens.size());
146     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
147     if (array == nullptr) {
148         WLOGFE("Failed to get screens");
149         return engine.CreateUndefined();
150     }
151     size_t i = 0;
152     for (auto& screen : screens) {
153         if (screen == nullptr) {
154             continue;
155         }
156         array->SetElement(i++, CreateJsScreenObject(engine, screen));
157     }
158     return arrayValue;
159 }
160 
IfCallbackRegistered(const std::string & type,NativeValue * jsListenerObject)161 bool IfCallbackRegistered(const std::string& type, NativeValue* jsListenerObject)
162 {
163     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
164         WLOGFI("JsScreenManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str());
165         return false;
166     }
167 
168     for (auto& iter : jsCbMap_[type]) {
169         if (jsListenerObject->StrictEquals(iter.first->Get())) {
170             WLOGFE("JsScreenManager::IfCallbackRegistered callback already registered!");
171             return true;
172         }
173     }
174     return false;
175 }
176 
RegisterScreenListenerWithType(NativeEngine & engine,const std::string & type,NativeValue * value)177 void RegisterScreenListenerWithType(NativeEngine& engine, const std::string& type, NativeValue* value)
178 {
179     if (IfCallbackRegistered(type, value)) {
180         WLOGFE("JsScreenManager::RegisterScreenListenerWithType callback already registered!");
181         return;
182     }
183     std::unique_ptr<NativeReference> callbackRef;
184     callbackRef.reset(engine.CreateReference(value, 1));
185     sptr<JsScreenListener> screenListener = new(std::nothrow) JsScreenListener(&engine);
186     if (screenListener == nullptr) {
187         WLOGFE("screenListener is nullptr");
188         return;
189     }
190     if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
191         SingletonContainer::Get<ScreenManager>().RegisterScreenListener(screenListener);
192         WLOGFI("JsScreenManager::RegisterScreenListenerWithType success");
193     } else {
194         WLOGFE("JsScreenManager::RegisterScreenListenerWithType failed method: %{public}s not support!",
195             type.c_str());
196         return;
197     }
198     screenListener->AddCallback(type, value);
199     jsCbMap_[type][std::move(callbackRef)] = screenListener;
200 }
201 
UnregisterAllScreenListenerWithType(const std::string & type)202 void UnregisterAllScreenListenerWithType(const std::string& type)
203 {
204     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
205         WLOGFI("JsScreenManager::UnregisterAllScreenListenerWithType methodName %{public}s not registered!",
206             type.c_str());
207         return;
208     }
209     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
210         it->second->RemoveAllCallback();
211         if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
212             sptr<ScreenManager::IScreenListener> thisListener(it->second);
213             SingletonContainer::Get<ScreenManager>().UnregisterScreenListener(thisListener);
214             WLOGFI("JsScreenManager::UnregisterAllScreenListenerWithType success");
215         }
216         jsCbMap_[type].erase(it++);
217     }
218     jsCbMap_.erase(type);
219 }
220 
UnRegisterScreenListenerWithType(const std::string & type,NativeValue * value)221 void UnRegisterScreenListenerWithType(const std::string& type, NativeValue* value)
222 {
223     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
224         WLOGFI("JsScreenManager::UnRegisterScreenListenerWithType methodName %{public}s not registered!",
225             type.c_str());
226         return;
227     }
228     if (value == nullptr) {
229         WLOGFE("JsScreenManager::UnRegisterScreenListenerWithType value is nullptr");
230         return;
231     }
232     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
233         if (value->StrictEquals(it->first->Get())) {
234             it->second->RemoveCallback(type, value);
235             if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) {
236                 sptr<ScreenManager::IScreenListener> thisListener(it->second);
237                 SingletonContainer::Get<ScreenManager>().UnregisterScreenListener(thisListener);
238                 WLOGFI("JsScreenManager::UnRegisterScreenListenerWithType success");
239             }
240             jsCbMap_[type].erase(it++);
241             break;
242         } else {
243             it++;
244         }
245     }
246     if (jsCbMap_[type].empty()) {
247         jsCbMap_.erase(type);
248     }
249 }
250 
OnRegisterScreenMangerCallback(NativeEngine & engine,NativeCallbackInfo & info)251 NativeValue* OnRegisterScreenMangerCallback(NativeEngine& engine, NativeCallbackInfo& info)
252 {
253     WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback is called");
254     if (info.argc < ARGC_TWO) {
255         WLOGFE("Params not match");
256         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
257         return engine.CreateUndefined();
258     }
259     std::string cbType;
260     if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
261         WLOGFE("Failed to convert parameter to callbackType");
262         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
263         return engine.CreateUndefined();
264     }
265     NativeValue* value = info.argv[INDEX_ONE];
266     if (value == nullptr) {
267         WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is nullptr");
268         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
269         return engine.CreateUndefined();
270     }
271     if (!value->IsCallable()) {
272         WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is not callable");
273         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
274         return engine.CreateUndefined();
275     }
276     std::lock_guard<std::mutex> lock(mtx_);
277     RegisterScreenListenerWithType(engine, cbType, value);
278     return engine.CreateUndefined();
279 }
280 
OnUnregisterScreenManagerCallback(NativeEngine & engine,NativeCallbackInfo & info)281 NativeValue* OnUnregisterScreenManagerCallback(NativeEngine& engine, NativeCallbackInfo& info)
282 {
283     WLOGFI("JsScreenManager::OnUnregisterScreenCallback is called");
284     if (info.argc < ARGC_ONE) {
285         WLOGFE("Params not match");
286         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
287         return engine.CreateUndefined();
288     }
289     std::string cbType;
290     if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
291         WLOGFE("Failed to convert parameter to callbackType");
292         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
293         return engine.CreateUndefined();
294     }
295     std::lock_guard<std::mutex> lock(mtx_);
296     if (info.argc == ARGC_ONE) {
297         UnregisterAllScreenListenerWithType(cbType);
298     } else {
299         NativeValue* value = info.argv[INDEX_ONE];
300         if ((value == nullptr) || (!value->IsCallable())) {
301             UnregisterAllScreenListenerWithType(cbType);
302         } else {
303             UnRegisterScreenListenerWithType(cbType, value);
304         }
305     }
306     return engine.CreateUndefined();
307 }
308 
OnMakeMirror(NativeEngine & engine,NativeCallbackInfo & info)309 NativeValue* OnMakeMirror(NativeEngine& engine, NativeCallbackInfo& info)
310 {
311     WLOGFI("OnMakeMirror is called");
312     if (info.argc < ARGC_TWO) {
313         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
314         return engine.CreateUndefined();
315     }
316 
317     int64_t mainScreenId;
318     if (!ConvertFromJsValue(engine, info.argv[0], mainScreenId)) {
319         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
320         return engine.CreateUndefined();
321     }
322     NativeArray* array = ConvertNativeValueTo<NativeArray>(info.argv[INDEX_ONE]);
323     if (array == nullptr) {
324         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
325         return engine.CreateUndefined();
326     }
327     uint32_t size = array->GetLength();
328     std::vector<ScreenId> screenIds;
329     for (uint32_t i = 0; i < size; i++) {
330         uint32_t screenId;
331         NativeValue* value = array->GetElement(i);
332         if (!ConvertFromJsValue(engine, value, screenId)) {
333             engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
334             return engine.CreateUndefined();
335         }
336         screenIds.emplace_back(static_cast<ScreenId>(screenId));
337     }
338 
339     AsyncTask::CompleteCallback complete =
340         [mainScreenId, screenIds](NativeEngine& engine, AsyncTask& task, int32_t status) {
341             ScreenId id = SingletonContainer::Get<ScreenManager>().MakeMirror(mainScreenId, screenIds);
342             if (id != SCREEN_ID_INVALID) {
343                 task.Resolve(engine, CreateJsValue(engine, static_cast<uint32_t>(id)));
344             } else {
345                 task.Reject(engine, CreateJsError(engine,
346                     static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN),
347                     "JsScreenManager::OnMakeMirror failed."));
348             }
349         };
350     NativeValue* lastParam = nullptr;
351     if (info.argc >= ARGC_THREE && info.argv[ARGC_THREE - 1] != nullptr &&
352         info.argv[ARGC_THREE - 1]->TypeOf() == NATIVE_FUNCTION) {
353         lastParam = info.argv[ARGC_THREE - 1];
354     }
355     NativeValue* result = nullptr;
356     AsyncTask::Schedule("JsScreenManager::OnMakeMirror",
357         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
358     return result;
359 }
360 
OnMakeExpand(NativeEngine & engine,NativeCallbackInfo & info)361 NativeValue* OnMakeExpand(NativeEngine& engine, NativeCallbackInfo& info)
362 {
363     WLOGFI("OnMakeExpand is called");
364     if (info.argc < ARGC_ONE) {
365         WLOGFE("Params not match");
366         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
367         return engine.CreateUndefined();
368     }
369 
370     NativeArray* array = ConvertNativeValueTo<NativeArray>(info.argv[0]);
371     if (array == nullptr) {
372         WLOGFE("Failed to get options");
373         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
374         return engine.CreateUndefined();
375     }
376     uint32_t size = array->GetLength();
377     std::vector<ExpandOption> options;
378     for (uint32_t i = 0; i < size; ++i) {
379         NativeObject* object = ConvertNativeValueTo<NativeObject>(array->GetElement(i));
380         ExpandOption expandOption;
381         int32_t res = GetExpandOptionFromJs(engine, object, expandOption);
382         if (res == -1) {
383             WLOGE("expandoption param %{public}d error!", i);
384             engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
385             return engine.CreateUndefined();
386         }
387         options.emplace_back(expandOption);
388     }
389 
390     AsyncTask::CompleteCallback complete =
391         [options](NativeEngine& engine, AsyncTask& task, int32_t status) {
392             ScreenId id = SingletonContainer::Get<ScreenManager>().MakeExpand(options);
393             if (id != SCREEN_ID_INVALID) {
394                 task.Resolve(engine, CreateJsValue(engine, static_cast<uint32_t>(id)));
395                 WLOGFI("MakeExpand success");
396             } else {
397                 task.Reject(engine, CreateJsError(engine,
398                     static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN),
399                     "JsScreenManager::OnMakeExpand failed."));
400                 WLOGFE("MakeExpand failed");
401             }
402         };
403     NativeValue* lastParam = nullptr;
404     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
405         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
406         lastParam = info.argv[ARGC_TWO - 1];
407     }
408     NativeValue* result = nullptr;
409     AsyncTask::Schedule("JsScreenManager::OnMakeExpand",
410         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
411     return result;
412 }
413 
GetExpandOptionFromJs(NativeEngine & engine,NativeObject * optionObject,ExpandOption & option)414 static int32_t GetExpandOptionFromJs(NativeEngine& engine, NativeObject* optionObject, ExpandOption& option)
415 {
416     NativeValue* screedIdValue = optionObject->GetProperty("screenId");
417     NativeValue* startXValue = optionObject->GetProperty("startX");
418     NativeValue* startYValue = optionObject->GetProperty("startY");
419     uint32_t screenId;
420     uint32_t startX;
421     uint32_t startY;
422     if (!ConvertFromJsValue(engine, screedIdValue, screenId)) {
423         WLOGFE("Failed to convert screedIdValue to callbackType");
424         return -1;
425     }
426     if (!ConvertFromJsValue(engine, startXValue, startX)) {
427         WLOGFE("Failed to convert startXValue to callbackType");
428         return -1;
429     }
430     if (!ConvertFromJsValue(engine, startYValue, startY)) {
431         WLOGFE("Failed to convert startYValue to callbackType");
432         return -1;
433     }
434     option = {screenId, startX, startY};
435     return 0;
436 }
437 
OnCreateVirtualScreen(NativeEngine & engine,NativeCallbackInfo & info)438 NativeValue* OnCreateVirtualScreen(NativeEngine& engine, NativeCallbackInfo& info)
439 {
440     WLOGFI("JsScreenManager::OnCreateVirtualScreen is called");
441     DmErrorCode errCode = DmErrorCode::DM_OK;
442     VirtualScreenOption option;
443     if (info.argc < ARGC_ONE) {
444         WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc);
445         errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
446     } else {
447         NativeObject* object = ConvertNativeValueTo<NativeObject>(info.argv[0]);
448         if (object == nullptr) {
449             WLOGFE("Failed to convert parameter to VirtualScreenOption.");
450             errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
451         } else {
452             errCode = GetVirtualScreenOptionFromJs(engine, object, option);
453         }
454     }
455     if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) {
456         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
457         return engine.CreateUndefined();
458     }
459     AsyncTask::CompleteCallback complete =
460         [option](NativeEngine& engine, AsyncTask& task, int32_t status) {
461             auto screenId = SingletonContainer::Get<ScreenManager>().CreateVirtualScreen(option);
462             auto screen = SingletonContainer::Get<ScreenManager>().GetScreenById(screenId);
463             if (screen == nullptr) {
464                 task.Reject(engine, CreateJsError(engine,
465                     static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN),
466                     "ScreenManager::CreateVirtualScreen failed."));
467                 WLOGFE("ScreenManager::CreateVirtualScreen failed.");
468                 return;
469             }
470             task.Resolve(engine, CreateJsScreenObject(engine, screen));
471             WLOGFI("JsScreenManager::OnCreateVirtualScreen success");
472         };
473     NativeValue* lastParam = nullptr;
474     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
475         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
476         lastParam = info.argv[ARGC_TWO - 1];
477     }
478     NativeValue* result = nullptr;
479     AsyncTask::Schedule("JsScreenManager::OnCreateVirtualScreen",
480         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
481     return result;
482 }
483 
GetVirtualScreenOptionFromJs(NativeEngine & engine,NativeObject * optionObject,VirtualScreenOption & option)484 DmErrorCode GetVirtualScreenOptionFromJs(NativeEngine& engine, NativeObject* optionObject, VirtualScreenOption& option)
485 {
486     NativeValue* name = optionObject->GetProperty("name");
487     if (!ConvertFromJsValue(engine, name, option.name_)) {
488         WLOGFE("Failed to convert parameter to name.");
489         return DmErrorCode::DM_ERROR_INVALID_PARAM;
490     }
491     NativeValue* width = optionObject->GetProperty("width");
492     if (!ConvertFromJsValue(engine, width, option.width_)) {
493         WLOGFE("Failed to convert parameter to width.");
494         return DmErrorCode::DM_ERROR_INVALID_PARAM;
495     }
496     NativeValue* height = optionObject->GetProperty("height");
497     if (!ConvertFromJsValue(engine, height, option.height_)) {
498         WLOGFE("Failed to convert parameter to height.");
499         return DmErrorCode::DM_ERROR_INVALID_PARAM;
500     }
501     NativeValue* density = optionObject->GetProperty("density");
502     double densityValue;
503     if (!ConvertFromJsValue(engine, density, densityValue)) {
504         WLOGFE("Failed to convert parameter to density.");
505         return DmErrorCode::DM_ERROR_INVALID_PARAM;
506     }
507     option.density_ = static_cast<float>(densityValue);
508 
509     NativeValue* surfaceIdNativeValue = optionObject->GetProperty("surfaceId");
510     if (!GetSurfaceFromJs(engine, surfaceIdNativeValue, option.surface_)) {
511         return DmErrorCode::DM_ERROR_INVALID_PARAM;
512     }
513     return DmErrorCode::DM_OK;
514 }
515 
GetSurfaceFromJs(NativeEngine & engine,NativeValue * surfaceIdNativeValue,sptr<Surface> & surface)516 bool GetSurfaceFromJs(NativeEngine& engine, NativeValue* surfaceIdNativeValue, sptr<Surface>& surface)
517 {
518     if (surfaceIdNativeValue == nullptr || surfaceIdNativeValue->TypeOf() != NATIVE_STRING) {
519         WLOGFE("Failed to convert parameter to surface. Invalidate params.");
520         return false;
521     }
522     char buffer[PATH_MAX];
523     size_t length = 0;
524     uint64_t surfaceId = 0;
525     napi_env env = reinterpret_cast<napi_env>(&engine);
526     napi_value surfaceIdValue = reinterpret_cast<napi_value>(surfaceIdNativeValue);
527     if (napi_get_value_string_utf8(env, surfaceIdValue, buffer, PATH_MAX, &length) != napi_ok) {
528         WLOGFE("Failed to convert parameter to surface.");
529         return false;
530     }
531     std::istringstream inputStream(buffer);
532     inputStream >> surfaceId;
533     surface = SurfaceUtils::GetInstance()->GetSurface(surfaceId);
534     if (surface == nullptr) {
535         WLOGFI("GetSurfaceFromJs failed, surfaceId:%{public}" PRIu64"", surfaceId);
536     }
537     return true;
538 }
539 
OnDestroyVirtualScreen(NativeEngine & engine,NativeCallbackInfo & info)540 NativeValue* OnDestroyVirtualScreen(NativeEngine& engine, NativeCallbackInfo& info)
541 {
542     WLOGFI("JsScreenManager::OnDestroyVirtualScreen is called");
543     DmErrorCode errCode = DmErrorCode::DM_OK;
544     int64_t screenId = -1LL;
545     if (info.argc < ARGC_ONE) {
546         WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc);
547         errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
548     } else {
549         if (!ConvertFromJsValue(engine, info.argv[0], screenId)) {
550             WLOGFE("Failed to convert parameter to screen id.");
551             errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
552         }
553     }
554     if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || screenId == -1LL) {
555         WLOGFE("JsScreenManager::OnDestroyVirtualScreen failed, Invalidate params.");
556         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
557         return engine.CreateUndefined();
558     }
559     AsyncTask::CompleteCallback complete =
560         [screenId](NativeEngine& engine, AsyncTask& task, int32_t status) {
561             auto res = DM_JS_TO_ERROR_CODE_MAP.at(
562                 SingletonContainer::Get<ScreenManager>().DestroyVirtualScreen(screenId));
563             if (res != DmErrorCode::DM_OK) {
564                 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(res),
565                     "ScreenManager::DestroyVirtualScreen failed."));
566                 WLOGFE("ScreenManager::DestroyVirtualScreen failed.");
567                 return;
568             }
569             task.Resolve(engine, engine.CreateUndefined());
570             WLOGFI("JsScreenManager::OnDestroyVirtualScreen success");
571         };
572     NativeValue* lastParam = nullptr;
573     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
574         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
575         lastParam = info.argv[ARGC_TWO - 1];
576     }
577     NativeValue* result = nullptr;
578     AsyncTask::Schedule("JsScreenManager::OnDestroyVirtualScreen",
579         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
580     return result;
581 }
582 
OnSetVirtualScreenSurface(NativeEngine & engine,NativeCallbackInfo & info)583 NativeValue* OnSetVirtualScreenSurface(NativeEngine& engine, NativeCallbackInfo& info)
584 {
585     WLOGFI("JsScreenManager::OnSetVirtualScreenSurface is called");
586     DmErrorCode errCode = DmErrorCode::DM_OK;
587     int64_t screenId = -1LL;
588     sptr<Surface> surface;
589     if (info.argc < ARGC_TWO) {
590         WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc);
591         errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
592     } else {
593         if (!ConvertFromJsValue(engine, info.argv[0], screenId)) {
594             WLOGFE("Failed to convert parameter to screen id.");
595             errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
596         }
597         if (!GetSurfaceFromJs(engine, info.argv[1], surface)) {
598             WLOGFE("Failed to convert parameter to surface");
599             errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
600         }
601     }
602     if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || surface == nullptr) {
603         WLOGFE("JsScreenManager::OnSetVirtualScreenSurface failed, Invalidate params.");
604         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
605         return engine.CreateUndefined();
606     }
607     AsyncTask::CompleteCallback complete =
608         [screenId, surface](NativeEngine& engine, AsyncTask& task, int32_t status) {
609             auto res = DM_JS_TO_ERROR_CODE_MAP.at(
610                 SingletonContainer::Get<ScreenManager>().SetVirtualScreenSurface(screenId, surface));
611             if (res != DmErrorCode::DM_OK) {
612                 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(res),
613                     "ScreenManager::SetVirtualScreenSurface failed."));
614                 WLOGFE("ScreenManager::SetVirtualScreenSurface failed.");
615                 return;
616             }
617             task.Resolve(engine, engine.CreateUndefined());
618             WLOGFI("JsScreenManager::OnSetVirtualScreenSurface success");
619         };
620     NativeValue* lastParam = nullptr;
621     if (info.argc >= ARGC_THREE && info.argv[ARGC_THREE - 1] != nullptr &&
622         info.argv[ARGC_THREE - 1]->TypeOf() == NATIVE_FUNCTION) {
623         lastParam = info.argv[ARGC_THREE - 1];
624     }
625     NativeValue* result = nullptr;
626     AsyncTask::Schedule("JsScreenManager::OnSetVirtualScreenSurface",
627         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
628     return result;
629 }
630 
OnIsScreenRotationLocked(NativeEngine & engine,NativeCallbackInfo & info)631 NativeValue* OnIsScreenRotationLocked(NativeEngine& engine, NativeCallbackInfo& info)
632 {
633     WLOGFI("OnIsScreenRotationLocked is called");
634     AsyncTask::CompleteCallback complete =
635         [](NativeEngine& engine, AsyncTask& task, int32_t status) {
636             bool isLocked = SingletonContainer::Get<ScreenManager>().IsScreenRotationLocked();
637             task.Resolve(engine, CreateJsValue(engine, isLocked));
638         };
639     NativeValue* lastParam = nullptr;
640     if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr &&
641         info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) {
642         lastParam = info.argv[ARGC_ONE - 1];
643     }
644     NativeValue* result = nullptr;
645     AsyncTask::Schedule("JsScreenManager::OnIsScreenRotationLocked",
646         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
647     return result;
648 }
649 
OnSetScreenRotationLocked(NativeEngine & engine,NativeCallbackInfo & info)650 NativeValue* OnSetScreenRotationLocked(NativeEngine& engine, NativeCallbackInfo& info)
651 {
652     WLOGFI("JsScreenManager::OnSetScreenRotationLocked is called");
653     DmErrorCode errCode = DmErrorCode::DM_OK;
654     if (info.argc < ARGC_ONE) {
655         WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc);
656         errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
657     }
658     bool isLocked = false;
659     if (errCode == DmErrorCode::DM_OK) {
660         NativeBoolean* nativeVal = ConvertNativeValueTo<NativeBoolean>(info.argv[0]);
661         if (nativeVal == nullptr) {
662             WLOGFE("[NAPI]Failed to convert parameter to isLocked");
663             errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
664         } else {
665             isLocked = static_cast<bool>(*nativeVal);
666         }
667     }
668     if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) {
669         WLOGFE("JsScreenManager::OnSetScreenRotationLocked failed, Invalidate params.");
670         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
671         return engine.CreateUndefined();
672     }
673 
674     AsyncTask::CompleteCallback complete =
675         [isLocked](NativeEngine& engine, AsyncTask& task, int32_t status) {
676             SingletonContainer::Get<ScreenManager>().SetScreenRotationLocked(isLocked);
677             task.Resolve(engine, engine.CreateUndefined());
678         };
679     NativeValue* lastParam = (info.argc <= ARGC_ONE) ? nullptr :
680         ((info.argv[ARGC_TWO - 1] != nullptr && info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) ?
681         info.argv[1] : nullptr);
682     NativeValue* result = nullptr;
683     AsyncTask::Schedule("JsScreenManager::OnSetScreenRotationLocked",
684         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
685     return result;
686 }
687 };
688 
InitScreenOrientation(NativeEngine * engine)689 NativeValue* InitScreenOrientation(NativeEngine* engine)
690 {
691     WLOGFI("JsScreenManager::InitScreenOrientation called");
692 
693     if (engine == nullptr) {
694         WLOGFE("engine is nullptr");
695         return nullptr;
696     }
697 
698     NativeValue *objValue = engine->CreateObject();
699     NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
700     if (object == nullptr) {
701         WLOGFE("Failed to get object");
702         return nullptr;
703     }
704 
705     object->SetProperty("UNSPECIFIED", CreateJsValue(*engine, static_cast<int32_t>(Orientation::UNSPECIFIED)));
706     object->SetProperty("VERTICAL", CreateJsValue(*engine, static_cast<int32_t>(Orientation::VERTICAL)));
707     object->SetProperty("HORIZONTAL", CreateJsValue(*engine, static_cast<int32_t>(Orientation::HORIZONTAL)));
708     object->SetProperty("REVERSE_VERTICAL",
709         CreateJsValue(*engine, static_cast<int32_t>(Orientation::REVERSE_VERTICAL)));
710     object->SetProperty("REVERSE_HORIZONTAL",
711         CreateJsValue(*engine, static_cast<int32_t>(Orientation::REVERSE_HORIZONTAL)));
712     return objValue;
713 }
714 
InitDisplayErrorCode(NativeEngine * engine)715 NativeValue* InitDisplayErrorCode(NativeEngine* engine)
716 {
717     WLOGFI("JsDisplayManager::InitDisplayErrorCode called");
718 
719     if (engine == nullptr) {
720         WLOGFE("engine is nullptr");
721         return nullptr;
722     }
723 
724     NativeValue *objValue = engine->CreateObject();
725     NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
726     if (object == nullptr) {
727         WLOGFE("Failed to get object");
728         return nullptr;
729     }
730 
731     object->SetProperty("DM_ERROR_NO_PERMISSION",
732         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_NO_PERMISSION)));
733     object->SetProperty("DM_ERROR_INVALID_PARAM",
734         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
735     object->SetProperty("DM_ERROR_DEVICE_NOT_SUPPORT",
736         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT)));
737     object->SetProperty("DM_ERROR_INVALID_SCREEN",
738         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN)));
739     object->SetProperty("DM_ERROR_INVALID_CALLING",
740         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_CALLING)));
741     object->SetProperty("DM_ERROR_SYSTEM_INNORMAL",
742         CreateJsValue(*engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL)));
743     return objValue;
744 }
745 
InitDisplayError(NativeEngine * engine)746 NativeValue* InitDisplayError(NativeEngine* engine)
747 {
748     WLOGFI("JsDisplayManager::InitDisplayError called");
749 
750     if (engine == nullptr) {
751         WLOGFE("engine is nullptr");
752         return nullptr;
753     }
754 
755     NativeValue *objValue = engine->CreateObject();
756     NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
757     if (object == nullptr) {
758         WLOGFE("Failed to get object");
759         return nullptr;
760     }
761 
762     object->SetProperty("DM_ERROR_INIT_DMS_PROXY_LOCKED",
763         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED)));
764     object->SetProperty("DM_ERROR_IPC_FAILED",
765         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_IPC_FAILED)));
766     object->SetProperty("DM_ERROR_REMOTE_CREATE_FAILED",
767         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_REMOTE_CREATE_FAILED)));
768     object->SetProperty("DM_ERROR_NULLPTR",
769         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_NULLPTR)));
770     object->SetProperty("DM_ERROR_INVALID_PARAM",
771         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_INVALID_PARAM)));
772     object->SetProperty("DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED",
773         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED)));
774     object->SetProperty("DM_ERROR_DEATH_RECIPIENT",
775         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_DEATH_RECIPIENT)));
776     object->SetProperty("DM_ERROR_INVALID_MODE_ID",
777         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_INVALID_MODE_ID)));
778     object->SetProperty("DM_ERROR_WRITE_DATA_FAILED",
779         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_WRITE_DATA_FAILED)));
780     object->SetProperty("DM_ERROR_RENDER_SERVICE_FAILED",
781         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_RENDER_SERVICE_FAILED)));
782     object->SetProperty("DM_ERROR_UNREGISTER_AGENT_FAILED",
783         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_UNREGISTER_AGENT_FAILED)));
784     object->SetProperty("DM_ERROR_INVALID_CALLING",
785         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_INVALID_CALLING)));
786     object->SetProperty("DM_ERROR_UNKNOWN",
787         CreateJsValue(*engine, static_cast<int32_t>(DMError::DM_ERROR_UNKNOWN)));
788     return objValue;
789 }
790 
JsScreenManagerInit(NativeEngine * engine,NativeValue * exportObj)791 NativeValue* JsScreenManagerInit(NativeEngine* engine, NativeValue* exportObj)
792 {
793     WLOGFI("JsScreenManagerInit is called");
794 
795     if (engine == nullptr || exportObj == nullptr) {
796         WLOGFE("JsScreenManagerInit engine or exportObj is nullptr");
797         return nullptr;
798     }
799 
800     NativeObject* object = ConvertNativeValueTo<NativeObject>(exportObj);
801     if (object == nullptr) {
802         WLOGFE("JsScreenManagerInit object is nullptr");
803         return nullptr;
804     }
805 
806     std::unique_ptr<JsScreenManager> jsScreenManager = std::make_unique<JsScreenManager>(engine);
807     object->SetNativePointer(jsScreenManager.release(), JsScreenManager::Finalizer, nullptr);
808 
809     object->SetProperty("Orientation", InitScreenOrientation(engine));
810     object->SetProperty("DmErrorCode", InitDisplayErrorCode(engine));
811     object->SetProperty("DMError", InitDisplayError(engine));
812 
813     const char *moduleName = "JsScreenManager";
814     BindNativeFunction(*engine, *object, "getAllScreens", moduleName, JsScreenManager::GetAllScreens);
815     BindNativeFunction(*engine, *object, "on", moduleName, JsScreenManager::RegisterScreenManagerCallback);
816     BindNativeFunction(*engine, *object, "off", moduleName, JsScreenManager::UnregisterScreenMangerCallback);
817     BindNativeFunction(*engine, *object, "makeMirror", moduleName, JsScreenManager::MakeMirror);
818     BindNativeFunction(*engine, *object, "makeExpand", moduleName, JsScreenManager::MakeExpand);
819     BindNativeFunction(*engine, *object, "createVirtualScreen", moduleName, JsScreenManager::CreateVirtualScreen);
820     BindNativeFunction(*engine, *object, "destroyVirtualScreen", moduleName, JsScreenManager::DestroyVirtualScreen);
821     BindNativeFunction(*engine, *object, "setVirtualScreenSurface", moduleName,
822         JsScreenManager::SetVirtualScreenSurface);
823     BindNativeFunction(*engine, *object, "setScreenRotationLocked", moduleName,
824         JsScreenManager::SetScreenRotationLocked);
825     BindNativeFunction(*engine, *object, "isScreenRotationLocked", moduleName,
826         JsScreenManager::IsScreenRotationLocked);
827     return engine->CreateUndefined();
828 }
829 }  // namespace Rosen
830 }  // namespace OHOS