• 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 <vector>
17 #include <new>
18 
19 #include "js_runtime_utils.h"
20 #include "native_engine/native_reference.h"
21 #include "display_manager.h"
22 #include "window_manager_hilog.h"
23 #include "singleton_container.h"
24 #include "js_display_listener.h"
25 #include "js_display.h"
26 #include "js_display_manager.h"
27 
28 namespace OHOS {
29 namespace Rosen {
30 using namespace AbilityRuntime;
31 constexpr size_t ARGC_ONE = 1;
32 constexpr size_t ARGC_TWO = 2;
33 constexpr int32_t INDEX_ONE = 1;
34 namespace {
35     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsDisplayManager"};
36 }
37 
38 class JsDisplayManager {
39 public:
JsDisplayManager(NativeEngine * engine)40 explicit JsDisplayManager(NativeEngine* engine) {
41 }
42 
43 ~JsDisplayManager() = default;
44 
Finalizer(NativeEngine * engine,void * data,void * hint)45 static void Finalizer(NativeEngine* engine, void* data, void* hint)
46 {
47     WLOGFI("JsDisplayManager::Finalizer is called");
48     std::unique_ptr<JsDisplayManager>(static_cast<JsDisplayManager*>(data));
49 }
50 
GetDefaultDisplay(NativeEngine * engine,NativeCallbackInfo * info)51 static NativeValue* GetDefaultDisplay(NativeEngine* engine, NativeCallbackInfo* info)
52 {
53     JsDisplayManager* me = CheckParamsAndGetThis<JsDisplayManager>(engine, info);
54     return (me != nullptr) ? me->OnGetDefaultDisplay(*engine, *info) : nullptr;
55 }
56 
GetAllDisplay(NativeEngine * engine,NativeCallbackInfo * info)57 static NativeValue* GetAllDisplay(NativeEngine* engine, NativeCallbackInfo* info)
58 {
59     JsDisplayManager* me = CheckParamsAndGetThis<JsDisplayManager>(engine, info);
60     return (me != nullptr) ? me->OnGetAllDisplay(*engine, *info) : nullptr;
61 }
62 
RegisterDisplayManagerCallback(NativeEngine * engine,NativeCallbackInfo * info)63 static NativeValue* RegisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info)
64 {
65     JsDisplayManager* me = CheckParamsAndGetThis<JsDisplayManager>(engine, info);
66     return (me != nullptr) ? me->OnRegisterDisplayManagerCallback(*engine, *info) : nullptr;
67 }
68 
UnregisterDisplayManagerCallback(NativeEngine * engine,NativeCallbackInfo * info)69 static NativeValue* UnregisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info)
70 {
71     JsDisplayManager* me = CheckParamsAndGetThis<JsDisplayManager>(engine, info);
72     return (me != nullptr) ? me->OnUnregisterDisplayManagerCallback(*engine, *info) : nullptr;
73 }
74 
75 private:
76 std::map<std::string, std::map<std::unique_ptr<NativeReference>, sptr<JsDisplayListener>>> jsCbMap_;
77 std::mutex mtx_;
78 
OnGetDefaultDisplay(NativeEngine & engine,NativeCallbackInfo & info)79 NativeValue* OnGetDefaultDisplay(NativeEngine& engine, NativeCallbackInfo& info)
80 {
81     WLOGFI("JsDisplayManager::OnGetDefaultDisplay is called");
82     DMError errCode = DMError::DM_OK;
83     if (info.argc != 0 && info.argc != ARGC_ONE) {
84         WLOGFE("JsDisplayManager::OnGetDefaultDisplay params not match");
85         errCode = DMError::DM_ERROR_INVALID_PARAM;
86     }
87 
88     AsyncTask::CompleteCallback complete =
89         [=](NativeEngine& engine, AsyncTask& task, int32_t status) {
90             if (errCode != DMError::DM_OK) {
91                 task.Reject(engine, CreateJsError(engine,
92                     static_cast<int32_t>(errCode), "JsDisplayManager::OnGetDefaultDisplay failed."));
93             }
94             sptr<Display> display = SingletonContainer::Get<DisplayManager>().GetDefaultDisplay();
95             if (display != nullptr) {
96                 task.Resolve(engine, CreateJsDisplayObject(engine, display));
97                 WLOGFI("JsDisplayManager::OnGetDefaultDisplay success");
98             } else {
99                 task.Reject(engine, CreateJsError(engine,
100                     static_cast<int32_t>(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetDefaultDisplay failed."));
101             }
102         };
103     NativeValue* lastParam = nullptr;
104     if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) {
105         lastParam = info.argv[0];
106     }
107     NativeValue* result = nullptr;
108     AsyncTask::Schedule(
109         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
110     return result;
111 }
112 
OnGetAllDisplay(NativeEngine & engine,NativeCallbackInfo & info)113 NativeValue* OnGetAllDisplay(NativeEngine& engine, NativeCallbackInfo& info)
114 {
115     WLOGFI("JsDisplayManager::OnGetAllDisplay is called");
116     DMError errCode = DMError::DM_OK;
117     if (info.argc != 0 && info.argc != ARGC_ONE) {
118         WLOGFE("JsDisplayManager::OnGetAllDisplay params not match");
119         errCode = DMError::DM_ERROR_INVALID_PARAM;
120     }
121 
122     AsyncTask::CompleteCallback complete =
123         [=](NativeEngine& engine, AsyncTask& task, int32_t status) {
124             if (errCode != DMError::DM_OK) {
125                 task.Reject(engine, CreateJsError(engine,
126                     static_cast<int32_t>(errCode), "JsDisplayManager::OnGetAllDisplay failed."));
127             }
128             std::vector<sptr<Display>> displays = SingletonContainer::Get<DisplayManager>().GetAllDisplays();
129             if (!displays.empty()) {
130                 task.Resolve(engine, CreateJsDisplayArrayObject(engine, displays));
131                 WLOGFI("JsDisplayManager::GetAllDisplays success");
132             } else {
133                 task.Reject(engine, CreateJsError(engine,
134                     static_cast<int32_t>(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetAllDisplay failed."));
135             }
136         };
137 
138     NativeValue* lastParam = nullptr;
139     if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) {
140         lastParam = info.argv[0];
141     }
142     NativeValue* result = nullptr;
143     AsyncTask::Schedule(
144         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
145     return result;
146 }
147 
RegisterDisplayListenerWithType(NativeEngine & engine,const std::string & type,NativeValue * value)148 void RegisterDisplayListenerWithType(NativeEngine& engine, const std::string& type, NativeValue* value)
149 {
150     if (IfCallbackRegistered(type, value)) {
151         WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType callback already registered!");
152         return;
153     }
154     std::unique_ptr<NativeReference> callbackRef;
155     callbackRef.reset(engine.CreateReference(value, 1));
156     sptr<JsDisplayListener> displayListener = new(std::nothrow) JsDisplayListener(&engine);
157     if (displayListener == nullptr) {
158         WLOGFE("displayListener is nullptr");
159         return;
160     }
161     if (type == "add" || type == "remove" || type == "change") {
162         SingletonContainer::Get<DisplayManager>().RegisterDisplayListener(displayListener);
163         WLOGFI("JsDisplayManager::RegisterDisplayListenerWithType success");
164     } else {
165         WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType failed method: %{public}s not support!",
166                type.c_str());
167         return;
168     }
169     displayListener->AddCallback(value);
170     jsCbMap_[type][std::move(callbackRef)] = displayListener;
171 }
172 
IfCallbackRegistered(const std::string & type,NativeValue * jsListenerObject)173 bool IfCallbackRegistered(const std::string& type, NativeValue* jsListenerObject)
174 {
175     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
176         WLOGFI("JsDisplayManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str());
177         return false;
178     }
179 
180     for (auto& iter : jsCbMap_[type]) {
181         if (jsListenerObject->StrictEquals(iter.first->Get())) {
182             WLOGFE("JsDisplayManager::IfCallbackRegistered callback already registered!");
183             return true;
184         }
185     }
186     return false;
187 }
188 
UnregisterAllDisplayListenerWithType(const std::string & type)189 void UnregisterAllDisplayListenerWithType(const std::string& type)
190 {
191     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
192         WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType methodName %{public}s not registered!",
193                type.c_str());
194         return;
195     }
196     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
197         it->second->RemoveAllCallback();
198         if (type == "add" || type == "remove" || type == "change") {
199             sptr<DisplayManager::IDisplayListener> thisListener(it->second);
200             SingletonContainer::Get<DisplayManager>().UnregisterDisplayListener(thisListener);
201             WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType success");
202         }
203         jsCbMap_[type].erase(it++);
204     }
205     jsCbMap_.erase(type);
206 }
207 
UnRegisterDisplayListenerWithType(const std::string & type,NativeValue * value)208 void UnRegisterDisplayListenerWithType(const std::string& type, NativeValue* value)
209 {
210     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
211         WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType methodName %{public}s not registered!",
212                type.c_str());
213         return;
214     }
215     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
216         if (value->StrictEquals(it->first->Get())) {
217             it->second->RemoveCallback(value);
218             if (type == "add" || type == "remove" || type == "change") {
219                 sptr<DisplayManager::IDisplayListener> thisListener(it->second);
220                 SingletonContainer::Get<DisplayManager>().UnregisterDisplayListener(thisListener);
221                 WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType success");
222             }
223             jsCbMap_[type].erase(it++);
224             break;
225         } else {
226             it++;
227         }
228     }
229     if (jsCbMap_[type].empty()) {
230         jsCbMap_.erase(type);
231     }
232 }
233 
OnRegisterDisplayManagerCallback(NativeEngine & engine,NativeCallbackInfo & info)234 NativeValue* OnRegisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info)
235 {
236     WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback is called");
237     if (info.argc != ARGC_TWO) {
238         WLOGFE("JsDisplayManager Params not match: %{public}zu", info.argc);
239         return engine.CreateUndefined();
240     }
241     std::string cbType;
242     if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
243         WLOGFE("Failed to convert parameter to callbackType");
244         return engine.CreateUndefined();
245     }
246     NativeValue* value = info.argv[INDEX_ONE];
247     if (value == nullptr) {
248         WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is nullptr");
249         return engine.CreateUndefined();
250     }
251     if (!value->IsCallable()) {
252         WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is not callable");
253         return engine.CreateUndefined();
254     }
255     std::lock_guard<std::mutex> lock(mtx_);
256     RegisterDisplayListenerWithType(engine, cbType, value);
257     return engine.CreateUndefined();
258 }
259 
OnUnregisterDisplayManagerCallback(NativeEngine & engine,NativeCallbackInfo & info)260 NativeValue* OnUnregisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info)
261 {
262     WLOGFI("JsDisplayManager::OnUnregisterDisplayCallback is called");
263     if (info.argc == 0) {
264         WLOGFE("JsDisplayManager Params not match %{public}zu", info.argc);
265         return engine.CreateUndefined();
266     }
267     std::string cbType;
268     if (!ConvertFromJsValue(engine, info.argv[0], cbType)) {
269         WLOGFE("Failed to convert parameter to callbackType");
270         return engine.CreateUndefined();
271     }
272     std::lock_guard<std::mutex> lock(mtx_);
273     if (info.argc == ARGC_ONE) {
274         UnregisterAllDisplayListenerWithType(cbType);
275     } else {
276         NativeValue* value = info.argv[INDEX_ONE];
277         if (value == nullptr) {
278             WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is nullptr");
279             return engine.CreateUndefined();
280         }
281         if (!value->IsCallable()) {
282             WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is not callable");
283             return engine.CreateUndefined();
284         }
285         UnRegisterDisplayListenerWithType(cbType, value);
286     }
287     return engine.CreateUndefined();
288 }
289 
CreateJsDisplayArrayObject(NativeEngine & engine,std::vector<sptr<Display>> & displays)290 NativeValue* CreateJsDisplayArrayObject(NativeEngine& engine, std::vector<sptr<Display>>& displays)
291 {
292     WLOGFI("JsDisplayManager::CreateJsDisplayArrayObject is called");
293     NativeValue* arrayValue = engine.CreateArray(displays.size());
294     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
295     int32_t i = 0;
296     for (auto& display : displays) {
297         array->SetElement(i++, CreateJsDisplayObject(engine, display));
298     }
299     return arrayValue;
300 }
301 };
302 
InitDisplayState(NativeEngine * engine)303 NativeValue* InitDisplayState(NativeEngine* engine)
304 {
305     WLOGFI("JsDisplayManager::InitDisplayState called");
306 
307     if (engine == nullptr) {
308         WLOGFE("engine is nullptr");
309         return nullptr;
310     }
311 
312     NativeValue *objValue = engine->CreateObject();
313     NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
314     if (object == nullptr) {
315         WLOGFE("Failed to get object");
316         return nullptr;
317     }
318 
319     object->SetProperty("STATE_UNKNOWN", CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_UNKNOWN)));
320     object->SetProperty("STATE_OFF", CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_OFF)));
321     object->SetProperty("STATE_ON", CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_ON)));
322     object->SetProperty("STATE_DOZE",
323                         CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_DOZE)));
324     object->SetProperty("STATE_DOZE_SUSPEND",
325                         CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_DOZE_SUSPEND)));
326     object->SetProperty("STATE_VR",
327                         CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_VR)));
328     object->SetProperty("STATE_ON_SUSPEND",
329                         CreateJsValue(*engine, static_cast<int32_t>(DisplayStateMode::STATE_ON_SUSPEND)));
330     return objValue;
331 }
332 
JsDisplayManagerInit(NativeEngine * engine,NativeValue * exportObj)333 NativeValue* JsDisplayManagerInit(NativeEngine* engine, NativeValue* exportObj)
334 {
335     WLOGFI("JsDisplayManagerInit is called");
336 
337     if (engine == nullptr || exportObj == nullptr) {
338         WLOGFE("JsDisplayManagerInit engine or exportObj is nullptr");
339         return nullptr;
340     }
341 
342     NativeObject* object = ConvertNativeValueTo<NativeObject>(exportObj);
343     if (object == nullptr) {
344         WLOGFE("JsDisplayManagerInit object is nullptr");
345         return nullptr;
346     }
347 
348     object->SetProperty("DisplayState", InitDisplayState(engine));
349 
350     std::unique_ptr<JsDisplayManager> jsDisplayManager = std::make_unique<JsDisplayManager>(engine);
351     object->SetNativePointer(jsDisplayManager.release(), JsDisplayManager::Finalizer, nullptr);
352 
353     BindNativeFunction(*engine, *object, "getDefaultDisplay", JsDisplayManager::GetDefaultDisplay);
354     BindNativeFunction(*engine, *object, "getAllDisplay", JsDisplayManager::GetAllDisplay);
355     BindNativeFunction(*engine, *object, "on", JsDisplayManager::RegisterDisplayManagerCallback);
356     BindNativeFunction(*engine, *object, "off", JsDisplayManager::UnregisterDisplayManagerCallback);
357     return engine->CreateUndefined();
358 }
359 }  // namespace Rosen
360 }  // namespace OHOS