• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_screen.h"
17 
18 #include <cinttypes>
19 #include "screen.h"
20 #include "screen_info.h"
21 #include "window_manager_hilog.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 using namespace AbilityRuntime;
26 constexpr size_t ARGC_ONE = 1;
27 constexpr size_t ARGC_TWO = 2;
28 namespace {
29     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsScreen"};
30 }
31 
32 static thread_local std::map<ScreenId, std::shared_ptr<NativeReference>> g_JsScreenMap;
33 std::recursive_mutex g_mutex;
34 
JsScreen(const sptr<Screen> & screen)35 JsScreen::JsScreen(const sptr<Screen>& screen) : screen_(screen)
36 {
37 }
38 
~JsScreen()39 JsScreen::~JsScreen()
40 {
41     WLOGFI("JsScreen::~JsScreen is called");
42 }
43 
Finalizer(NativeEngine * engine,void * data,void * hint)44 void JsScreen::Finalizer(NativeEngine* engine, void* data, void* hint)
45 {
46     WLOGFI("JsScreen::Finalizer is called");
47     auto jsScreen = std::unique_ptr<JsScreen>(static_cast<JsScreen*>(data));
48     if (jsScreen == nullptr) {
49         WLOGFE("jsScreen::Finalizer jsScreen is null");
50         return;
51     }
52     sptr<Screen> screen = jsScreen->screen_;
53     if (screen == nullptr) {
54         WLOGFE("JsScreen::Finalizer screen is null");
55         return;
56     }
57     ScreenId screenId = screen->GetId();
58     WLOGFI("JsScreen::Finalizer screenId : %{public}" PRIu64"", screenId);
59     std::lock_guard<std::recursive_mutex> lock(g_mutex);
60     if (g_JsScreenMap.find(screenId) != g_JsScreenMap.end()) {
61         WLOGFI("JsScreen::Finalizer screen is destroyed: %{public}" PRIu64"", screenId);
62         g_JsScreenMap.erase(screenId);
63     }
64 }
65 
SetOrientation(NativeEngine * engine,NativeCallbackInfo * info)66 NativeValue* JsScreen::SetOrientation(NativeEngine* engine, NativeCallbackInfo* info)
67 {
68     JsScreen* me = CheckParamsAndGetThis<JsScreen>(engine, info);
69     return (me != nullptr) ? me->OnSetOrientation(*engine, *info) : nullptr;
70 }
71 
OnSetOrientation(NativeEngine & engine,NativeCallbackInfo & info)72 NativeValue* JsScreen::OnSetOrientation(NativeEngine& engine, NativeCallbackInfo& info)
73 {
74     WLOGFI("OnSetOrientation is called");
75     bool paramValidFlag = true;
76     Orientation orientation = Orientation::UNSPECIFIED;
77     if (info.argc < ARGC_ONE) {
78         WLOGFE("OnSetOrientation Params not match, info argc: %{public}zu", info.argc);
79         paramValidFlag = false;
80     } else {
81         if (!ConvertFromJsValue(engine, info.argv[0], orientation)) {
82             paramValidFlag = false;
83             WLOGFE("Failed to convert parameter to orientation");
84         }
85     }
86     if (!paramValidFlag) {
87         WLOGE("OnSetOrientation paramValidFlag error");
88         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
89         return engine.CreateUndefined();
90     }
91     if (orientation < Orientation::BEGIN || orientation > Orientation::END) {
92         WLOGE("Orientation param error! orientation value must from enum Orientation");
93         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
94         return engine.CreateUndefined();
95     }
96 
97     AsyncTask::CompleteCallback complete =
98         [=](NativeEngine& engine, AsyncTask& task, int32_t status) {
99             bool res = screen_->SetOrientation(orientation);
100             if (res) {
101                 task.Resolve(engine, engine.CreateUndefined());
102                 WLOGFI("OnSetOrientation success");
103             } else {
104                 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL),
105                                                   "JsScreen::OnSetOrientation failed."));
106                 WLOGFE("OnSetOrientation failed");
107             }
108         };
109     NativeValue* lastParam = nullptr;
110     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
111         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
112         lastParam = info.argv[ARGC_TWO - 1];
113     }
114     NativeValue* result = nullptr;
115     AsyncTask::Schedule("JsScreen::OnSetOrientation",
116         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
117     return result;
118 }
119 
120 
SetScreenActiveMode(NativeEngine * engine,NativeCallbackInfo * info)121 NativeValue* JsScreen::SetScreenActiveMode(NativeEngine* engine, NativeCallbackInfo* info)
122 {
123     WLOGFI("SetScreenActiveMode is called");
124     JsScreen* me = CheckParamsAndGetThis<JsScreen>(engine, info);
125     return (me != nullptr) ? me->OnSetScreenActiveMode(*engine, *info) : nullptr;
126 }
127 
OnSetScreenActiveMode(NativeEngine & engine,NativeCallbackInfo & info)128 NativeValue* JsScreen::OnSetScreenActiveMode(NativeEngine& engine, NativeCallbackInfo& info)
129 {
130     WLOGFI("OnSetScreenActiveMode is called");
131     bool paramValidFlag = true;
132     uint32_t modeId = 0;
133     if (info.argc < ARGC_ONE) {
134         WLOGFE("OnSetScreenActiveMode Params not match %{public}zu", info.argc);
135         paramValidFlag = false;
136     } else {
137         if (!ConvertFromJsValue(engine, info.argv[0], modeId)) {
138             WLOGFE("Failed to convert parameter to modeId");
139             paramValidFlag = false;
140         }
141     }
142     if (!paramValidFlag) {
143         WLOGFE("OnSetScreenActiveMode paramValidFlag error");
144         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
145         return engine.CreateUndefined();
146     }
147 
148     AsyncTask::CompleteCallback complete =
149         [=](NativeEngine& engine, AsyncTask& task, int32_t status) {
150             bool res = screen_->SetScreenActiveMode(modeId);
151             if (res) {
152                 task.Resolve(engine, engine.CreateUndefined());
153                 WLOGFI("OnSetScreenActiveMode success");
154             } else {
155                 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL),
156                                                 "JsScreen::OnSetScreenActiveMode failed."));
157                 WLOGFE("OnSetScreenActiveMode failed");
158             }
159         };
160     NativeValue* lastParam = nullptr;
161     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
162         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
163         lastParam = info.argv[ARGC_TWO - 1];
164     }
165     NativeValue* result = nullptr;
166     AsyncTask::Schedule("JsScreen::OnSetScreenActiveMode",
167         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
168     return result;
169 }
170 
SetDensityDpi(NativeEngine * engine,NativeCallbackInfo * info)171 NativeValue* JsScreen::SetDensityDpi(NativeEngine* engine, NativeCallbackInfo* info)
172 {
173     WLOGFI("SetDensityDpi is called");
174     JsScreen* me = CheckParamsAndGetThis<JsScreen>(engine, info);
175     return (me != nullptr) ? me->OnSetDensityDpi(*engine, *info) : nullptr;
176 }
177 
OnSetDensityDpi(NativeEngine & engine,NativeCallbackInfo & info)178 NativeValue* JsScreen::OnSetDensityDpi(NativeEngine& engine, NativeCallbackInfo& info)
179 {
180     WLOGFI("OnSetDensityDpi is called");
181     bool paramValidFlag = true;
182     uint32_t densityDpi = 0;
183     if (info.argc < ARGC_ONE) {
184         WLOGFE("OnSetDensityDpi Params not match %{public}zu", info.argc);
185         paramValidFlag = false;
186     } else {
187         if (!ConvertFromJsValue(engine, info.argv[0], densityDpi)) {
188             WLOGFE("Failed to convert parameter to densityDpi");
189             paramValidFlag = false;
190         }
191     }
192     if (!paramValidFlag) {
193         WLOGFE("OnSetDensityDpi paramValidFlag error");
194         engine.Throw(CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM)));
195         return engine.CreateUndefined();
196     }
197 
198     AsyncTask::CompleteCallback complete =
199         [=](NativeEngine& engine, AsyncTask& task, int32_t status) {
200             bool res = screen_->SetDensityDpi(densityDpi);
201             if (res) {
202                 task.Resolve(engine, engine.CreateUndefined());
203                 WLOGFI("OnSetDensityDpi success");
204             } else {
205                 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL),
206                                                 "JsScreen::OnSetDensityDpi failed."));
207                 WLOGFE("OnSetDensityDpi failed");
208             }
209         };
210     NativeValue* lastParam = nullptr;
211     if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr &&
212         info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) {
213         lastParam = info.argv[ARGC_TWO - 1];
214     }
215     NativeValue* result = nullptr;
216     AsyncTask::Schedule("JsScreen::OnSetDensityDpi",
217         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
218     return result;
219 }
220 
FindJsDisplayObject(ScreenId screenId)221 std::shared_ptr<NativeReference> FindJsDisplayObject(ScreenId screenId)
222 {
223     WLOGFI("[NAPI]Try to find screen %{public}" PRIu64" in g_JsScreenMap", screenId);
224     std::lock_guard<std::recursive_mutex> lock(g_mutex);
225     if (g_JsScreenMap.find(screenId) == g_JsScreenMap.end()) {
226         WLOGFI("[NAPI]Can not find screen %{public}" PRIu64" in g_JsScreenMap", screenId);
227         return nullptr;
228     }
229     return g_JsScreenMap[screenId];
230 }
231 
CreateJsScreenObject(NativeEngine & engine,sptr<Screen> & screen)232 NativeValue* CreateJsScreenObject(NativeEngine& engine, sptr<Screen>& screen)
233 {
234     WLOGFI("JsScreen::CreateJsScreen is called");
235     NativeValue* objValue = nullptr;
236     std::shared_ptr<NativeReference> jsScreenObj = FindJsDisplayObject(screen->GetId());
237     if (jsScreenObj != nullptr && jsScreenObj->Get() != nullptr) {
238         WLOGFI("[NAPI]FindJsScreenObject %{public}" PRIu64"", screen->GetId());
239         objValue = jsScreenObj->Get();
240     }
241     if (objValue == nullptr) {
242         objValue = engine.CreateObject();
243     }
244     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
245     if (object == nullptr) {
246         WLOGFE("Failed to convert prop to jsObject");
247         return engine.CreateUndefined();
248     }
249     std::unique_ptr<JsScreen> jsScreen = std::make_unique<JsScreen>(screen);
250     object->SetNativePointer(jsScreen.release(), JsScreen::Finalizer, nullptr);
251     auto info = screen->GetScreenInfo();
252     if (info == nullptr) {
253         WLOGFE("Failed to GetScreenInfo");
254         return engine.CreateUndefined();
255     }
256     ScreenId screenId = info->GetScreenId();
257     object->SetProperty("id",
258         CreateJsValue(engine, screenId == SCREEN_ID_INVALID ? -1 : static_cast<int64_t>(screenId)));
259     ScreenId parentId = info->GetParentId();
260     object->SetProperty("parent",
261         CreateJsValue(engine, parentId == SCREEN_ID_INVALID ? -1 : static_cast<int64_t>(parentId)));
262     object->SetProperty("orientation", CreateJsValue(engine, info->GetOrientation()));
263     object->SetProperty("activeModeIndex", CreateJsValue(engine, info->GetModeId()));
264     object->SetProperty("supportedModeInfo", CreateJsScreenModeArrayObject(engine, info->GetModes()));
265     object->SetProperty("densityDpi", CreateJsValue(engine,
266         static_cast<uint32_t>(info->GetVirtualPixelRatio() * DOT_PER_INCH))); // Dpi = Density(VPR) * 160.
267     if (jsScreenObj == nullptr || jsScreenObj->Get() == nullptr) {
268         std::shared_ptr<NativeReference> JsScreenRef;
269         JsScreenRef.reset(engine.CreateReference(objValue, 1));
270         std::lock_guard<std::recursive_mutex> lock(g_mutex);
271         g_JsScreenMap[screenId] = JsScreenRef;
272         const char *moduleName = "JsScreen";
273         BindNativeFunction(engine, *object, "setScreenActiveMode", moduleName, JsScreen::SetScreenActiveMode);
274         BindNativeFunction(engine, *object, "setOrientation", moduleName, JsScreen::SetOrientation);
275         BindNativeFunction(engine, *object, "setDensityDpi", moduleName, JsScreen::SetDensityDpi);
276     }
277     return objValue;
278 }
279 
CreateJsScreenModeArrayObject(NativeEngine & engine,std::vector<sptr<SupportedScreenModes>> screenModes)280 NativeValue* CreateJsScreenModeArrayObject(NativeEngine& engine, std::vector<sptr<SupportedScreenModes>> screenModes)
281 {
282     NativeValue* arrayValue = engine.CreateArray(screenModes.size());
283     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
284     size_t i = 0;
285     for (const auto& mode : screenModes) {
286         array->SetElement(i++, CreateJsScreenModeObject(engine, mode));
287     }
288     return arrayValue;
289 }
290 
CreateJsScreenModeObject(NativeEngine & engine,const sptr<SupportedScreenModes> & mode)291 NativeValue* CreateJsScreenModeObject(NativeEngine& engine, const sptr<SupportedScreenModes>& mode)
292 {
293     WLOGFI("JsScreen::CreateJsScreenMode is called");
294     NativeValue* objValue = engine.CreateObject();
295     NativeObject* optionObject = ConvertNativeValueTo<NativeObject>(objValue);
296     if (optionObject == nullptr) {
297         WLOGFE("Failed to convert prop to jsObject");
298         return engine.CreateUndefined();
299     }
300     uint32_t width = mode->width_;
301     uint32_t height = mode->height_;
302     uint32_t refreshRate = mode->refreshRate_;
303     optionObject->SetProperty("width", CreateJsValue(engine, width));
304     optionObject->SetProperty("height", CreateJsValue(engine, height));
305     optionObject->SetProperty("refreshRate", CreateJsValue(engine, refreshRate));
306     return objValue;
307 }
308 }  // namespace Rosen
309 }  // namespace OHOS
310