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