/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "js_runtime_utils.h" #include "native_engine/native_reference.h" #include "display_manager.h" #include "window_manager_hilog.h" #include "singleton_container.h" #include "js_display_listener.h" #include "js_display.h" #include "js_display_manager.h" namespace OHOS { namespace Rosen { using namespace AbilityRuntime; constexpr size_t ARGC_ONE = 1; constexpr size_t ARGC_TWO = 2; constexpr int32_t INDEX_ONE = 1; namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsDisplayManager"}; } class JsDisplayManager { public: explicit JsDisplayManager(NativeEngine* engine) { } ~JsDisplayManager() = default; static void Finalizer(NativeEngine* engine, void* data, void* hint) { WLOGFI("JsDisplayManager::Finalizer is called"); std::unique_ptr(static_cast(data)); } static NativeValue* GetDefaultDisplay(NativeEngine* engine, NativeCallbackInfo* info) { JsDisplayManager* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnGetDefaultDisplay(*engine, *info) : nullptr; } static NativeValue* GetDefaultDisplaySync(NativeEngine* engine, NativeCallbackInfo* info) { JsDisplayManager* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnGetDefaultDisplaySync(*engine, *info) : nullptr; } static NativeValue* GetAllDisplay(NativeEngine* engine, NativeCallbackInfo* info) { JsDisplayManager* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnGetAllDisplay(*engine, *info) : nullptr; } static NativeValue* RegisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) { JsDisplayManager* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnRegisterDisplayManagerCallback(*engine, *info) : nullptr; } static NativeValue* UnregisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) { JsDisplayManager* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnUnregisterDisplayManagerCallback(*engine, *info) : nullptr; } private: std::map, sptr>> jsCbMap_; std::mutex mtx_; NativeValue* OnGetDefaultDisplay(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsDisplayManager::OnGetDefaultDisplay is called"); DMError errCode = DMError::DM_OK; if (info.argc != 0 && info.argc != ARGC_ONE) { WLOGFE("JsDisplayManager::OnGetDefaultDisplay params not match"); errCode = DMError::DM_ERROR_INVALID_PARAM; } AsyncTask::CompleteCallback complete = [=](NativeEngine& engine, AsyncTask& task, int32_t status) { if (errCode != DMError::DM_OK) { task.Reject(engine, CreateJsError(engine, static_cast(errCode), "JsDisplayManager::OnGetDefaultDisplay failed.")); } sptr display = SingletonContainer::Get().GetDefaultDisplay(); if (display != nullptr) { task.Resolve(engine, CreateJsDisplayObject(engine, display)); WLOGFI("JsDisplayManager::OnGetDefaultDisplay success"); } else { task.Reject(engine, CreateJsError(engine, static_cast(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetDefaultDisplay failed.")); } }; NativeValue* lastParam = nullptr; if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { lastParam = info.argv[0]; } NativeValue* result = nullptr; AsyncTask::Schedule("JsDisplayManager::OnGetDefaultDisplay", engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); return result; } NativeValue* OnGetDefaultDisplaySync(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsDisplayManager::OnGetDefaultDisplaySync is called"); if (info.argc != 0) { WLOGFE("JsDisplayManager::OnGetDefaultDisplaySync params not match"); return engine.CreateUndefined(); } sptr display = SingletonContainer::Get().GetDefaultDisplay(); if (display == nullptr) { WLOGFE("JsDisplayManager::OnGetDefaultDisplaySync, display is nullptr."); return engine.CreateUndefined(); } return CreateJsDisplayObject(engine, display); } NativeValue* OnGetAllDisplay(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsDisplayManager::OnGetAllDisplay is called"); DMError errCode = DMError::DM_OK; if (info.argc != 0 && info.argc != ARGC_ONE) { WLOGFE("JsDisplayManager::OnGetAllDisplay params not match"); errCode = DMError::DM_ERROR_INVALID_PARAM; } AsyncTask::CompleteCallback complete = [=](NativeEngine& engine, AsyncTask& task, int32_t status) { if (errCode != DMError::DM_OK) { task.Reject(engine, CreateJsError(engine, static_cast(errCode), "JsDisplayManager::OnGetAllDisplay failed.")); } std::vector> displays = SingletonContainer::Get().GetAllDisplays(); if (!displays.empty()) { task.Resolve(engine, CreateJsDisplayArrayObject(engine, displays)); WLOGFI("JsDisplayManager::GetAllDisplays success"); } else { task.Reject(engine, CreateJsError(engine, static_cast(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetAllDisplay failed.")); } }; NativeValue* lastParam = nullptr; if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { lastParam = info.argv[0]; } NativeValue* result = nullptr; AsyncTask::Schedule("JsDisplayManager::OnGetAllDisplay", engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); return result; } void RegisterDisplayListenerWithType(NativeEngine& engine, const std::string& type, NativeValue* value) { if (IfCallbackRegistered(type, value)) { WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType callback already registered!"); return; } std::unique_ptr callbackRef; callbackRef.reset(engine.CreateReference(value, 1)); sptr displayListener = new(std::nothrow) JsDisplayListener(&engine); if (displayListener == nullptr) { WLOGFE("displayListener is nullptr"); return; } if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_CHANGE) { SingletonContainer::Get().RegisterDisplayListener(displayListener); WLOGFI("JsDisplayManager::RegisterDisplayListenerWithType success"); } else { WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType failed method: %{public}s not support!", type.c_str()); return; } displayListener->AddCallback(type, value); jsCbMap_[type][std::move(callbackRef)] = displayListener; } bool IfCallbackRegistered(const std::string& type, NativeValue* jsListenerObject) { if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsDisplayManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str()); return false; } for (auto& iter : jsCbMap_[type]) { if (jsListenerObject->StrictEquals(iter.first->Get())) { WLOGFE("JsDisplayManager::IfCallbackRegistered callback already registered!"); return true; } } return false; } void UnregisterAllDisplayListenerWithType(const std::string& type) { if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType methodName %{public}s not registered!", type.c_str()); return; } for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { it->second->RemoveAllCallback(); if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_CHANGE) { sptr thisListener(it->second); SingletonContainer::Get().UnregisterDisplayListener(thisListener); WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType success"); } jsCbMap_[type].erase(it++); } jsCbMap_.erase(type); } void UnRegisterDisplayListenerWithType(const std::string& type, NativeValue* value) { if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType methodName %{public}s not registered!", type.c_str()); return; } for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { if (value->StrictEquals(it->first->Get())) { it->second->RemoveCallback(type, value); if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_CHANGE) { sptr thisListener(it->second); SingletonContainer::Get().UnregisterDisplayListener(thisListener); WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType success"); } jsCbMap_[type].erase(it++); break; } else { it++; } } if (jsCbMap_[type].empty()) { jsCbMap_.erase(type); } } NativeValue* OnRegisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback is called"); if (info.argc != ARGC_TWO) { WLOGFE("JsDisplayManager Params not match: %{public}zu", info.argc); return engine.CreateUndefined(); } std::string cbType; if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { WLOGFE("Failed to convert parameter to callbackType"); return engine.CreateUndefined(); } NativeValue* value = info.argv[INDEX_ONE]; if (value == nullptr) { WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is nullptr"); return engine.CreateUndefined(); } if (!value->IsCallable()) { WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is not callable"); return engine.CreateUndefined(); } std::lock_guard lock(mtx_); RegisterDisplayListenerWithType(engine, cbType, value); return engine.CreateUndefined(); } NativeValue* OnUnregisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsDisplayManager::OnUnregisterDisplayCallback is called"); if (info.argc == 0) { WLOGFE("JsDisplayManager Params not match %{public}zu", info.argc); return engine.CreateUndefined(); } std::string cbType; if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { WLOGFE("Failed to convert parameter to callbackType"); return engine.CreateUndefined(); } std::lock_guard lock(mtx_); if (info.argc == ARGC_ONE) { UnregisterAllDisplayListenerWithType(cbType); } else { NativeValue* value = info.argv[INDEX_ONE]; if (value == nullptr) { WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is nullptr"); return engine.CreateUndefined(); } if (!value->IsCallable()) { WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is not callable"); return engine.CreateUndefined(); } UnRegisterDisplayListenerWithType(cbType, value); } return engine.CreateUndefined(); } NativeValue* CreateJsDisplayArrayObject(NativeEngine& engine, std::vector>& displays) { WLOGFI("JsDisplayManager::CreateJsDisplayArrayObject is called"); NativeValue* arrayValue = engine.CreateArray(displays.size()); NativeArray* array = ConvertNativeValueTo(arrayValue); if (array == nullptr) { WLOGFE("Failed to create display array"); return engine.CreateUndefined(); } int32_t i = 0; for (auto& display : displays) { if (display == nullptr) { continue; } array->SetElement(i++, CreateJsDisplayObject(engine, display)); } return arrayValue; } }; NativeValue* InitDisplayState(NativeEngine* engine) { WLOGFI("JsDisplayManager::InitDisplayState called"); if (engine == nullptr) { WLOGFE("engine is nullptr"); return nullptr; } NativeValue *objValue = engine->CreateObject(); NativeObject *object = ConvertNativeValueTo(objValue); if (object == nullptr) { WLOGFE("Failed to get object"); return nullptr; } object->SetProperty("STATE_UNKNOWN", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_UNKNOWN))); object->SetProperty("STATE_OFF", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_OFF))); object->SetProperty("STATE_ON", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_ON))); object->SetProperty("STATE_DOZE", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_DOZE))); object->SetProperty("STATE_DOZE_SUSPEND", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_DOZE_SUSPEND))); object->SetProperty("STATE_VR", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_VR))); object->SetProperty("STATE_ON_SUSPEND", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_ON_SUSPEND))); return objValue; } NativeValue* JsDisplayManagerInit(NativeEngine* engine, NativeValue* exportObj) { WLOGFI("JsDisplayManagerInit is called"); if (engine == nullptr || exportObj == nullptr) { WLOGFE("JsDisplayManagerInit engine or exportObj is nullptr"); return nullptr; } NativeObject* object = ConvertNativeValueTo(exportObj); if (object == nullptr) { WLOGFE("JsDisplayManagerInit object is nullptr"); return nullptr; } std::unique_ptr jsDisplayManager = std::make_unique(engine); object->SetNativePointer(jsDisplayManager.release(), JsDisplayManager::Finalizer, nullptr); object->SetProperty("DisplayState", InitDisplayState(engine)); BindNativeFunction(*engine, *object, "getDefaultDisplay", JsDisplayManager::GetDefaultDisplay); BindNativeFunction(*engine, *object, "getDefaultDisplaySync", JsDisplayManager::GetDefaultDisplaySync); BindNativeFunction(*engine, *object, "getAllDisplay", JsDisplayManager::GetAllDisplay); BindNativeFunction(*engine, *object, "on", JsDisplayManager::RegisterDisplayManagerCallback); BindNativeFunction(*engine, *object, "off", JsDisplayManager::UnregisterDisplayManagerCallback); return engine->CreateUndefined(); } } // namespace Rosen } // namespace OHOS