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