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_display.h"
17
18 #include <cinttypes>
19 #include <hitrace_meter.h>
20 #include <map>
21 #include <set>
22
23 #include "cutout_info.h"
24 #include "display.h"
25 #include "display_info.h"
26 #include "window_manager_hilog.h"
27 #include "display_manager.h"
28 #include "singleton_container.h"
29 #include "js_display_listener.h"
30
31 namespace OHOS {
32 namespace Rosen {
33 using namespace AbilityRuntime;
34 constexpr size_t ARGC_ONE = 1;
35 constexpr size_t ARGC_TWO = 2;
36 constexpr int32_t INDEX_ONE = 1;
37 namespace {
38 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsDisplay"};
39 const std::map<DisplayState, DisplayStateMode> NATIVE_TO_JS_DISPLAY_STATE_MAP {
40 { DisplayState::UNKNOWN, DisplayStateMode::STATE_UNKNOWN },
41 { DisplayState::OFF, DisplayStateMode::STATE_OFF },
42 { DisplayState::ON, DisplayStateMode::STATE_ON },
43 { DisplayState::DOZE, DisplayStateMode::STATE_DOZE },
44 { DisplayState::DOZE_SUSPEND, DisplayStateMode::STATE_DOZE_SUSPEND },
45 { DisplayState::VR, DisplayStateMode::STATE_VR },
46 { DisplayState::ON_SUSPEND, DisplayStateMode::STATE_ON_SUSPEND },
47 };
48
49 using GraphicCM_ColorSpaceType = enum {
50 GRAPHIC_CM_COLORSPACE_NONE,
51
52 GRAPHIC_CM_BT601_EBU_FULL = 2 | (1 << 8) | (2 << 16) | (1 << 21), // COLORPRIMARIES_BT601_P | (TRANSFUNC_BT709 << 8) | (MATRIX_BT601_P << 16) | (RANGE_FULL << 21)
53 GRAPHIC_CM_BT601_SMPTE_C_FULL = 3 | (1 << 8) | (3 << 16) | (1 << 21), // COLORPRIMARIES_BT601_N | (TRANSFUNC_BT709 << 8) | (MATRIX_BT601_N << 16) | (RANGE_FULL << 21)
54 GRAPHIC_CM_BT709_FULL = 1 | (1 << 8) | (1 << 16) | (1 << 21), // COLORPRIMARIES_BT709 | (TRANSFUNC_BT709 << 8) | (MATRIX_BT709 << 16) | (RANGE_FULL << 21)
55 GRAPHIC_CM_BT2020_HLG_FULL = 4 | (5 << 8) | (4 << 16) | (1 << 21), // COLORPRIMARIES_BT2020 | (TRANSFUNC_HLG << 8) | (MATRIX_BT2020 << 16) | (RANGE_FULL << 21)
56 GRAPHIC_CM_BT2020_PQ_FULL = 4 | (4 << 8) | (4 << 16) | (1 << 21), // COLORPRIMARIES_BT2020 | (TRANSFUNC_PQ << 8) | (MATRIX_BT2020 << 16) | (RANGE_FULL << 21)
57
58 GRAPHIC_CM_BT601_EBU_LIMIT = 2 | (1 << 8) | (2 << 16) | (2 << 21), // COLORPRIMARIES_BT601_P | (TRANSFUNC_BT709 << 8) | (MATRIX_BT601_P << 16) | (RANGE_LIMITED << 21)
59 GRAPHIC_CM_BT601_SMPTE_C_LIMIT = 3 | (1 << 8) | (3 << 16) | (2 << 21), // COLORPRIMARIES_BT601_N | (TRANSFUNC_BT709 << 8) | (MATRIX_BT601_N << 16) | (RANGE_LIMITED << 21)
60 GRAPHIC_CM_BT709_LIMIT = 1 | (1 << 8) | (1 << 16) | (2 << 21), // COLORPRIMARIES_BT709 | (TRANSFUNC_BT709 << 8) | (MATRIX_BT709 << 16) | (RANGE_LIMITED << 21)
61 GRAPHIC_CM_BT2020_HLG_LIMIT = 4 | (5 << 8) | (4 << 16) | (2 << 21), // COLORPRIMARIES_BT2020 | (TRANSFUNC_HLG << 8) | (MATRIX_BT2020 << 16) | (RANGE_LIMITED << 21)
62 GRAPHIC_CM_BT2020_PQ_LIMIT = 4 | (4 << 8) | (4 << 16) | (2 << 21), // COLORPRIMARIES_BT2020 | (TRANSFUNC_PQ << 8) | (MATRIX_BT2020 << 16) | (RANGE_LIMITED << 21)
63
64 GRAPHIC_CM_SRGB_FULL = 1 | (2 << 8) | (3 << 16) | (1 << 21), // COLORPRIMARIES_SRGB | (TRANSFUNC_SRGB << 8) | (MATRIX_BT601_N << 16) | (RANGE_FULL << 21)
65 GRAPHIC_CM_P3_FULL = 6 | (2 << 8) | (3 << 16) | (1 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_SRGB << 8) | (MATRIX_P3 << 16) | (RANGE_FULL << 21)
66 GRAPHIC_CM_P3_HLG_FULL = 6 | (5 << 8) | (3 << 16) | (1 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_HLG << 8) | (MATRIX_P3 << 16) | (RANGE_FULL << 21)
67 GRAPHIC_CM_P3_PQ_FULL = 6 | (4 << 8) | (3 << 16) | (1 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_PQ << 8) | (MATRIX_P3 << 16) | (RANGE_FULL << 21)
68 GRAPHIC_CM_ADOBERGB_FULL = 23 | (6 << 8) | (0 << 16) | (1 << 21), // COLORPRIMARIES_ADOBERGB | (TRANSFUNC_ADOBERGB << 8) | (MATRIX_ADOBERGB << 16) | (RANGE_FULL << 21)
69
70 GRAPHIC_CM_SRGB_LIMIT = 1 | (2 << 8) | (3 << 16) | (2 << 21), // COLORPRIMARIES_SRGB | (TRANSFUNC_SRGB << 8) | (MATRIX_BT601_N << 16) | (RANGE_LIMITED << 21)
71 GRAPHIC_CM_P3_LIMIT = 6 | (2 << 8) | (3 << 16) | (2 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_SRGB << 8) | (MATRIX_P3 << 16) | (RANGE_LIMITED << 21)
72 GRAPHIC_CM_P3_HLG_LIMIT = 6 | (5 << 8) | (3 << 16) | (2 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_HLG << 8) | (MATRIX_P3 << 16) | (RANGE_LIMITED << 21)
73 GRAPHIC_CM_P3_PQ_LIMIT = 6 | (4 << 8) | (3 << 16) | (2 << 21), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_PQ << 8) | (MATRIX_P3 << 16) | (RANGE_LIMITED << 21)
74 GRAPHIC_CM_ADOBERGB_LIMIT = 23 | (6 << 8) | (0 << 16) | (2 << 21), // COLORPRIMARIES_ADOBERGB | (TRANSFUNC_ADOBERGB << 8) | (MATRIX_ADOBERGB << 16) | (RANGE_LIMITED << 21)
75
76 GRAPHIC_CM_LINEAR_SRGB = 1 | (3 << 8), // COLORPRIMARIES_SRGB | (TRANSFUNC_LINEAR << 8)
77 GRAPHIC_CM_LINEAR_BT709 = 1 | (3 << 8), // equal to GRAPHIC_CM_LINEAR_SRGB
78 GRAPHIC_CM_LINEAR_P3 = 6 | (3 << 8), // COLORPRIMARIES_P3_D65 | (TRANSFUNC_LINEAR << 8)
79 GRAPHIC_CM_LINEAR_BT2020 = 4 | (3 << 8), // COLORPRIMARIES_BT2020 | (TRANSFUNC_LINEAR << 8)
80
81 GRAPHIC_CM_DISPLAY_SRGB = 1 | (2 << 8) | (3 << 16) | (1 << 21), // equal to GRAPHIC_CM_SRGB_FULL
82 GRAPHIC_CM_DISPLAY_P3_SRGB = 6 | (2 << 8) | (3 << 16) | (1 << 21), // equal to GRAPHIC_CM_P3_FULL
83 GRAPHIC_CM_DISPLAY_P3_HLG = 6 | (5 << 8) | (3 << 16) | (1 << 21), // equal to GRAPHIC_CM_P3_HLG_FULL
84 GRAPHIC_CM_DISPLAY_P3_PQ = 6 | (4 << 8) | (3 << 16) | (1 << 21), // equal to GRAPHIC_CM_P3_PQ_FULL
85 GRAPHIC_CM_DISPLAY_BT2020_SRGB = 4 | (2 << 8) | (4 << 16) | (1 << 21), // COLORPRIMARIES_BT2020 | (TRANSFUNC_SRGB << 8) | (MATRIX_BT2020 << 16) | (RANGE_FULL << 21)
86 GRAPHIC_CM_DISPLAY_BT2020_HLG = 4 | (5 << 8) | (4 << 16) | (1 << 21), // equal to GRAPHIC_CM_BT2020_HLG_FULL
87 GRAPHIC_CM_DISPLAY_BT2020_PQ = 4 | (4 << 8) | (4 << 16) | (1 << 21) // equal to GRAPHIC_CM_BT2020_PQ_FULL
88 };
89
90 typedef enum : uint32_t {
91 NOT_SUPPORT_HDR = 0,
92 VIDEO_HLG,
93 VIDEO_HDR10,
94 VIDEO_HDR_VIVID,
95 IMAGE_HDR_VIVID_DUAL,
96 IMAGE_HDR_VIVID_SINGLE,
97 IMAGE_HDR_ISO_DUAL,
98 IMAGE_HDR_ISO_SINGLE,
99 } ScreenHDRFormat;
100
101 const std::map<GraphicCM_ColorSpaceType, ColorSpace> NATIVE_TO_JS_COLOR_SPACE_TYPE_MAP {
102 { GraphicCM_ColorSpaceType::GRAPHIC_CM_COLORSPACE_NONE, ColorSpace::UNKNOWN },
103 { GraphicCM_ColorSpaceType::GRAPHIC_CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB },
104 { GraphicCM_ColorSpaceType::GRAPHIC_CM_ADOBERGB_LIMIT, ColorSpace::ADOBE_RGB },
105 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT2020_HLG_FULL, ColorSpace::BT2020_HLG },
106 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT2020_HLG_LIMIT, ColorSpace::BT2020_HLG },
107 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_BT2020_HLG, ColorSpace::BT2020_HLG },
108 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT2020_PQ_FULL, ColorSpace::BT2020_PQ },
109 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT2020_PQ_LIMIT, ColorSpace::BT2020_PQ },
110 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_BT2020_PQ, ColorSpace::BT2020_PQ },
111 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT601_EBU_FULL, ColorSpace::BT601_EBU },
112 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT601_EBU_LIMIT, ColorSpace::BT601_EBU },
113 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT601_SMPTE_C_FULL, ColorSpace::BT601_SMPTE_C },
114 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT601_SMPTE_C_LIMIT, ColorSpace::BT601_SMPTE_C },
115 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT709_FULL, ColorSpace::BT709 },
116 { GraphicCM_ColorSpaceType::GRAPHIC_CM_BT709_LIMIT, ColorSpace::BT709 },
117 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_HLG_FULL, ColorSpace::P3_HLG },
118 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_HLG_LIMIT, ColorSpace::P3_HLG },
119 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_P3_HLG, ColorSpace::P3_HLG },
120 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_PQ_FULL, ColorSpace::P3_PQ },
121 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_PQ_LIMIT, ColorSpace::P3_PQ },
122 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_P3_PQ, ColorSpace::P3_PQ },
123 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_FULL, ColorSpace::DISPLAY_P3 },
124 { GraphicCM_ColorSpaceType::GRAPHIC_CM_P3_LIMIT, ColorSpace::DISPLAY_P3 },
125 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_P3_SRGB, ColorSpace::DISPLAY_P3 },
126 { GraphicCM_ColorSpaceType::GRAPHIC_CM_SRGB_FULL, ColorSpace::SRGB },
127 { GraphicCM_ColorSpaceType::GRAPHIC_CM_SRGB_LIMIT, ColorSpace::SRGB },
128 { GraphicCM_ColorSpaceType::GRAPHIC_CM_DISPLAY_SRGB, ColorSpace::SRGB },
129 { GraphicCM_ColorSpaceType::GRAPHIC_CM_LINEAR_SRGB, ColorSpace::LINEAR_SRGB },
130 { GraphicCM_ColorSpaceType::GRAPHIC_CM_LINEAR_BT709, ColorSpace::LINEAR_SRGB },
131 { GraphicCM_ColorSpaceType::GRAPHIC_CM_LINEAR_P3, ColorSpace::LINEAR_P3 },
132 { GraphicCM_ColorSpaceType::GRAPHIC_CM_LINEAR_BT2020, ColorSpace::LINEAR_BT2020 },
133 };
134
135 const std::map<ScreenHDRFormat, HDRFormat> NATIVE_TO_JS_HDR_FORMAT_TYPE_MAP {
136 { ScreenHDRFormat::NOT_SUPPORT_HDR, HDRFormat::NONE },
137 { ScreenHDRFormat::VIDEO_HLG, HDRFormat::VIDEO_HLG },
138 { ScreenHDRFormat::VIDEO_HDR10, HDRFormat::VIDEO_HDR10 },
139 { ScreenHDRFormat::VIDEO_HDR_VIVID, HDRFormat::VIDEO_HDR_VIVID },
140 { ScreenHDRFormat::IMAGE_HDR_VIVID_DUAL, HDRFormat::IMAGE_HDR_VIVID_DUAL },
141 { ScreenHDRFormat::IMAGE_HDR_VIVID_SINGLE, HDRFormat::IMAGE_HDR_VIVID_SINGLE },
142 { ScreenHDRFormat::IMAGE_HDR_ISO_DUAL, HDRFormat::IMAGE_HDR_ISO_DUAL },
143 { ScreenHDRFormat::IMAGE_HDR_ISO_SINGLE, HDRFormat::IMAGE_HDR_ISO_SINGLE },
144 };
145 }
146
147 static thread_local std::map<DisplayId, std::shared_ptr<NativeReference>> g_JsDisplayMap;
148 std::map<std::string, std::map<std::unique_ptr<NativeReference>, sptr<JsDisplayListener>>> jsCbMap_;
149 std::mutex mtx_;
150 std::recursive_mutex g_mutex;
151
JsDisplay(const sptr<Display> & display)152 JsDisplay::JsDisplay(const sptr<Display>& display) : display_(display)
153 {
154 }
155
~JsDisplay()156 JsDisplay::~JsDisplay()
157 {
158 WLOGI("JsDisplay::~JsDisplay is called");
159 }
160
Finalizer(napi_env env,void * data,void * hint)161 void JsDisplay::Finalizer(napi_env env, void* data, void* hint)
162 {
163 WLOGI("JsDisplay::Finalizer is called");
164 auto jsDisplay = std::unique_ptr<JsDisplay>(static_cast<JsDisplay*>(data));
165 if (jsDisplay == nullptr) {
166 WLOGFE("JsDisplay::Finalizer jsDisplay is null");
167 return;
168 }
169 sptr<Display> display = jsDisplay->display_;
170 if (display == nullptr) {
171 WLOGFE("JsDisplay::Finalizer display is null");
172 return;
173 }
174 DisplayId displayId = display->GetId();
175 WLOGI("JsDisplay::Finalizer displayId : %{public}" PRIu64"", displayId);
176 std::lock_guard<std::recursive_mutex> lock(g_mutex);
177 if (g_JsDisplayMap.find(displayId) != g_JsDisplayMap.end()) {
178 WLOGI("JsDisplay::Finalizer Display is destroyed: %{public}" PRIu64"", displayId);
179 g_JsDisplayMap.erase(displayId);
180 }
181 }
182
GetCutoutInfo(napi_env env,napi_callback_info info)183 napi_value JsDisplay::GetCutoutInfo(napi_env env, napi_callback_info info)
184 {
185 WLOGD("GetCutoutInfo is called");
186 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
187 return (me != nullptr) ? me->OnGetCutoutInfo(env, info) : nullptr;
188 }
189
GetDisplayCapability(napi_env env,napi_callback_info info)190 napi_value JsDisplay::GetDisplayCapability(napi_env env, napi_callback_info info)
191 {
192 WLOGI("GetDisplayCapability is called");
193 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
194 return (me != nullptr) ? me->OnGetDisplayCapability(env, info) : nullptr;
195 }
196
GetAvailableArea(napi_env env,napi_callback_info info)197 napi_value JsDisplay::GetAvailableArea(napi_env env, napi_callback_info info)
198 {
199 WLOGI("GetAvailableArea is called");
200 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
201 return (me != nullptr) ? me->OnGetAvailableArea(env, info) : nullptr;
202 }
203
RegisterDisplayManagerCallback(napi_env env,napi_callback_info info)204 napi_value JsDisplay::RegisterDisplayManagerCallback(napi_env env, napi_callback_info info)
205 {
206 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
207 return (me != nullptr) ? me->OnRegisterDisplayManagerCallback(env, info) : nullptr;
208 }
209
UnregisterDisplayManagerCallback(napi_env env,napi_callback_info info)210 napi_value JsDisplay::UnregisterDisplayManagerCallback(napi_env env, napi_callback_info info)
211 {
212 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
213 return (me != nullptr) ? me->OnUnregisterDisplayManagerCallback(env, info) : nullptr;
214 }
215
NapiIsCallable(napi_env env,napi_value value)216 bool NapiIsCallable(napi_env env, napi_value value)
217 {
218 bool result = false;
219 napi_is_callable(env, value, &result);
220 return result;
221 }
222
IfCallbackRegistered(napi_env env,const std::string & type,napi_value jsListenerObject)223 bool IfCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject)
224 {
225 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
226 WLOGI("IfCallbackRegistered methodName %{public}s not registered!", type.c_str());
227 return false;
228 }
229
230 for (auto& iter : jsCbMap_[type]) {
231 bool isEquals = false;
232 napi_strict_equals(env, jsListenerObject, iter.first->GetNapiValue(), &isEquals);
233 if (isEquals) {
234 WLOGFE("IfCallbackRegistered callback already registered!");
235 return true;
236 }
237 }
238 return false;
239 }
240
OnRegisterDisplayManagerCallback(napi_env env,napi_callback_info info)241 napi_value JsDisplay::OnRegisterDisplayManagerCallback(napi_env env, napi_callback_info info)
242 {
243 WLOGD("OnRegisterDisplayManagerCallback is called");
244 size_t argc = 4;
245 napi_value argv[4] = {nullptr};
246 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
247 if (argc < ARGC_TWO) {
248 WLOGFE("JsDisplayManager Params not match: %{public}zu", argc);
249 std::string errMsg = "Invalid args count, need 2 args";
250 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
251 return NapiGetUndefined(env);
252 }
253 std::string cbType;
254 if (!ConvertFromJsValue(env, argv[0], cbType)) {
255 std::string errMsg = "Failed to convert parameter to callbackType";
256 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
257 WLOGFE("Failed to convert parameter to callbackType");
258 return NapiGetUndefined(env);
259 }
260 napi_value value = argv[INDEX_ONE];
261 if (value == nullptr) {
262 WLOGI("OnRegisterDisplayManagerCallback info->argv[1] is nullptr");
263 std::string errMsg = "OnRegisterDisplayManagerCallback is nullptr";
264 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
265 return NapiGetUndefined(env);
266 }
267 if (!NapiIsCallable(env, value)) {
268 WLOGI("OnRegisterDisplayManagerCallback info->argv[1] is not callable");
269 std::string errMsg = "OnRegisterDisplayManagerCallback is not callable";
270 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
271 return NapiGetUndefined(env);
272 }
273 std::lock_guard<std::mutex> lock(mtx_);
274 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(RegisterDisplayListenerWithType(env, cbType, value));
275 if (ret != DmErrorCode::DM_OK) {
276 WLOGFE("Failed to register display listener with type");
277 std::string errMsg = "Failed to register display listener with type";
278 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
279 return NapiGetUndefined(env);
280 }
281 return NapiGetUndefined(env);
282 }
283
RegisterDisplayListenerWithType(napi_env env,const std::string & type,napi_value value)284 DMError JsDisplay::RegisterDisplayListenerWithType(napi_env env, const std::string& type, napi_value value)
285 {
286 if (IfCallbackRegistered(env, type, value)) {
287 WLOGFI("RegisterDisplayListenerWithType callback already registered!");
288 return DMError::DM_OK;
289 }
290 std::unique_ptr<NativeReference> callbackRef;
291 napi_ref result = nullptr;
292 napi_create_reference(env, value, 1, &result);
293 callbackRef.reset(reinterpret_cast<NativeReference*>(result));
294 sptr<JsDisplayListener> displayListener = new(std::nothrow) JsDisplayListener(env);
295 DMError ret = DMError::DM_OK;
296 if (displayListener == nullptr) {
297 WLOGFE("displayListener is nullptr");
298 return DMError::DM_ERROR_INVALID_PARAM;
299 }
300 if (type == EVENT_AVAILABLE_AREA_CHANGED) {
301 auto displayId = display_->GetId();
302 ret = SingletonContainer::Get<DisplayManager>().RegisterAvailableAreaListener(displayListener, displayId);
303 } else {
304 WLOGFE("RegisterDisplayListenerWithType failed, %{public}s not support", type.c_str());
305 return DMError::DM_ERROR_INVALID_PARAM;
306 }
307 if (ret != DMError::DM_OK) {
308 WLOGFE("RegisterDisplayListenerWithType failed, ret: %{public}u", ret);
309 return ret;
310 }
311 displayListener->AddCallback(type, value);
312 jsCbMap_[type][std::move(callbackRef)] = displayListener;
313 return DMError::DM_OK;
314 }
315
OnUnregisterDisplayManagerCallback(napi_env env,napi_callback_info info)316 napi_value JsDisplay::OnUnregisterDisplayManagerCallback(napi_env env, napi_callback_info info)
317 {
318 WLOGI("OnUnregisterDisplayCallback is called");
319 size_t argc = 4;
320 napi_value argv[4] = {nullptr};
321 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
322 if (argc < ARGC_ONE) {
323 WLOGFE("JsDisplayManager Params not match %{public}zu", argc);
324 std::string errMsg = "Invalid args count, need one arg at least!";
325 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
326 return NapiGetUndefined(env);
327 }
328 std::string cbType;
329 if (!ConvertFromJsValue(env, argv[0], cbType)) {
330 WLOGFE("Failed to convert parameter to callbackType");
331 std::string errMsg = "Failed to convert parameter to string";
332 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
333 return NapiGetUndefined(env);
334 }
335 std::lock_guard<std::mutex> lock(mtx_);
336 DmErrorCode ret;
337 if (argc == ARGC_ONE) {
338 ret = DM_JS_TO_ERROR_CODE_MAP.at(UnregisterAllDisplayListenerWithType(cbType));
339 } else {
340 napi_value value = argv[INDEX_ONE];
341 if ((value == nullptr) || (!NapiIsCallable(env, value))) {
342 ret = DM_JS_TO_ERROR_CODE_MAP.at(UnregisterAllDisplayListenerWithType(cbType));
343 } else {
344 ret = DM_JS_TO_ERROR_CODE_MAP.at(UnRegisterDisplayListenerWithType(env, cbType, value));
345 }
346 }
347 if (ret != DmErrorCode::DM_OK) {
348 WLOGFW("failed to unregister display listener with type");
349 std::string errMsg = "failed to unregister display listener with type";
350 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM), errMsg));
351 return NapiGetUndefined(env);
352 }
353 return NapiGetUndefined(env);
354 }
355
UnregisterAllDisplayListenerWithType(const std::string & type)356 DMError JsDisplay::UnregisterAllDisplayListenerWithType(const std::string& type)
357 {
358 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
359 WLOGI("UnregisterAllDisplayListenerWithType methodName %{public}s not registered!",
360 type.c_str());
361 return DMError::DM_OK;
362 }
363 DMError ret = DMError::DM_OK;
364 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
365 it->second->RemoveAllCallback();
366 if (type == EVENT_AVAILABLE_AREA_CHANGED) {
367 auto displayId = display_->GetId();
368 sptr<DisplayManager::IAvailableAreaListener> thisListener(it->second);
369 ret = SingletonContainer::Get<DisplayManager>().UnregisterAvailableAreaListener(thisListener, displayId);
370 } else {
371 ret = DMError::DM_ERROR_INVALID_PARAM;
372 }
373 jsCbMap_[type].erase(it++);
374 WLOGFI("unregister display listener with type %{public}s ret: %{public}u", type.c_str(), ret);
375 }
376 jsCbMap_.erase(type);
377 return ret;
378 }
379
UnRegisterDisplayListenerWithType(napi_env env,const std::string & type,napi_value value)380 DMError JsDisplay::UnRegisterDisplayListenerWithType(napi_env env, const std::string& type, napi_value value)
381 {
382 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
383 WLOGI("UnRegisterDisplayListenerWithType methodName %{public}s not registered!", type.c_str());
384 return DMError::DM_OK;
385 }
386 DMError ret = DMError::DM_OK;
387 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
388 bool isEquals = false;
389 napi_strict_equals(env, value, it->first->GetNapiValue(), &isEquals);
390 if (isEquals) {
391 it->second->RemoveCallback(env, type, value);
392 if (type == EVENT_AVAILABLE_AREA_CHANGED) {
393 auto displayId = display_->GetId();
394 sptr<DisplayManager::IAvailableAreaListener> thisListener(it->second);
395 ret = SingletonContainer::Get<DisplayManager>().UnregisterAvailableAreaListener(thisListener,
396 displayId);
397 } else {
398 ret = DMError::DM_ERROR_INVALID_PARAM;
399 }
400 jsCbMap_[type].erase(it++);
401 WLOGFI("unregister display listener with type %{public}s ret: %{public}u", type.c_str(), ret);
402 break;
403 } else {
404 it++;
405 }
406 }
407 if (jsCbMap_[type].empty()) {
408 jsCbMap_.erase(type);
409 }
410 return ret;
411 }
412
HasImmersiveWindow(napi_env env,napi_callback_info info)413 napi_value JsDisplay::HasImmersiveWindow(napi_env env, napi_callback_info info)
414 {
415 WLOGI("HasImmersiveWindow is called");
416 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
417 return (me != nullptr) ? me->OnHasImmersiveWindow(env, info) : nullptr;
418 }
419
GetType(napi_env env,napi_value value)420 napi_valuetype GetType(napi_env env, napi_value value)
421 {
422 napi_valuetype res = napi_undefined;
423 napi_typeof(env, value, &res);
424 return res;
425 }
426
OnGetCutoutInfo(napi_env env,napi_callback_info info)427 napi_value JsDisplay::OnGetCutoutInfo(napi_env env, napi_callback_info info)
428 {
429 WLOGD("OnGetCutoutInfo is called");
430 napi_value result = nullptr;
431 size_t argc = 4;
432 napi_value argv[4] = {nullptr};
433 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
434 napi_value lastParam = nullptr;
435 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr && GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
436 lastParam = argv[ARGC_ONE - 1];
437 }
438 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
439 auto asyncTask = [this, env, task = napiAsyncTask.get()]() {
440 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplay::OnGetCutoutInfo");
441 sptr<CutoutInfo> cutoutInfo = display_->GetCutoutInfo();
442 if (cutoutInfo != nullptr) {
443 task->Resolve(env, CreateJsCutoutInfoObject(env, cutoutInfo));
444 WLOGD("JsDisplay::OnGetCutoutInfo success");
445 } else {
446 task->Reject(env, CreateJsError(env,
447 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "JsDisplay::OnGetCutoutInfo failed."));
448 }
449 delete task;
450 };
451 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
452 napiAsyncTask->Reject(env, CreateJsError(env,
453 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
454 } else {
455 napiAsyncTask.release();
456 }
457 return result;
458 }
459
CreateEmptyAsyncTask(napi_env env,napi_value lastParam,napi_value * result)460 std::unique_ptr<NapiAsyncTask> JsDisplay::CreateEmptyAsyncTask(napi_env env, napi_value lastParam, napi_value* result)
461 {
462 napi_valuetype type = napi_undefined;
463 napi_typeof(env, lastParam, &type);
464 if (lastParam == nullptr || type != napi_function) {
465 napi_deferred nativeDeferred = nullptr;
466 napi_create_promise(env, &nativeDeferred, result);
467 return std::make_unique<NapiAsyncTask>(nativeDeferred, std::unique_ptr<NapiAsyncTask::ExecuteCallback>(),
468 std::unique_ptr<NapiAsyncTask::CompleteCallback>());
469 } else {
470 napi_get_undefined(env, result);
471 napi_ref callbackRef = nullptr;
472 napi_create_reference(env, lastParam, 1, &callbackRef);
473 return std::make_unique<NapiAsyncTask>(callbackRef, std::unique_ptr<NapiAsyncTask::ExecuteCallback>(),
474 std::unique_ptr<NapiAsyncTask::CompleteCallback>());
475 }
476 }
477
OnGetAvailableArea(napi_env env,napi_callback_info info)478 napi_value JsDisplay::OnGetAvailableArea(napi_env env, napi_callback_info info)
479 {
480 WLOGI("OnGetAvailableArea is called");
481 size_t argc = 4;
482 napi_value argv[4] = {nullptr};
483 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
484 napi_value lastParam = nullptr;
485 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
486 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
487 lastParam = argv[ARGC_ONE - 1];
488 }
489 napi_value result = nullptr;
490 std::unique_ptr<NapiAsyncTask> napiAsyncTask = JsDisplay::CreateEmptyAsyncTask(env, lastParam, &result);
491 auto asyncTask = [this, env, task = napiAsyncTask.get()]() {
492 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplay::OnGetAvailableArea");
493 DMRect area;
494 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(display_->GetAvailableArea(area));
495 if (ret == DmErrorCode::DM_OK) {
496 task->Resolve(env, CreateJsRectObject(env, area));
497 WLOGI("JsDisplay::OnGetAvailableArea success");
498 } else {
499 task->Reject(env, CreateJsError(env, static_cast<int32_t>(ret),
500 "JsDisplay::OnGetAvailableArea failed."));
501 }
502 delete task;
503 };
504 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
505 napiAsyncTask->Reject(env, CreateJsError(env,
506 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
507 } else {
508 napiAsyncTask.release();
509 }
510 return result;
511 }
512
OnGetDisplayCapability(napi_env env,napi_callback_info info)513 napi_value JsDisplay::OnGetDisplayCapability(napi_env env, napi_callback_info info)
514 {
515 WLOGI("OnGetDisplayCapability is called");
516 size_t argc = 4;
517 napi_value argv[4] = {nullptr};
518 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
519 std::string capabilitInfo;
520 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(display_->GetDisplayCapability(capabilitInfo));
521 if (ret == DmErrorCode::DM_OK) {
522 WLOGI("JsDisplay::OnGetDisplayCapability success, displayCapability = %{public}s", capabilitInfo.c_str());
523 } else {
524 napi_throw(env, CreateJsError(env, static_cast<int32_t>(ret)));
525 WLOGE("JsDisplay::OnGetDisplayCapability failed.");
526 }
527 return CreateJsValue(env, capabilitInfo);
528 }
529
OnHasImmersiveWindow(napi_env env,napi_callback_info info)530 napi_value JsDisplay::OnHasImmersiveWindow(napi_env env, napi_callback_info info)
531 {
532 WLOGI("OnHasImmersiveWindow is called");
533 size_t argc = 4;
534 napi_value argv[4] = {nullptr};
535 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
536 napi_value lastParam = nullptr;
537 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
538 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
539 lastParam = argv[ARGC_ONE - 1];
540 }
541 napi_value result = nullptr;
542 std::unique_ptr<NapiAsyncTask> napiAsyncTask = JsDisplay::CreateEmptyAsyncTask(env, lastParam, &result);
543 auto asyncTask = [this, env, task = napiAsyncTask.get()]() {
544 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplay::OnHasImmersiveWindow");
545 bool immersive = false;
546 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(display_->HasImmersiveWindow(immersive));
547 if (ret == DmErrorCode::DM_OK) {
548 task->Resolve(env, CreateJsValue(env, immersive));
549 WLOGI("JsDisplay::OnHasImmersiveWindow success - immersive window exists: %{public}d", immersive);
550 } else {
551 task->Reject(env, CreateJsError(env,
552 static_cast<int32_t>(ret), "JsDisplay::OnHasImmersiveWindow failed."));
553 }
554 delete task;
555 };
556 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
557 napiAsyncTask->Reject(env, CreateJsError(env,
558 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
559 } else {
560 napiAsyncTask.release();
561 }
562 return result;
563 }
564
GetSupportedColorSpaces(napi_env env,napi_callback_info info)565 napi_value JsDisplay::GetSupportedColorSpaces(napi_env env, napi_callback_info info)
566 {
567 WLOGI("GetSupportedColorSpaces is called");
568 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
569 return (me != nullptr) ? me->OnGetSupportedColorSpaces(env, info) : nullptr;
570 }
571
CreateJsColorSpaceArray(napi_env env,const std::vector<uint32_t> & colorSpaces)572 static napi_value CreateJsColorSpaceArray(napi_env env, const std::vector<uint32_t>& colorSpaces)
573 {
574 WLOGD("JsDisplay::CreateJsColorSpaceArray is called");
575 std::set<uint32_t> nativeColorSpaces;
576 for (const auto colorSpace : colorSpaces) {
577 GraphicCM_ColorSpaceType colorSpaceValue = static_cast<GraphicCM_ColorSpaceType>(colorSpace);
578 if (NATIVE_TO_JS_COLOR_SPACE_TYPE_MAP.count(colorSpaceValue) == 0) {
579 WLOGFE("Get color space name %{public}u, but not in api type", colorSpace);
580 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DMError::DM_ERROR_DEVICE_NOT_SUPPORT)));
581 return NapiGetUndefined(env);
582 }
583 nativeColorSpaces.insert(static_cast<uint32_t>(NATIVE_TO_JS_COLOR_SPACE_TYPE_MAP.at(colorSpaceValue)));
584 }
585 napi_value arrayValue = nullptr;
586 napi_create_array_with_length(env, nativeColorSpaces.size(), &arrayValue);
587 if (arrayValue == nullptr) {
588 WLOGFE("Failed to create color space array");
589 return NapiGetUndefined(env);
590 }
591 uint32_t index = 0;
592 for (const auto nativeColorSpace : nativeColorSpaces) {
593 napi_set_element(env, arrayValue, index++, CreateJsValue(env, nativeColorSpace));
594 }
595 return arrayValue;
596 }
597
OnGetSupportedColorSpaces(napi_env env,napi_callback_info info)598 napi_value JsDisplay::OnGetSupportedColorSpaces(napi_env env, napi_callback_info info)
599 {
600 WLOGI("OnGetSupportedColorSpaces is called");
601 size_t argc = 4;
602 napi_value argv[4] = {nullptr};
603 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
604 napi_value lastParam = nullptr;
605 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
606 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
607 lastParam = argv[ARGC_ONE - 1];
608 }
609 napi_value result = nullptr;
610 std::unique_ptr<NapiAsyncTask> napiAsyncTask = JsDisplay::CreateEmptyAsyncTask(env, lastParam, &result);
611 auto asyncTask = [this, env, task = napiAsyncTask.get()]() {
612 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplay::OnGetSupportedColorSpaces");
613 std::vector<uint32_t> colorSpaces;
614 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(display_->GetSupportedColorSpaces(colorSpaces));
615 if (ret == DmErrorCode::DM_OK) {
616 task->Resolve(env, CreateJsColorSpaceArray(env, colorSpaces));
617 WLOGI("OnGetSupportedColorSpaces success");
618 } else {
619 task->Reject(env, CreateJsError(env, static_cast<int32_t>(ret),
620 "JsDisplay::OnGetSupportedColorSpaces failed."));
621 WLOGFE("OnGetSupportedColorSpaces failed");
622 }
623 delete task;
624 };
625 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
626 napiAsyncTask->Reject(env, CreateJsError(env,
627 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
628 } else {
629 napiAsyncTask.release();
630 }
631 return result;
632 }
633
GetSupportedHDRFormats(napi_env env,napi_callback_info info)634 napi_value JsDisplay::GetSupportedHDRFormats(napi_env env, napi_callback_info info)
635 {
636 WLOGI("GetSupportedHDRFormats is called");
637 JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(env, info);
638 return (me != nullptr) ? me->OnGetSupportedHDRFormats(env, info) : nullptr;
639 }
640
CreateJsHDRFormatArray(napi_env env,const std::vector<uint32_t> & hdrFormats)641 static napi_value CreateJsHDRFormatArray(napi_env env, const std::vector<uint32_t>& hdrFormats)
642 {
643 WLOGD("JsDisplay::CreateJsHDRFormatArray is called");
644 std::set<uint32_t> nativeHDRFormats;
645 for (const auto hdrFormat : hdrFormats) {
646 ScreenHDRFormat hdrFormatValue = static_cast<ScreenHDRFormat>(hdrFormat);
647 if (NATIVE_TO_JS_HDR_FORMAT_TYPE_MAP.count(hdrFormatValue) == 0) {
648 WLOGFE("Get HDR format name %{public}u, but not in api type", hdrFormat);
649 napi_throw(env, CreateJsError(env, static_cast<int32_t>(DMError::DM_ERROR_DEVICE_NOT_SUPPORT)));
650 return NapiGetUndefined(env);
651 }
652 nativeHDRFormats.insert(static_cast<uint32_t>(NATIVE_TO_JS_HDR_FORMAT_TYPE_MAP.at(hdrFormatValue)));
653 }
654 napi_value arrayValue = nullptr;
655 napi_create_array_with_length(env, hdrFormats.size(), &arrayValue);
656 if (arrayValue == nullptr) {
657 WLOGFE("Failed to create HDR format array");
658 return NapiGetUndefined(env);
659 }
660 uint32_t index = 0;
661 for (const auto nativeHDRFormat : nativeHDRFormats) {
662 napi_set_element(env, arrayValue, index++, CreateJsValue(env, nativeHDRFormat));
663 }
664 return arrayValue;
665 }
666
OnGetSupportedHDRFormats(napi_env env,napi_callback_info info)667 napi_value JsDisplay::OnGetSupportedHDRFormats(napi_env env, napi_callback_info info)
668 {
669 WLOGI("OnGetSupportedHDRFormats is called");
670 size_t argc = 4;
671 napi_value argv[4] = {nullptr};
672 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
673 napi_value lastParam = nullptr;
674 if (argc >= ARGC_ONE && argv[ARGC_ONE - 1] != nullptr &&
675 GetType(env, argv[ARGC_ONE - 1]) == napi_function) {
676 lastParam = argv[ARGC_ONE - 1];
677 }
678 napi_value result = nullptr;
679 std::unique_ptr<NapiAsyncTask> napiAsyncTask = JsDisplay::CreateEmptyAsyncTask(env, lastParam, &result);
680 auto asyncTask = [this, env, task = napiAsyncTask.get()]() {
681 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsDisplay::OnGetSupportedHDRFormats");
682 std::vector<uint32_t> hdrFormats;
683 DmErrorCode ret = DM_JS_TO_ERROR_CODE_MAP.at(display_->GetSupportedHDRFormats(hdrFormats));
684 if (ret == DmErrorCode::DM_OK) {
685 task->Resolve(env, CreateJsHDRFormatArray(env, hdrFormats));
686 WLOGI("OnGetSupportedHDRFormats success");
687 } else {
688 task->Reject(env, CreateJsError(env, static_cast<int32_t>(ret),
689 "JsDisplay::OnGetSupportedHDRFormats failed."));
690 WLOGFE("OnGetSupportedHDRFormats failed");
691 }
692 delete task;
693 };
694 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) {
695 napiAsyncTask->Reject(env, CreateJsError(env,
696 static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "Send event failed!"));
697 } else {
698 napiAsyncTask.release();
699 }
700 return result;
701 }
702
FindJsDisplayObject(DisplayId displayId)703 std::shared_ptr<NativeReference> FindJsDisplayObject(DisplayId displayId)
704 {
705 WLOGD("[NAPI]Try to find display %{public}" PRIu64" in g_JsDisplayMap", displayId);
706 std::lock_guard<std::recursive_mutex> lock(g_mutex);
707 if (g_JsDisplayMap.find(displayId) == g_JsDisplayMap.end()) {
708 WLOGD("[NAPI]Can not find display %{public}" PRIu64" in g_JsDisplayMap", displayId);
709 return nullptr;
710 }
711 return g_JsDisplayMap[displayId];
712 }
713
NapiGetUndefined(napi_env env)714 napi_value NapiGetUndefined(napi_env env)
715 {
716 napi_value result = nullptr;
717 napi_get_undefined(env, &result);
718 return result;
719 }
720
CreateJsCutoutInfoObject(napi_env env,sptr<CutoutInfo> cutoutInfo)721 napi_value CreateJsCutoutInfoObject(napi_env env, sptr<CutoutInfo> cutoutInfo)
722 {
723 WLOGD("JsDisplay::CreateJsCutoutInfoObject is called");
724 napi_value objValue = nullptr;
725 napi_create_object(env, &objValue);
726 if (objValue == nullptr) {
727 WLOGFE("Failed to convert prop to jsObject");
728 return NapiGetUndefined(env);
729 }
730 if (cutoutInfo == nullptr) {
731 WLOGFE("Get null cutout info");
732 return NapiGetUndefined(env);
733 }
734 std::vector<DMRect> boundingRects = cutoutInfo->GetBoundingRects();
735 WaterfallDisplayAreaRects waterfallDisplayAreaRects = cutoutInfo->GetWaterfallDisplayAreaRects();
736 napi_set_named_property(env, objValue, "boundingRects", CreateJsBoundingRectsArrayObject(env, boundingRects));
737 napi_set_named_property(env, objValue, "waterfallDisplayAreaRects",
738 CreateJsWaterfallDisplayAreaRectsObject(env, waterfallDisplayAreaRects));
739 return objValue;
740 }
741
CreateJsDisplayPhysicalInfoObject(napi_env env,DisplayPhysicalResolution physicalInfo)742 napi_value CreateJsDisplayPhysicalInfoObject(napi_env env, DisplayPhysicalResolution physicalInfo)
743 {
744 napi_value objValue = nullptr;
745 napi_create_object(env, &objValue);
746 napi_set_named_property(env, objValue, "foldDisplayMode", CreateJsValue(env, physicalInfo.foldDisplayMode_));
747 napi_set_named_property(env, objValue, "physicalWidth", CreateJsValue(env, physicalInfo.physicalWidth_));
748 napi_set_named_property(env, objValue, "physicalHeight", CreateJsValue(env, physicalInfo.physicalHeight_));
749 return objValue;
750 }
751
CreateJsRectObject(napi_env env,DMRect rect)752 napi_value CreateJsRectObject(napi_env env, DMRect rect)
753 {
754 napi_value objValue = nullptr;
755 napi_create_object(env, &objValue);
756 napi_set_named_property(env, objValue, "left", CreateJsValue(env, rect.posX_));
757 napi_set_named_property(env, objValue, "top", CreateJsValue(env, rect.posY_));
758 napi_set_named_property(env, objValue, "width", CreateJsValue(env, rect.width_));
759 napi_set_named_property(env, objValue, "height", CreateJsValue(env, rect.height_));
760 return objValue;
761 }
762
CreateJsWaterfallDisplayAreaRectsObject(napi_env env,WaterfallDisplayAreaRects waterfallDisplayAreaRects)763 napi_value CreateJsWaterfallDisplayAreaRectsObject(napi_env env,
764 WaterfallDisplayAreaRects waterfallDisplayAreaRects)
765 {
766 napi_value objValue = nullptr;
767 napi_create_object(env, &objValue);
768 napi_set_named_property(env, objValue, "left", CreateJsRectObject(env, waterfallDisplayAreaRects.left));
769 napi_set_named_property(env, objValue, "top", CreateJsRectObject(env, waterfallDisplayAreaRects.top));
770 napi_set_named_property(env, objValue, "right", CreateJsRectObject(env, waterfallDisplayAreaRects.right));
771 napi_set_named_property(env, objValue, "bottom", CreateJsRectObject(env, waterfallDisplayAreaRects.bottom));
772 return objValue;
773 }
774
CreateJsBoundingRectsArrayObject(napi_env env,std::vector<DMRect> boundingRects)775 napi_value CreateJsBoundingRectsArrayObject(napi_env env, std::vector<DMRect> boundingRects)
776 {
777 napi_value arrayValue = nullptr;
778 napi_create_array_with_length(env, boundingRects.size(), &arrayValue);
779 size_t i = 0;
780 for (const auto& rect : boundingRects) {
781 napi_set_element(env, arrayValue, i++, CreateJsRectObject(env, rect));
782 }
783 return arrayValue;
784 }
785
NapiSetNamedProperty(napi_env env,napi_value objValue,sptr<DisplayInfo> info)786 void NapiSetNamedProperty(napi_env env, napi_value objValue, sptr<DisplayInfo> info)
787 {
788 napi_set_named_property(env, objValue, "id", CreateJsValue(env, static_cast<uint32_t>(info->GetDisplayId())));
789 napi_set_named_property(env, objValue, "name", CreateJsValue(env, info->GetName()));
790 napi_set_named_property(env, objValue, "alive", CreateJsValue(env, info->GetAliveStatus()));
791 if (NATIVE_TO_JS_DISPLAY_STATE_MAP.count(info->GetDisplayState()) != 0) {
792 napi_set_named_property(env, objValue, "state",
793 CreateJsValue(env, NATIVE_TO_JS_DISPLAY_STATE_MAP.at(info->GetDisplayState())));
794 } else {
795 napi_set_named_property(env, objValue, "state", CreateJsValue(env, DisplayStateMode::STATE_UNKNOWN));
796 }
797 napi_set_named_property(env, objValue, "refreshRate", CreateJsValue(env, info->GetRefreshRate()));
798 napi_set_named_property(env, objValue, "rotation", CreateJsValue(env, info->GetRotation()));
799 napi_set_named_property(env, objValue, "width", CreateJsValue(env, info->GetWidth()));
800 napi_set_named_property(env, objValue, "height", CreateJsValue(env, info->GetHeight()));
801 napi_set_named_property(env, objValue, "densityDPI",
802 CreateJsValue(env, info->GetVirtualPixelRatio() * DOT_PER_INCH));
803 napi_set_named_property(env, objValue, "orientation", CreateJsValue(env, info->GetDisplayOrientation()));
804 napi_set_named_property(env, objValue, "densityPixels", CreateJsValue(env, info->GetVirtualPixelRatio()));
805 napi_set_named_property(env, objValue, "scaledDensity", CreateJsValue(env, info->GetVirtualPixelRatio()));
806 napi_set_named_property(env, objValue, "xDPI", CreateJsValue(env, info->GetXDpi()));
807 napi_set_named_property(env, objValue, "yDPI", CreateJsValue(env, info->GetYDpi()));
808 napi_set_named_property(env, objValue, "colorSpaces", CreateJsColorSpaceArray(env, info->GetColorSpaces()));
809 napi_set_named_property(env, objValue, "hdrFormats", CreateJsHDRFormatArray(env, info->GetHdrFormats()));
810 napi_set_named_property(env, objValue, "availableWidth", CreateJsValue(env, info->GetAvailableWidth()));
811 napi_set_named_property(env, objValue, "availableHeight", CreateJsValue(env, info->GetAvailableHeight()));
812 napi_set_named_property(env, objValue, "screenShape", CreateJsValue(env, info->GetScreenShape()));
813 if (info->GetDisplaySourceMode() == DisplaySourceMode::MAIN ||
814 info->GetDisplaySourceMode() == DisplaySourceMode::EXTEND) {
815 napi_set_named_property(env, objValue, "x", CreateJsValue(env, info->GetX()));
816 napi_set_named_property(env, objValue, "y", CreateJsValue(env, info->GetY()));
817 } else {
818 napi_set_named_property(env, objValue, "x", NapiGetUndefined(env));
819 napi_set_named_property(env, objValue, "y", NapiGetUndefined(env));
820 }
821 napi_set_named_property(env, objValue, "sourceMode", CreateJsValue(env, info->GetDisplaySourceMode()));
822 }
823
CreateJsDisplayObject(napi_env env,sptr<Display> & display)824 napi_value CreateJsDisplayObject(napi_env env, sptr<Display>& display)
825 {
826 WLOGD("CreateJsDisplay is called");
827 napi_value objValue = nullptr;
828 std::shared_ptr<NativeReference> jsDisplayObj = FindJsDisplayObject(display->GetId());
829 if (jsDisplayObj != nullptr && jsDisplayObj->GetNapiValue() != nullptr) {
830 WLOGD("[NAPI]FindJsDisplayObject %{public}" PRIu64"", display->GetId());
831 objValue = jsDisplayObj->GetNapiValue();
832 }
833 if (objValue == nullptr) {
834 napi_create_object(env, &objValue);
835 }
836 if (objValue == nullptr) {
837 WLOGFE("Failed to get jsObject");
838 return NapiGetUndefined(env);
839 }
840 auto info = display->GetDisplayInfoWithCache();
841 if (info == nullptr) {
842 WLOGFE("Failed to GetDisplayInfo");
843 return NapiGetUndefined(env);
844 }
845
846 NapiSetNamedProperty(env, objValue, info);
847
848 if (jsDisplayObj == nullptr || jsDisplayObj->GetNapiValue() == nullptr) {
849 std::unique_ptr<JsDisplay> jsDisplay = std::make_unique<JsDisplay>(display);
850 napi_wrap(env, objValue, jsDisplay.release(), JsDisplay::Finalizer, nullptr, nullptr);
851 BindNativeFunction(env, objValue, "getCutoutInfo", "JsDisplay", JsDisplay::GetCutoutInfo);
852 BindNativeFunction(env, objValue, "hasImmersiveWindow", "JsDisplay", JsDisplay::HasImmersiveWindow);
853 BindNativeFunction(env, objValue, "getSupportedColorSpaces", "JsDisplay", JsDisplay::GetSupportedColorSpaces);
854 BindNativeFunction(env, objValue, "getSupportedHDRFormats", "JsDisplay", JsDisplay::GetSupportedHDRFormats);
855 BindNativeFunction(env, objValue, "getAvailableArea", "JsDisplay", JsDisplay::GetAvailableArea);
856 BindNativeFunction(env, objValue, "on", "JsDisplay", JsDisplay::RegisterDisplayManagerCallback);
857 BindNativeFunction(env, objValue, "off", "JsDisplay", JsDisplay::UnregisterDisplayManagerCallback);
858 BindNativeFunction(env, objValue, "getDisplayCapability", "JsDisplay", JsDisplay::GetDisplayCapability);
859 std::shared_ptr<NativeReference> jsDisplayRef;
860 napi_ref result = nullptr;
861 napi_create_reference(env, objValue, 1, &result);
862 jsDisplayRef.reset(reinterpret_cast<NativeReference*>(result));
863 DisplayId displayId = display->GetId();
864 std::lock_guard<std::recursive_mutex> lock(g_mutex);
865 g_JsDisplayMap[displayId] = jsDisplayRef;
866 }
867 return objValue;
868 }
869 } // namespace Rosen
870 } // namespace OHOS
871