• 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 <map>
20 
21 #include "cutout_info.h"
22 #include "display.h"
23 #include "display_info.h"
24 #include "window_manager_hilog.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 using namespace AbilityRuntime;
29 constexpr size_t ARGC_ONE = 1;
30 namespace {
31     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsDisplay"};
32     const std::map<DisplayState,      DisplayStateMode> NATIVE_TO_JS_DISPLAY_STATE_MAP {
33         { DisplayState::UNKNOWN,      DisplayStateMode::STATE_UNKNOWN      },
34         { DisplayState::OFF,          DisplayStateMode::STATE_OFF          },
35         { DisplayState::ON,           DisplayStateMode::STATE_ON           },
36         { DisplayState::DOZE,         DisplayStateMode::STATE_DOZE         },
37         { DisplayState::DOZE_SUSPEND, DisplayStateMode::STATE_DOZE_SUSPEND },
38         { DisplayState::VR,           DisplayStateMode::STATE_VR           },
39         { DisplayState::ON_SUSPEND,   DisplayStateMode::STATE_ON_SUSPEND   },
40     };
41 }
42 
43 static thread_local std::map<DisplayId, std::shared_ptr<NativeReference>> g_JsDisplayMap;
44 std::recursive_mutex g_mutex;
45 
JsDisplay(const sptr<Display> & display)46 JsDisplay::JsDisplay(const sptr<Display>& display) : display_(display)
47 {
48 }
49 
~JsDisplay()50 JsDisplay::~JsDisplay()
51 {
52     WLOGI("JsDisplay::~JsDisplay is called");
53 }
54 
Finalizer(NativeEngine * engine,void * data,void * hint)55 void JsDisplay::Finalizer(NativeEngine* engine, void* data, void* hint)
56 {
57     WLOGI("JsDisplay::Finalizer is called");
58     auto jsDisplay = std::unique_ptr<JsDisplay>(static_cast<JsDisplay*>(data));
59     if (jsDisplay == nullptr) {
60         WLOGFE("JsDisplay::Finalizer jsDisplay is null");
61         return;
62     }
63     sptr<Display> display = jsDisplay->display_;
64     if (display == nullptr) {
65         WLOGFE("JsDisplay::Finalizer display is null");
66         return;
67     }
68     DisplayId displayId = display->GetId();
69     WLOGI("JsDisplay::Finalizer displayId : %{public}" PRIu64"", displayId);
70     std::lock_guard<std::recursive_mutex> lock(g_mutex);
71     if (g_JsDisplayMap.find(displayId) != g_JsDisplayMap.end()) {
72         WLOGI("JsDisplay::Finalizer Display is destroyed: %{public}" PRIu64"", displayId);
73         g_JsDisplayMap.erase(displayId);
74     }
75 }
76 
GetCutoutInfo(NativeEngine * engine,NativeCallbackInfo * info)77 NativeValue* JsDisplay::GetCutoutInfo(NativeEngine* engine, NativeCallbackInfo* info)
78 {
79     WLOGI("GetCutoutInfo is called");
80     JsDisplay* me = CheckParamsAndGetThis<JsDisplay>(engine, info);
81     return (me != nullptr) ? me->OnGetCutoutInfo(*engine, *info) : nullptr;
82 }
83 
OnGetCutoutInfo(NativeEngine & engine,NativeCallbackInfo & info)84 NativeValue* JsDisplay::OnGetCutoutInfo(NativeEngine& engine, NativeCallbackInfo& info)
85 {
86     WLOGI("OnGetCutoutInfo is called");
87     AsyncTask::CompleteCallback complete =
88         [this](NativeEngine& engine, AsyncTask& task, int32_t status) {
89             sptr<CutoutInfo> cutoutInfo = display_->GetCutoutInfo();
90             if (cutoutInfo != nullptr) {
91                 task.Resolve(engine, CreateJsCutoutInfoObject(engine, cutoutInfo));
92                 WLOGI("JsDisplay::OnGetCutoutInfo success");
93             } else {
94                 task.Reject(engine, CreateJsError(engine,
95                     static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_SCREEN), "JsDisplay::OnGetCutoutInfo failed."));
96             }
97         };
98     NativeValue* lastParam = nullptr;
99     if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr &&
100         info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) {
101         lastParam = info.argv[ARGC_ONE - 1];
102     }
103     NativeValue* result = nullptr;
104     AsyncTask::Schedule("JsDisplay::OnGetCutoutInfo",
105         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
106     return result;
107 }
108 
FindJsDisplayObject(DisplayId displayId)109 std::shared_ptr<NativeReference> FindJsDisplayObject(DisplayId displayId)
110 {
111     WLOGI("[NAPI]Try to find display %{public}" PRIu64" in g_JsDisplayMap", displayId);
112     std::lock_guard<std::recursive_mutex> lock(g_mutex);
113     if (g_JsDisplayMap.find(displayId) == g_JsDisplayMap.end()) {
114         WLOGI("[NAPI]Can not find display %{public}" PRIu64" in g_JsDisplayMap", displayId);
115         return nullptr;
116     }
117     return g_JsDisplayMap[displayId];
118 }
119 
CreateJsCutoutInfoObject(NativeEngine & engine,sptr<CutoutInfo> cutoutInfo)120 NativeValue* CreateJsCutoutInfoObject(NativeEngine& engine, sptr<CutoutInfo> cutoutInfo)
121 {
122     WLOGI("JsDisplay::CreateJsCutoutInfoObject is called");
123     NativeValue* objValue = engine.CreateObject();
124     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
125     if (object == nullptr) {
126         WLOGFE("Failed to convert prop to jsObject");
127         return engine.CreateUndefined();
128     }
129     if (cutoutInfo == nullptr) {
130         WLOGFE("Get null cutout info");
131         return engine.CreateUndefined();
132     }
133     std::vector<DMRect> boundingRects = cutoutInfo->GetBoundingRects();
134     WaterfallDisplayAreaRects waterfallDisplayAreaRects = cutoutInfo->GetWaterfallDisplayAreaRects();
135     object->SetProperty("boundingRects", CreateJsBoundingRectsArrayObject(engine, boundingRects));
136     object->SetProperty("waterfallDisplayAreaRects",
137         CreateJsWaterfallDisplayAreaRectsObject(engine, waterfallDisplayAreaRects));
138     return objValue;
139 }
140 
CreateJsRectObject(NativeEngine & engine,DMRect rect)141 NativeValue* CreateJsRectObject(NativeEngine& engine, DMRect rect)
142 {
143     NativeValue* objValue = engine.CreateObject();
144     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
145     object->SetProperty("left", CreateJsValue(engine, rect.posX_));
146     object->SetProperty("top", CreateJsValue(engine, rect.posY_));
147     object->SetProperty("width", CreateJsValue(engine, rect.width_));
148     object->SetProperty("height", CreateJsValue(engine, rect.height_));
149     return objValue;
150 }
151 
CreateJsWaterfallDisplayAreaRectsObject(NativeEngine & engine,WaterfallDisplayAreaRects waterfallDisplayAreaRects)152 NativeValue* CreateJsWaterfallDisplayAreaRectsObject(NativeEngine& engine,
153     WaterfallDisplayAreaRects waterfallDisplayAreaRects)
154 {
155     NativeValue* objValue = engine.CreateObject();
156     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
157     object->SetProperty("left", CreateJsRectObject(engine, waterfallDisplayAreaRects.left));
158     object->SetProperty("top", CreateJsRectObject(engine, waterfallDisplayAreaRects.top));
159     object->SetProperty("right", CreateJsRectObject(engine, waterfallDisplayAreaRects.right));
160     object->SetProperty("bottom", CreateJsRectObject(engine, waterfallDisplayAreaRects.bottom));
161     return objValue;
162 }
163 
CreateJsBoundingRectsArrayObject(NativeEngine & engine,std::vector<DMRect> boundingRects)164 NativeValue* CreateJsBoundingRectsArrayObject(NativeEngine& engine, std::vector<DMRect> boundingRects)
165 {
166     NativeValue* arrayValue = engine.CreateArray(boundingRects.size());
167     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
168     size_t i = 0;
169     for (const auto& rect : boundingRects) {
170         array->SetElement(i++, CreateJsRectObject(engine, rect));
171     }
172     return arrayValue;
173 }
174 
CreateJsDisplayObject(NativeEngine & engine,sptr<Display> & display)175 NativeValue* CreateJsDisplayObject(NativeEngine& engine, sptr<Display>& display)
176 {
177     WLOGI("CreateJsDisplay is called");
178     NativeValue* objValue = nullptr;
179     std::shared_ptr<NativeReference> jsDisplayObj = FindJsDisplayObject(display->GetId());
180     if (jsDisplayObj != nullptr && jsDisplayObj->Get() != nullptr) {
181         WLOGI("[NAPI]FindJsDisplayObject %{public}" PRIu64"", display->GetId());
182         objValue = jsDisplayObj->Get();
183     }
184     if (objValue == nullptr) {
185         objValue = engine.CreateObject();
186     }
187     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
188     if (object == nullptr) {
189         WLOGFE("Failed to convert prop to jsObject");
190         return engine.CreateUndefined();
191     }
192     auto info = display->GetDisplayInfo();
193     if (info == nullptr) {
194         WLOGFE("Failed to GetDisplayInfo");
195         return engine.CreateUndefined();
196     }
197     object->SetProperty("id", CreateJsValue(engine, static_cast<uint32_t>(info->GetDisplayId())));
198     object->SetProperty("name", CreateJsValue(engine, info->GetName()));
199     object->SetProperty("alive", CreateJsValue(engine, info->GetAliveStatus()));
200     if (NATIVE_TO_JS_DISPLAY_STATE_MAP.count(info->GetDisplayState()) != 0) {
201         object->SetProperty("state", CreateJsValue(engine, NATIVE_TO_JS_DISPLAY_STATE_MAP.at(info->GetDisplayState())));
202     } else {
203         object->SetProperty("state", CreateJsValue(engine, DisplayStateMode::STATE_UNKNOWN));
204     }
205 
206     object->SetProperty("refreshRate", CreateJsValue(engine, info->GetRefreshRate()));
207     object->SetProperty("rotation", CreateJsValue(engine, info->GetRotation()));
208     object->SetProperty("width", CreateJsValue(engine, info->GetWidth()));
209     object->SetProperty("height", CreateJsValue(engine, info->GetHeight()));
210     object->SetProperty("densityDPI", CreateJsValue(engine, info->GetVirtualPixelRatio() * DOT_PER_INCH));
211     object->SetProperty("orientation", CreateJsValue(engine, info->GetDisplayOrientation()));
212     object->SetProperty("densityPixels", CreateJsValue(engine, info->GetVirtualPixelRatio()));
213     object->SetProperty("scaledDensity", CreateJsValue(engine, info->GetVirtualPixelRatio()));
214     object->SetProperty("xDPI", CreateJsValue(engine, info->GetXDpi()));
215     object->SetProperty("yDPI", CreateJsValue(engine, info->GetYDpi()));
216     if (jsDisplayObj == nullptr || jsDisplayObj->Get() == nullptr) {
217         std::unique_ptr<JsDisplay> jsDisplay = std::make_unique<JsDisplay>(display);
218         object->SetNativePointer(jsDisplay.release(), JsDisplay::Finalizer, nullptr);
219         BindNativeFunction(engine, *object, "getCutoutInfo", "JsDisplay", JsDisplay::GetCutoutInfo);
220         std::shared_ptr<NativeReference> jsDisplayRef;
221         jsDisplayRef.reset(engine.CreateReference(objValue, 1));
222         DisplayId displayId = display->GetId();
223         std::lock_guard<std::recursive_mutex> lock(g_mutex);
224         g_JsDisplayMap[displayId] = jsDisplayRef;
225     }
226     return objValue;
227 }
228 }  // namespace Rosen
229 }  // namespace OHOS
230