From d7bf426926e2a3eb2d38b3a63a780fd89b86c85d Mon Sep 17 00:00:00 2001 From: liyizhou <13278290+li-yi-zhou@user.noreply.gitee.com> Date: Tue, 17 Jun 2025 11:01:07 +0800 Subject: [PATCH] =?UTF-8?q?=E9=97=AA=E6=8E=A7=E7=90=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 + .../wm/floating_ball_template_base_info.h | 34 + .../wm/floating_ball_template_info.h | 74 ++ interfaces/innerkits/wm/window.h | 49 ++ interfaces/innerkits/wm/wm_common.h | 56 +- interfaces/kits/napi/BUILD.gn | 1 + .../kits/napi/floating_ball_napi/BUILD.gn | 67 ++ .../napi/floating_ball_napi/js_fb_utils.cpp | 109 +++ .../napi/floating_ball_napi/js_fb_utils.h | 31 + .../js_fb_window_controller.cpp | 631 ++++++++++++++++++ .../js_fb_window_controller.h | 73 ++ .../js_fb_window_listener.cpp | 96 +++ .../js_fb_window_listener.h | 45 ++ .../js_fb_window_manager.cpp | 137 ++++ .../floating_ball_napi/js_fb_window_manager.h | 37 + .../floating_ball_napi/js_fbwindow_module.cpp | 28 + .../window_napi/js_window_utils.h | 3 + previewer/include/wm_common.h | 24 +- test/fuzztest/wms/BUILD.gn | 1 + test/fuzztest/wms/fb_fuzzer/BUILD.gn | 83 +++ test/fuzztest/wms/fb_fuzzer/corpus/init | 14 + test/fuzztest/wms/fb_fuzzer/fb_fuzzer.cpp | 159 +++++ test/fuzztest/wms/fb_fuzzer/fb_fuzzer.h | 21 + test/fuzztest/wms/fb_fuzzer/project.xml | 25 + utils/include/window_helper.h | 11 +- utils/src/wm_common.cpp | 8 + .../common/include/session_permission.h | 1 + .../common/include/window_session_property.h | 6 + .../common/src/window_session_property.cpp | 35 +- .../js_scene_session.cpp | 259 +++++++ .../scene_session_manager/js_scene_session.h | 13 + .../scene_session_manager/js_scene_utils.cpp | 1 + .../scene_session_manager/js_scene_utils.h | 5 +- .../include/zidl/session_stage_interface.h | 10 + .../zidl/session_stage_ipc_interface_code.h | 1 + .../include/zidl/session_stage_proxy.h | 1 + .../include/zidl/session_stage_stub.h | 1 + .../src/zidl/session_stage_proxy.cpp | 28 + .../container/src/zidl/session_stage_stub.cpp | 14 + 39 files changed, 2192 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 interfaces/innerkits/wm/floating_ball_template_base_info.h create mode 100644 interfaces/innerkits/wm/floating_ball_template_info.h create mode 100644 interfaces/kits/napi/floating_ball_napi/BUILD.gn create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_utils.cpp create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_utils.h create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.cpp create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.h create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.cpp create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.h create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.cpp create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.h create mode 100644 interfaces/kits/napi/floating_ball_napi/js_fbwindow_module.cpp create mode 100644 test/fuzztest/wms/fb_fuzzer/BUILD.gn create mode 100644 test/fuzztest/wms/fb_fuzzer/corpus/init create mode 100644 test/fuzztest/wms/fb_fuzzer/fb_fuzzer.cpp create mode 100644 test/fuzztest/wms/fb_fuzzer/fb_fuzzer.h create mode 100644 test/fuzztest/wms/fb_fuzzer/project.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..6b09f17c68 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.vscode/tags-34.wecode-db +.vscode/tags-34.wecode-db-shm +.vscode/tags-34.wecode-db-wal +.vscode/tags-34.wecode-lock +.vscode/.cache/clangd/wecode-cpp.db +.vscode/.cache/clangd/wecode-cpp.db-shm +.vscode/.cache/clangd/wecode-cpp.db-wal diff --git a/interfaces/innerkits/wm/floating_ball_template_base_info.h b/interfaces/innerkits/wm/floating_ball_template_base_info.h new file mode 100644 index 0000000000..11f5840d6d --- /dev/null +++ b/interfaces/innerkits/wm/floating_ball_template_base_info.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025-2025 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. + */ + +#ifndef OHOS_FLOATING_BALL_TEMPALTE_BASE_INFO_H +#define OHOS_FLOATING_BALL_TEMPALTE_BASE_INFO_H + +#include "wm_common.h" + +namespace OHOS::Rosen { +class FloatingBallTemplateBaseInfo { +public: + FloatingBallTemplateBaseInfo() = default; + FloatingBallTemplateBaseInfo(uint32_t templateType, std::string title, std::string content) : + template_(templateType), title_(title), content_(content) {}; + virtual ~FloatingBallTemplateBaseInfo() = default; + + uint32_t template_ {}; + std::string title_ {}; + std::string content_ {}; +}; +} // namespace OHOS::Rosen +#endif // OHOS_FLOATING_BALL_TEMPALTE_BASE_INFO_H \ No newline at end of file diff --git a/interfaces/innerkits/wm/floating_ball_template_info.h b/interfaces/innerkits/wm/floating_ball_template_info.h new file mode 100644 index 0000000000..01ed2b887f --- /dev/null +++ b/interfaces/innerkits/wm/floating_ball_template_info.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025-2025 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. + */ + +#ifndef OHOS_FLOATING_BALL_TEMPALTE_INFO_H +#define OHOS_FLOATING_BALL_TEMPALTE_INFO_H + +#include + +#include "wm_common.h" +#include "floating_ball_template_base_info.h" + +namespace OHOS::Rosen { +class FloatingBallTemplateInfo : public FloatingBallTemplateBaseInfo, + public Parcelable { +public: + FloatingBallTemplateInfo() = default; + FloatingBallTemplateInfo(uint32_t templateType, std::string title, std::string content, + std::shared_ptr icon) : FloatingBallTemplateBaseInfo(templateType, title, content), + icon_(icon) {}; + FloatingBallTemplateInfo(const FloatingBallTemplateBaseInfo& baseInfo, + std::shared_ptr icon) : + FloatingBallTemplateBaseInfo(baseInfo.template_, baseInfo.title_, baseInfo.content_), icon_(icon) {}; + ~FloatingBallTemplateInfo() override = default; + + std::shared_ptr icon_ {}; + + bool Marshalling(Parcel& parcel) const override + { + if (!parcel.WriteUint32(template_) || !parcel.WriteString(title_) || !parcel.WriteString(content_)) { + return false; + } + bool hasIcon = icon_ ? true : false; + if (!parcel.WriteBool(hasIcon)) { + return false; + } + if (hasIcon && !parcel.WriteParcelable(icon_.get())) { + return false; + } + return true; + } + + static FloatingBallTemplateInfo* Unmarshalling(Parcel& parcel) + { + auto* fbTemplateInfo = new FloatingBallTemplateInfo(); + if (!parcel.ReadUint32(fbTemplateInfo->template_) || !parcel.ReadString(fbTemplateInfo->title_) || + !parcel.ReadString(fbTemplateInfo->content_)) { + delete fbTemplateInfo; + return nullptr; + } + bool hasIcon = parcel.ReadBool(); + if (hasIcon) { + fbTemplateInfo->icon_ = std::shared_ptr(parcel.ReadParcelable()); + if (!fbTemplateInfo->icon_) { + delete fbTemplateInfo; + return nullptr; + } + } + return fbTemplateInfo; + } +}; +} // namespace OHOS::Rosen +#endif // OHOS_FLOATING_BALL_TEMPALTE_INFO_H \ No newline at end of file diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index ce4d07dc9d..10c8bba459 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -25,6 +25,7 @@ #include "window_option.h" #include "occupied_area_change_info.h" #include "data_handler_interface.h" +#include "floating_ball_template_base_info.h" typedef struct napi_env__* napi_env; typedef struct napi_value__* napi_value; @@ -873,6 +874,20 @@ public: static sptr CreatePiP(sptr& option, const PiPTemplateInfo& pipTemplateInfo, const std::shared_ptr& context, WMError& errCode = DefaultCreateErrCode); + /** + * @brief create fb window with session + * + * @param option window propertion + * @param fbTemplateBaseInfo baseInfo of fb window + * @param icon icon of fb window + * @param context ability context + * @param errCode error code of create fb window + * @return sptr If create fb window success, return window instance; Otherwise, return nullptr + */ + static sptr CreateFb(sptr& option, const FloatingBallTemplateBaseInfo& fbTemplateBaseInfo, + const std::shared_ptr& icon, const std::shared_ptr& context, + WMError& errCode = DefaultCreateErrCode); + /** * @brief find window by windowName * @@ -4224,6 +4239,40 @@ public: * @return WM_OK means set success. */ virtual WMError InjectTouchEvent(const std::shared_ptr& pointerEvent) { return WMError::WM_OK; } + + /** + * @brief update the floating ball window instance (w,h,r). + * + * @param fbTemplateInfo the tempalte info of the floating-ball. + * @param icon the icon of the floating-ball. + */ + virtual void UpdateFloatingBall(const FloatingBallTemplateBaseInfo& fbTemplateBaseInfo, + const std::shared_ptr& icon) {} + + /** + * @brief Notify prepare to close window + */ + virtual void NotifyPrepareCloseFloatingBall() {} + + /** + * @brief restore floating ball ability (w,h,r). + * + * @param want the want of the ability. + */ + virtual WMError RestoreFbMainWindow(const std::shared_ptr& want) + { + return WMError::WM_OK; + } + + /** + * @brief get windowId of floating-ball + * + * @param windowId the windowId of floating-ball. + */ + virtual WMError GetFloatingBallWindowId(uint32_t& windowId) + { + return WMError::WM_OK; + } }; } } diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 7029753fe9..cd418f1101 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -158,6 +158,7 @@ enum class WindowType : uint32_t { WINDOW_TYPE_MAGNIFICATION, WINDOW_TYPE_MAGNIFICATION_MENU, ABOVE_APP_SYSTEM_WINDOW_END, + WINDOW_TYPE_FB, SYSTEM_SUB_WINDOW_BASE = 2500, WINDOW_TYPE_SYSTEM_SUB_WINDOW = SYSTEM_SUB_WINDOW_BASE, @@ -191,7 +192,8 @@ enum class WindowMode : uint32_t { WINDOW_MODE_SPLIT_SECONDARY, WINDOW_MODE_FLOATING, WINDOW_MODE_PIP, - END = WINDOW_MODE_PIP, + WINDOW_MODE_FB + END = WINDOW_MODE_FB, }; /** @@ -247,11 +249,13 @@ enum WindowModeSupport : uint32_t { WINDOW_MODE_SUPPORT_SPLIT_PRIMARY = 1 << 2, WINDOW_MODE_SUPPORT_SPLIT_SECONDARY = 1 << 3, WINDOW_MODE_SUPPORT_PIP = 1 << 4, + WINDOW_MODE_SUPPORT_FB = 1 << 5, WINDOW_MODE_SUPPORT_ALL = WINDOW_MODE_SUPPORT_FULLSCREEN | WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | WINDOW_MODE_SUPPORT_SPLIT_SECONDARY | WINDOW_MODE_SUPPORT_FLOATING | - WINDOW_MODE_SUPPORT_PIP + WINDOW_MODE_SUPPORT_PIP | + WINDOW_MODE_SUPPORT_FB }; /** @@ -328,6 +332,14 @@ enum class WMError : int32_t { WM_ERROR_ILLEGAL_PARAM, WM_ERROR_FILTER_ERROR, WM_ERROR_TIMEOUT, + WM_ERROR_FB_PARAM_INVALID, + WM_ERROR_FB_CREATE_FAILED, + WM_ERROR_FB_REPEAT_CONTROLLER, + WM_ERROR_FB_REPEAT_OPERATION, + WM_ERROR_FB_INTERNAL_ERROR, + WM_ERROR_FB_STATE_ABNORMALLY, + WM_ERROR_FB_INVALID_STATE, + WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED, }; /** @@ -357,6 +369,14 @@ enum class WmErrorCode : int32_t { WM_ERROR_ILLEGAL_PARAM = 1300016, WM_ERROR_FILTER_ERROR = 1300017, WM_ERROR_TIMEOUT = 1300018, + WM_ERROR_FB_PARAM_INVALID = 1300019, + WM_ERROR_FB_CREATE_FAILED = 1300020, + WM_ERROR_FB_REPEAT_CONTROLLER = 1300021, + WM_ERROR_FB_REPEAT_OPERATION = 1300022, + WM_ERROR_FB_INTERNAL_ERROR = 1300023, + WM_ERROR_FB_STATE_ABNORMALLY = 1300024, + WM_ERROR_FB_INVALID_STATE = 1300025, + WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED = 1300026, }; /** @@ -1583,12 +1603,44 @@ struct PiPTemplateInfo : public Parcelable { } }; + +/** + * @brief Enumerates floating ball state. + */ +enum class FloatingBallState : uint32_t { + STARTED = 1, + STOPPED = 2, + ERROR = 3, +}; + +/** + * @brief Enumerates floating ball template. + */ +enum class FloatingBallTemplate : uint32_t { + STATIC = 1, + NORMAL = 2, + EMPHATIC = 3, + SIMPLE = 4, + END = 5, +}; + struct PiPWindowSize { uint32_t width; uint32_t height; double scale; }; +/** + * @brief Enumerates floating ball window state. + */ +enum class FbWindowState : uint32_t { + STATE_UNDEFINED = 0, + STATE_STARTING = 1, + STATE_STARTED = 2, + STATE_STOPPING = 3, + STATE_STOPPED = 4, +}; + /** * @struct VsyncCallback * diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn index 10c02683f4..275c9d81c6 100644 --- a/interfaces/kits/napi/BUILD.gn +++ b/interfaces/kits/napi/BUILD.gn @@ -28,5 +28,6 @@ group("napi_packages") { "window_runtime:window_napi", "window_runtime:window_native_kit", "window_runtime:windowstage_kit", + "floating_ball_napi:floatingball_napi", ] } diff --git a/interfaces/kits/napi/floating_ball_napi/BUILD.gn b/interfaces/kits/napi/floating_ball_napi/BUILD.gn new file mode 100644 index 0000000000..b5a55f2af3 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2023-2023 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. + +import("//build/ohos.gni") +import("../../../../windowmanager_aafwk.gni") + +config("fb_config") { + visibility = [ ":*" ] + include_dirs = [ "../../../../wm/include" ] +} + +ohos_shared_library("floatingball_napi") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + sources = [ + "js_fb_window_manager.cpp", + "js_fbwindow_module.cpp", + "js_fb_window_controller.cpp", + "js_fb_utils.cpp", + "js_fb_window_listener.cpp", + ] + + configs = [ + ":fb_config", + "../../../../resources/config/build:coverage_flags", + ] + + deps = [ + "../../../../utils:libwmutil", + "../../../../utils:libwmutil_base", + "../../../../wm:libwm", + ] + + external_deps = [ + "ability_runtime:ability_context_native", + "ability_runtime:abilitykit_native", + "ability_runtime:runtime", + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + "image_framework:image", + ] + + relative_install_dir = "module" + part_name = "window_manager" + subsystem_name = "window" + + defines = [] + if (build_variant == "user") { + defines += [ "IS_RELEASE_VERSION" ] + } +} diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_utils.cpp b/interfaces/kits/napi/floating_ball_napi/js_fb_utils.cpp new file mode 100644 index 0000000000..0bd6a523c1 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_utils.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025-2025 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 "js_fb_utils.h" + +#include +#include "window.h" +#include "wm_common.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +napi_value NapiGetUndefined(napi_env env) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + return result; +} + +napi_value NapiThrowInvalidParam(napi_env env, std::string msg) +{ + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_FB_PARAM_INVALID), msg)); + return NapiGetUndefined(env); +} + +napi_valuetype GetType(napi_env env, napi_value value) +{ + napi_valuetype res = napi_undefined; + napi_typeof(env, value, &res); + return res; +} + +bool NapiIsCallable(napi_env env, napi_value value) +{ + bool result = false; + napi_is_callable(env, value, &result); + return result; +} + +static napi_status SetEnumProperty(napi_env env, napi_value& obj, const std::string& enumName, int32_t enumValue) +{ + napi_value value = nullptr; + napi_status ret = napi_create_int32(env, enumValue, &value); + if (ret != napi_ok) { + return ret; + } + ret = napi_set_named_property(env, obj, enumName.c_str(), value); + if (ret != napi_ok) { + return ret; + } + return ret; +} + +static napi_value ExportFloatingBallState(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_create_object(env, &result); + if (result == nullptr) { + TLOGE(WmsLogTag::DEFAULT, "Failed to get object"); + return nullptr; + } + (void)SetEnumProperty(env, result, "STARTED", static_cast(FloatingBallState::STARTED)); + (void)SetEnumProperty(env, result, "STOPPED", static_cast(FloatingBallState::STOPPED)); + napi_object_freeze(env, result); + return result; +} + +static napi_value ExportFloatingBallTemplate(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_create_object(env, &result); + if (result == nullptr) { + TLOGE(WmsLogTag::DEFAULT, "Failed to get object"); + return nullptr; + } + (void)SetEnumProperty(env, result, "STATIC", static_cast(FloatingBallTemplate::STATIC)); + (void)SetEnumProperty(env, result, "NORMAL", static_cast(FloatingBallTemplate::NORMAL)); + (void)SetEnumProperty(env, result, "EMPHATIC", static_cast(FloatingBallTemplate::EMPHATIC)); + (void)SetEnumProperty(env, result, "SIMPLE", static_cast(FloatingBallTemplate::SIMPLE)); + napi_object_freeze(env, result); + return result; +} + +napi_status InitFbEnums(napi_env env, napi_value exports) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_GETTER("FloatingBallState", ExportFloatingBallState), + DECLARE_NAPI_GETTER("FloatingBallTemplate", ExportFloatingBallTemplate), + }; + size_t count = sizeof(properties) / sizeof(napi_property_descriptor); + return napi_define_properties(env, exports, count, properties); +} + +} // Rosen +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_utils.h b/interfaces/kits/napi/floating_ball_napi/js_fb_utils.h new file mode 100644 index 0000000000..2ace6a3b25 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_utils.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025-2025 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. + */ + +#ifndef OHOS_JS_FB_UTILS_H +#define OHOS_JS_FB_UTILS_H + +#include "js_runtime_utils.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +napi_value NapiGetUndefined(napi_env env); +napi_value NapiThrowInvalidParam(napi_env env, std::string msg); +napi_valuetype GetType(napi_env env, napi_value value); +bool NapiIsCallable(napi_env env, napi_value value); +napi_status InitFbEnums(napi_env env, napi_value exports); +} +} +#endif //OHOS_JS_FB_UTILS_H diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.cpp b/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.cpp new file mode 100644 index 0000000000..0d6b912542 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.cpp @@ -0,0 +1,631 @@ +/* + * Copyright (c) 2025-2025 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 "js_fb_window_controller.h" +#include "window_manager_hilog.h" +#include "floating_ball_manager.h" +#include "js_fb_utils.h" +#include "pixel_map_napi.h" +#include "napi_common_want.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + const std::string STATE_CHANGE_CB = "stateChange"; + const std::string CLICK_EVENT = "clickEvent"; + const uint32_t TITLE_MAX_LEN = 128; + const uint32_t CONTENT_MAX_LEN = 128; + const int32_t PIXEL_MAP_MAX_SIZE = 512 * 1024; +} + +void BindFunctions(napi_env env, napi_value object, const char* moduleName) +{ + BindNativeFunction(env, object, "startFloatingBall", moduleName, JsFbController::StartFloatingBall); + BindNativeFunction(env, object, "updateFloatingBall", moduleName, JsFbController::UpdateFloatingBall); + BindNativeFunction(env, object, "stopFloatingBall", moduleName, JsFbController::StopFloatingBall); + BindNativeFunction(env, object, "restoreMainWindow", moduleName, JsFbController::RestoreMainWindow); + BindNativeFunction(env, object, "on", moduleName, JsFbController::RegisterCallback); + BindNativeFunction(env, object, "off", moduleName, JsFbController::UnregisterCallback); + BindNativeFunction(env, object, "getFloatingBallWindowInfo", moduleName, JsFbController::GetFloatingBallWindowInfo); +} + +napi_value CreateJsFbControllerObject(napi_env env, sptr& fbController) +{ + napi_value objValue = nullptr; + napi_status status = napi_create_object(env, &objValue); + if (status != napi_ok || objValue == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "failed to create js obj, error:%{public}d", status); + return NapiGetUndefined(env); + } + + TLOGI(WmsLogTag::WMS_SYSTEM, "CreateJsFbController"); + std::unique_ptr jsFbController = std::make_unique(fbController); + napi_wrap(env, objValue, jsFbController.release(), JsFbController::Finalizer, nullptr, nullptr); + + BindFunctions(env, objValue, "JsFbController"); + return objValue; +} + +JsFbController::JsFbController(const sptr& fbController) + : fbController_(fbController) +{ +} + +JsFbController::~JsFbController() +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "JsFbController release"); +} + +void JsFbController::Finalizer(napi_env env, void* data, void* hint) +{ + TLOGD(WmsLogTag::WMS_SYSTEM, "Finalizer is called"); + std::unique_ptr(static_cast(data)); +} + +napi_value JsFbController::StartFloatingBall(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnStartFloatingBall(env, info) : nullptr; +} + +napi_value JsFbController::OnStartFloatingBall(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_SYSTEM, "OnStartFloatingBall [NAPI]"); + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { + return NapiThrowInvalidParam(env, "Missing args when start floating ball"); + } + + napi_value config = argv[0]; + if (config == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "config is null"); + return NapiThrowInvalidParam(env, + "Failed to convert object to FloatingBallOption or FloatingBallOption is null"); + } + + FbOption option; + if (GetFloatingBallOptionFromJs(env, config, option) == nullptr) { + return NapiGetUndefined(env); + } + + TLOGI(WmsLogTag::WMS_SYSTEM, "OnStartFloatingBall is called"); + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, option, task = napiAsyncTask, + weak = wptr(fbController_)]() { + auto fbController = weak.promote(); + if (fbController == nullptr) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_FB_STATE_ABNORMALLY), + "JsFbController::OnStartFloatingBall failed.")); + return; + } + sptr optionPtr = sptr::MakeSptr(option); + WMError errCode = fbController->StartFloatingBall(optionPtr); + if (errCode != WMError::WM_OK) { + task->Reject(env, CreateJsError(env, static_cast(WM_JS_TO_ERROR_CODE_MAP.at(errCode)), + "JsFbController::OnStartFloatingBall failed.")); + return; + } + task->Resolve(env, NapiGetUndefined(env)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_FB_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +napi_value JsFbController::UpdateFloatingBall(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnUpdateFloatingBall(env, info) : nullptr; +} + +napi_value JsFbController::OnUpdateFloatingBall(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "OnUpdateFloatingBall"); + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { + return NapiThrowInvalidParam(env, "Missing args when update floating ball"); + } + + napi_value config = argv[0]; + if (config == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "config is null"); + return NapiThrowInvalidParam(env, + "Failed to convert object to FloatingBallOption or FloatingBallOption is null"); + } + + FbOption option; + if (GetFloatingBallOptionFromJs(env, config, option) == nullptr) { + return NapiGetUndefined(env); + } + + TLOGI(WmsLogTag::WMS_SYSTEM, "OnUpdateFloatingBall is called"); + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, option, task = napiAsyncTask, + weak = wptr(fbController_)]() { + auto fbController = weak.promote(); + if (fbController == nullptr) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_FB_STATE_ABNORMALLY), + "JsFbController::OnUpdateFloatingBall failed.")); + return; + } + sptr optionPtr = sptr::MakeSptr(option); + WMError errCode = fbController->UpdateFloatingBall(optionPtr); + if (errCode != WMError::WM_OK) { + task->Reject(env, CreateJsError(env, static_cast(WM_JS_TO_ERROR_CODE_MAP.at(errCode)), + "JsFbController::OnUpdateFloatingBall failed.")); + return; + } + task->Resolve(env, NapiGetUndefined(env)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_FB_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +napi_value JsFbController::StopFloatingBall(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnStopFloatingBall(env, info) : nullptr; +} + +napi_value JsFbController::OnStopFloatingBall(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "OnStopFloatingBall"); + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, task = napiAsyncTask, + weak = wptr(fbController_)]() { + auto fbController = weak.promote(); + if (fbController == nullptr) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "JsFBController::OnStopFloatingBall failed.")); + return; + } + WMError errCode = fbController->StopFloatingBallFromClient(); + if (errCode != WMError::WM_OK) { + task->Reject(env, CreateJsError(env, static_cast(WM_JS_TO_ERROR_CODE_MAP.at(errCode)), + "JsFBController::OnStopFloatingBall failed.")); + return; + } + task->Resolve(env, NapiGetUndefined(env)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_PIP_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +napi_value JsFbController::RestoreMainWindow(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnRestoreAbility(env, info) : nullptr; +} + +napi_value JsFbController::OnRestoreAbility(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "OnRestoreAbility"); + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { + return NapiThrowInvalidParam(env, "Missing args when start ui ability"); + } + + napi_value wantValue = argv[0]; + if (wantValue == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "want is null"); + return NapiThrowInvalidParam(env, "want is null"); + } + + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantValue, want)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "unWrap want failed."); + return NapiThrowInvalidParam(env, "Incorrect parameter, parameter must be want."); + } + + std::shared_ptr abilityWant = std::make_shared(want); + + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, abilityWant, task = napiAsyncTask, + weak = wptr(fbController_)]() { + auto fbController = weak.promote(); + if (fbController == nullptr) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_FB_STATE_ABNORMALLY), + "JsFBController::OnRestoreMainWindow failed.")); + return; + } + WMError errCode = fbController->RestoreMainWindow(abilityWant); + if (errCode != WMError::WM_OK) { + task->Reject(env, CreateJsError(env, static_cast(WM_JS_TO_ERROR_CODE_MAP.at(errCode)), + "JsFBController::OnRestoreMainWindow failed.")); + return; + } + task->Resolve(env, NapiGetUndefined(env)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_PIP_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +napi_value JsFbController::GetFloatingBallOptionFromJs(napi_env env, napi_value optionObject, FbOption& option) +{ + napi_value templateValue = nullptr; + napi_value titleValue = nullptr; + napi_value contentValue = nullptr; + + uint32_t templateType = 0; + std::string title = ""; + std::string content = ""; + bool hasProperty = false; + napi_has_named_property(env, optionObject, "template", &hasProperty); + if (hasProperty) { + napi_get_named_property(env, optionObject, "template", &templateValue); + ConvertFromJsValue(env, templateValue, templateType); + option.SetTemplate(templateType); + } + napi_has_named_property(env, optionObject, "title", &hasProperty); + if (hasProperty) { + napi_get_named_property(env, optionObject, "title", &titleValue); + ConvertFromJsValue(env, titleValue, title); + option.SetTitle(title); + } + napi_has_named_property(env, optionObject, "content", &hasProperty); + if (hasProperty) { + napi_get_named_property(env, optionObject, "content", &contentValue); + ConvertFromJsValue(env, contentValue, content); + option.SetContent(content); + } + if (GetIcon(env, optionObject, option) == nullptr) { + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM), "Invalid icon object")); + return nullptr; + } + return CheckParams(env, option); +} + +napi_value JsFbController::CheckParams(const napi_env &env, FbOption& option) +{ + if (option.GetTemplate() < static_cast(FloatingBallTemplate::STATIC) || + option.GetTemplate() >= static_cast(FloatingBallTemplate::END)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "tempalte %{public}d is invalid.", option.GetTemplate()); + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM), "tempalte is invalid.")); + return nullptr; + } + if (option.GetTitle().length() > TITLE_MAX_LEN) { + TLOGE(WmsLogTag::WMS_SYSTEM, "title length Exceed the limit %{public}lu.", option.GetTitle().length()); + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM), "title length Exceed the limit")); + return nullptr; + } + if (option.GetContent().length() > CONTENT_MAX_LEN) { + TLOGE(WmsLogTag::WMS_SYSTEM, "content length Exceed the limit %{public}lu.", option.GetContent().length()); + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM), "content length Exceed the limit")); + return nullptr; + } + if (option.GetIcon() != nullptr && option.GetIcon()->GetByteCount() > PIXEL_MAP_MAX_SIZE) { + TLOGE(WmsLogTag::WMS_SYSTEM, "icon size Exceed the limit %{public}d.", option.GetIcon()->GetByteCount()); + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM), "icon size Exceed the limit")); + return nullptr; + } + return NapiGetUndefined(env); +} + +napi_value JsFbController::GetIcon(const napi_env &env, const napi_value &value, FbOption& option) +{ + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + bool hasProperty = false; + + napi_has_named_property(env, value, "icon", &hasProperty); + if (hasProperty) { + napi_get_named_property(env, value, "icon", &result); + napi_typeof(env, result, &valuetype); + if (valuetype != napi_object) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Wrong argument type. Object expected."); + return nullptr; + } + std::shared_ptr pixelMap = nullptr; + pixelMap = Media::PixelMapNapi::GetPixelMap(env, result); + if (pixelMap == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Invalid object pixelMap"); + return nullptr; + } + option.SetIcon(pixelMap); + } + return NapiGetUndefined(env); +} + +napi_value JsFbController::RegisterCallback(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnRegisterCallback(env, info) : nullptr; +} + +napi_value JsFbController::OnRegisterCallback(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "OnRegisterCallback is called"); + size_t argc = 2; + napi_value argv[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 2) { + TLOGE(WmsLogTag::WMS_SYSTEM, "OnRegisterCallback Params not match: %{public}zu", argc); + return NapiThrowInvalidParam(env, "OnRegisterCallback Params not match"); + } + std::string cbType = ""; + if (!ConvertFromJsValue(env, argv[0], cbType)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to convert parameter to callbackType"); + return NapiThrowInvalidParam(env, "Failed to convert parameter to callbackType"); + } + napi_value value = argv[1]; + if (value == nullptr || !NapiIsCallable(env, value)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Callback is nullptr or not callable"); + return NapiThrowInvalidParam(env, "Callback is nullptr or not callable"); + } + WmErrorCode ret = RegisterListenerWithType(env, cbType, value); + if (ret != WmErrorCode::WM_OK) { + TLOGE(WmsLogTag::WMS_SYSTEM, "OnRegisterCallback failed"); + return NapiThrowInvalidParam(env, "OnRegisterCallback failed"); + } + return NapiGetUndefined(env); +} + +WmErrorCode JsFbController::RegisterListenerWithType(napi_env env, const std::string& type, napi_value value) +{ + std::lock_guard lock(callbBackMutex_); + if (IfCallbackRegistered(env, type, value)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Callback already registered!"); + return WmErrorCode::WM_ERROR_INVALID_CALLING; + } + std::shared_ptr callbackRef; + napi_ref result = nullptr; + napi_create_reference(env, value, 1, &result); + callbackRef.reset(reinterpret_cast(result)); + auto fbWindowListener = sptr::MakeSptr(env, callbackRef); + if (fbWindowListener == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "New JsFbWindowListener failed"); + return WmErrorCode::WM_ERROR_STATE_ABNORMALLY; + } + jsCbMap_[type].insert(fbWindowListener); + + if (type == STATE_CHANGE_CB) { + ProcessStateChangeRegister(fbWindowListener); + } + if (type == CLICK_EVENT) { + ProcessClickEventRegister(fbWindowListener); + } + TLOGI(WmsLogTag::WMS_SYSTEM, "Register type %{public}s success! callback map size: %{public}zu", + type.c_str(), jsCbMap_[type].size()); + return WmErrorCode::WM_OK; +} + +bool JsFbController::IfCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + TLOGI(WmsLogTag::WMS_SYSTEM, "methodName %{public}s not registered!", type.c_str()); + return false; + } + for (auto& listener : jsCbMap_[type]) { + bool isEquals = false; + napi_strict_equals(env, jsListenerObject, listener->GetCallbackRef()->GetNapiValue(), &isEquals); + if (isEquals) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Callback already registered!"); + return true; + } + } + return false; +} + +void JsFbController::ProcessStateChangeRegister(const sptr& listener) +{ + if (fbController_ == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "controller is nullptr"); + return; + } + sptr thisListener(listener); + fbController_->RegisterFbLifecycle(thisListener); +} + +void JsFbController::ProcessClickEventRegister(const sptr& listener) +{ + if (fbController_ == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "controller is nullptr"); + return; + } + sptr thisListener(listener); + fbController_->RegisterFbClickObserver(thisListener); +} + +napi_value JsFbController::UnregisterCallback(napi_env env, napi_callback_info info) +{ + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnUnregisterCallback(env, info) : nullptr; +} + +napi_value JsFbController::OnUnregisterCallback(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value argv[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc == 0 || argc > 2) { + TLOGE(WmsLogTag::WMS_SYSTEM, "JsFbController Params not match: %{public}zu", argc); + return NapiThrowInvalidParam(env, "Params num not match"); + } + std::string cbType = ""; + if (!ConvertFromJsValue(env, argv[0], cbType)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to convert parameter to string"); + return NapiThrowInvalidParam(env, "Failed to convert parameter to string"); + } + if (argc == 1) { + UnRegisterListenerWithType(env, cbType, nullptr); + return NapiGetUndefined(env); + } + napi_value value = argv[1]; + if (value != nullptr && NapiIsCallable(env, value)) { + UnRegisterListenerWithType(env, cbType, value); + } + return NapiGetUndefined(env); +} + +WmErrorCode JsFbController::UnRegisterListenerWithType(napi_env env, const std::string& type, napi_value value) +{ + std::lock_guard lock(callbBackMutex_); + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + TLOGI(WmsLogTag::WMS_SYSTEM, "methodName %{public}s not registered!", type.c_str()); + return WmErrorCode::WM_ERROR_INVALID_CALLING; + } + + if (value == nullptr) { + TLOGI(WmsLogTag::WMS_SYSTEM, "methodName %{public}s start unregister all callback!", type.c_str()); + for (auto& listener : jsCbMap_[type]) { + WmErrorCode ret = UnRegisterListener(type, listener); + if (ret != WmErrorCode::WM_OK) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Unregister type %{public}s failed, no value", type.c_str()); + return ret; + } + } + jsCbMap_.erase(type); + } else { + TLOGI(WmsLogTag::WMS_SYSTEM, "methodName %{public}s start unregister one callback!", type.c_str()); + bool foundCallbackValue = false; + for (auto& listener : jsCbMap_[type]) { + bool isEquals = false; + napi_strict_equals(env, value, listener->GetCallbackRef()->GetNapiValue(), &isEquals); + if (!isEquals) { + continue; + } + foundCallbackValue = true; + WmErrorCode ret = UnRegisterListener(type, listener); + if (ret != WmErrorCode::WM_OK) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Unregister type %{public}s failed", type.c_str()); + return ret; + } + jsCbMap_[type].erase(listener); + break; + } + if (!foundCallbackValue) { + TLOGW(WmsLogTag::WMS_SYSTEM, "Unregister type %{public}s failed because not found callback!", type.c_str()); + return WmErrorCode::WM_OK; + } + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); + } + } + TLOGI(WmsLogTag::WMS_SYSTEM, "Unregister type %{public}s success!", type.c_str()); + return WmErrorCode::WM_OK; +} + +WmErrorCode JsFbController::UnRegisterListener(const std::string& type, + const sptr& fbWindowListener) +{ + if (type == STATE_CHANGE_CB) { + ProcessStateChangeUnRegister(fbWindowListener); + } + if (type == CLICK_EVENT) { + ProcessClickEventUnRegister(fbWindowListener); + } + return WmErrorCode::WM_OK; +} + +void JsFbController::ProcessStateChangeUnRegister(const sptr& listener) +{ + if (fbController_ == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "controller is nullptr"); + return; + } + sptr thisListener(listener); + fbController_->UnRegisterFbLifecycle(thisListener); +} + +void JsFbController::ProcessClickEventUnRegister(const sptr& listener) +{ + if (fbController_ == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "controller is nullptr"); + return; + } + sptr thisListener(listener); + fbController_->UnRegisterFbClickObserver(thisListener); +} + +napi_value JsFbController::GetFloatingBallWindowInfo(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "GetFloatingBallWindowInfo start!"); + JsFbController* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnGetFloatingBallWindowInfo(env, info) : nullptr; +} + +napi_value CreateJsFbWindowInfoObject(napi_env env, uint32_t windowId) +{ + napi_value objValue = nullptr; + napi_status status = napi_create_object(env, &objValue); + if (status != napi_ok || objValue == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "failed to create js obj, error:%{public}d", status); + return NapiGetUndefined(env); + } + TLOGI(WmsLogTag::WMS_SYSTEM, "CreateJsFbWindowInfo"); + std::unique_ptr fbWindowInfo = std::make_unique(windowId); + napi_wrap(env, objValue, fbWindowInfo.release(), FbWindowInfo::Finalizer, nullptr, nullptr); + return objValue; +} + +napi_value JsFbController::OnGetFloatingBallWindowInfo(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_SYSTEM, "NAPI OnGetFloatingBallWindowInfo"); + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, task = napiAsyncTask, + weak = wptr(fbController_)]() { + auto fbController = weak.promote(); + if (fbController == nullptr) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_FB_INTERNAL_ERROR), + "JsFBController::OnGetFloatingBallWindowInfo failed.")); + return; + } + uint32_t windowId = 0; + auto ret = fbController->GetFloatingBallWindowInfo(windowId); + if (ret != WMError::WM_OK) { + task->Reject(env, CreateJsError(env, static_cast(WmErrorCode::WM_ERROR_FB_INTERNAL_ERROR), + "JsFBController::OnGetFloatingBallWindowInfo failed.")); + return; + } + task->Resolve(env, CreateJsFbWindowInfoObject(env, windowId)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_FB_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.h b/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.h new file mode 100644 index 0000000000..912e592ea2 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_controller.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025-2025 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. + */ + +#ifndef OHOS_JS_FB_CONTROLLER_H +#define OHOS_JS_FB_CONTROLLER_H + +#include +#include +#include "floating_ball_controller.h" +#include "wm_common.h" +#include "js_fb_window_listener.h" + +namespace OHOS { +namespace Rosen { +napi_value CreateJsFbControllerObject(napi_env env, sptr& floatingController); +class JsFbController { +public: + explicit JsFbController(const sptr& floatingController); + ~JsFbController(); + static void Finalizer(napi_env env, void* data, void* hint); + static napi_value StartFloatingBall(napi_env env, napi_callback_info info); + static napi_value StopFloatingBall(napi_env env, napi_callback_info info); + static napi_value RestoreMainWindow(napi_env env, napi_callback_info info); + static napi_value UpdateFloatingBall(napi_env env, napi_callback_info info); + static napi_value RegisterCallback(napi_env env, napi_callback_info info); + static napi_value UnregisterCallback(napi_env env, napi_callback_info info); + static napi_value GetFloatingBallWindowInfo(napi_env env, napi_callback_info info); + +private: + napi_value OnStartFloatingBall(napi_env env, napi_callback_info info); + napi_value OnUpdateFloatingBall(napi_env env, napi_callback_info info); + napi_value OnStopFloatingBall(napi_env env, napi_callback_info info); + napi_value OnRestoreAbility(napi_env env, napi_callback_info info); + + napi_value OnRegisterCallback(napi_env env, napi_callback_info info); + napi_value OnUnregisterCallback(napi_env env, napi_callback_info info); + + napi_value OnGetFloatingBallWindowInfo(napi_env env, napi_callback_info info); + + bool IfCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject); + WmErrorCode RegisterListenerWithType(napi_env env, const std::string& type, napi_value value); + WmErrorCode UnRegisterListenerWithType(napi_env env, const std::string& type, napi_value value); + WmErrorCode UnRegisterListener(const std::string& type, const sptr& fbWindowListener); + + void ProcessStateChangeRegister(const sptr& listener); + void ProcessClickEventRegister(const sptr& listener); + void ProcessStateChangeUnRegister(const sptr& listener); + void ProcessClickEventUnRegister(const sptr& listener); + + + sptr fbController_ = nullptr; + napi_value GetFloatingBallOptionFromJs(napi_env env, napi_value optionObject, FbOption& option); + napi_value CheckParams(const napi_env &env, FbOption& option); + napi_value GetIcon(const napi_env &env, const napi_value &value, FbOption& option); + std::unordered_map>> jsCbMap_; + std::mutex callbBackMutex_; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // OHOS_JS_FB_CONTROLLER_H diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.cpp b/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.cpp new file mode 100644 index 0000000000..298c900f63 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025-2025 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 "js_fb_window_listener.h" + +#include "js_fb_window_controller.h" +#include "window_manager_hilog.h" +#include "floating_ball_manager.h" +#include "js_fb_utils.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; + +static napi_value CallJsFunction(napi_env env, napi_value method, napi_value const * argv, size_t argc) +{ + if (env == nullptr || method == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "env nullptr or method is nullptr"); + return nullptr; + } + napi_value result = nullptr; + napi_value callResult = nullptr; + napi_get_undefined(env, &result); + napi_get_undefined(env, &callResult); + napi_call_function(env, result, method, argc, argv, &callResult); + TLOGD(WmsLogTag::WMS_SYSTEM, "called."); + return callResult; +} + +JsFbWindowListener::~JsFbWindowListener() +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "~JsWindowListener"); +} + +std::shared_ptr JsFbWindowListener::GetCallbackRef() const +{ + return jsCallBack_; +} + +void JsFbWindowListener::OnFloatingBallStart() +{ + OnFbListenerCallback(FloatingBallState::STARTED, 0); +} + +void JsFbWindowListener::OnFloatingBallStop() +{ + OnFbListenerCallback(FloatingBallState::STOPPED, 0); +} + +void JsFbWindowListener::OnFbListenerCallback(const FloatingBallState& state, const int32_t& errorCode) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "state: %{public}d", static_cast(state)); + auto napiTask = [jsCallback = jsCallBack_, state, errorCode, env = env_]() { + napi_value argv[] = {CreateJsValue(env, static_cast(state)), CreateJsValue(env, errorCode)}; + CallJsFunction(env, jsCallback->GetNapiValue(), argv, ArraySize(argv)); + }; + if (env_ != nullptr) { + napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate); + if (ret != napi_status::napi_ok) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to SendEvent"); + } + } else { + TLOGE(WmsLogTag::WMS_SYSTEM, "env is nullptr"); + } +} + +void JsFbWindowListener::OnClickEvent() +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "called, clickEvent"); + auto napiTask = [jsCallback = jsCallBack_, env = env_]() { + CallJsFunction(env, jsCallback->GetNapiValue(), {}, 0); + }; + if (env_ != nullptr) { + napi_status ret = napi_send_event(env_, napiTask, napi_eprio_immediate); + if (ret != napi_status::napi_ok) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to SendEvent"); + } + } else { + TLOGE(WmsLogTag::WMS_SYSTEM, "env is nullptr"); + } +} + +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.h b/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.h new file mode 100644 index 0000000000..e38fe14f3c --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_listener.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025-2025 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. + */ + +#ifndef OHOS_JS_FB_WINDOW_LISTENER_H +#define OHOS_JS_FB_WINDOW_LISTENER_H + +#include "native_engine/native_value.h" +#include "floating_ball_interface.h" +#include "refbase.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class JsFbWindowListener : public IFbLifeCycle, + public IFbClickObserver { +public: + JsFbWindowListener(napi_env env, const std::shared_ptr& callback) + : env_(env), jsCallBack_(callback) {} + ~JsFbWindowListener() override; + std::shared_ptr GetCallbackRef() const; + void OnFloatingBallStart() override; + void OnFloatingBallStop() override; + + void OnClickEvent() override; + +private: + void OnFbListenerCallback(const FloatingBallState& state, const int32_t& errorCode); + napi_env env_ = nullptr; + std::shared_ptr jsCallBack_ = nullptr; +}; +} // namespace Rosen +} // namespace OHOS +#endif /* OHOS_JS_FB_WINDOW_LISTENER_H */ diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.cpp b/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.cpp new file mode 100644 index 0000000000..6fa84b9774 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2025-2025 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 "js_fb_window_manager.h" +#include "js_fb_utils.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "floating_ball_controller.h" +#include "js_fb_window_controller.h" +#include "floating_ball_manager.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; + +JsFbWindowManager::JsFbWindowManager() +{ +} + +JsFbWindowManager::~JsFbWindowManager() +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "JsFbWindowManager release"); +} + +napi_value JsFbWindowManager::CreateFbController(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "JsFbWindowManagerInit create"); + JsFbWindowManager* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnCreateFbController(env, info) : nullptr; +} + +napi_value JsFbWindowManager::OnCreateFbController(napi_env env, napi_callback_info info) +{ + if (!FloatingBallManager::IsPhoneOrPad()) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Device is not phone or pad, do not support floating ball"); + napi_throw(env, AbilityRuntime::CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT), + "Device is not phone or pad, do not support floating ball")); + return NapiGetUndefined(env); + } + size_t argc = 1; + napi_value argv[1] = {nullptr}; + // 解析应用传参FloatingBallConfiguration对象 + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { + return NapiThrowInvalidParam(env, "Missing args when creating fbController"); + } + + napi_value config = argv[0]; + if (config == nullptr) { + return NapiThrowInvalidParam(env, "Failed to convert object to fbConfiguration or fbConfiguration is null"); + } + + napi_value contextPtrValue = nullptr; + napi_get_named_property(env, config, "context", &contextPtrValue); + void* contextPtr = nullptr; + napi_unwrap(env, contextPtrValue, &contextPtr); + return NapiSendTask(env, contextPtr); +} + +napi_value JsFbWindowManager::NapiSendTask(napi_env env, void* contextPtr) +{ + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [this, env, task = napiAsyncTask, contextPtr]() mutable { + auto context = static_cast*>(contextPtr); + if (context == nullptr) { + task->Reject(env, CreateJsError(env, static_cast( + WMError::WM_ERROR_FB_INTERNAL_ERROR), "Invalid context")); + return; + } + sptr mainWindow = Window::GetMainWindowWithContext(context->lock()); + if (mainWindow == nullptr) { + task->Reject(env, CreateJsError(env, static_cast( + WMError::WM_ERROR_FB_INTERNAL_ERROR), "Invalid mainWindow")); + return; + } + sptr fbController = sptr::MakeSptr(mainWindow, + mainWindow->GetWindowId(), contextPtr); + task->Resolve(env, CreateJsFbControllerObject(env, fbController)); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_immediate)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WMError::WM_ERROR_FB_INTERNAL_ERROR), "Send event failed")); + } + return result; +} + +void JsFbWindowManager::Finalizer(napi_env env, void* data, void* hint) +{ + std::unique_ptr(static_cast(data)); +} + +napi_value JsFbWindowManager::IsFbEnabled(napi_env env, napi_callback_info info) +{ + JsFbWindowManager* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnIsFbEnabled(env, info) : nullptr; +} + +napi_value JsFbWindowManager::OnIsFbEnabled(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_SYSTEM, "OnIsFbEnabled called"); + bool isPhoneOrPad = FloatingBallManager::IsPhoneOrPad(); + return CreateJsValue(env, isPhoneOrPad); +} + +napi_value JsFbWindowManagerInit(napi_env env, napi_value exportObj) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "JsFbWindowManagerInit"); + if (env == nullptr || exportObj == nullptr) { + TLOGI(WmsLogTag::WMS_SYSTEM, "JsFbWindowManagerInit env or exportObj is nullptr"); + return nullptr; + } + std::unique_ptr jsFbManager = std::make_unique(); + napi_wrap(env, exportObj, jsFbManager.release(), JsFbWindowManager::Finalizer, nullptr, nullptr); + const char* moduleName = "FloatingBall"; + BindNativeFunction(env, exportObj, "create", moduleName, JsFbWindowManager::CreateFbController); + BindNativeFunction(env, exportObj, "isFloatingBallEnabled", moduleName, JsFbWindowManager::IsFbEnabled); + InitFbEnums(env, exportObj); + return NapiGetUndefined(env); +} +} +} \ No newline at end of file diff --git a/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.h b/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.h new file mode 100644 index 0000000000..d1e6a63203 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fb_window_manager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2025 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. + */ +#ifndef OHOS_JS_FB_WINDOW_MANAGER_H +#define OHOS_JS_FB_WINDOW_MANAGER_H + +#include "js_runtime_utils.h" + +namespace OHOS { +namespace Rosen { +napi_value JsFbWindowManagerInit(napi_env env, napi_value exportObj); +class JsFbWindowManager { +public: + JsFbWindowManager(); + ~JsFbWindowManager(); + static napi_value CreateFbController(napi_env env, napi_callback_info info); + static void Finalizer(napi_env env, void* data, void* hint); + static napi_value IsFbEnabled(napi_env env, napi_callback_info info); +private: + napi_value OnCreateFbController(napi_env env, napi_callback_info info); + napi_value NapiSendTask(napi_env env, void* contextPtr); + napi_value OnIsFbEnabled(napi_env env, napi_callback_info info); +}; +} +} +#endif // OHOS_JS_FB_WINDOW_MANAGER_H \ No newline at end of file diff --git a/interfaces/kits/napi/floating_ball_napi/js_fbwindow_module.cpp b/interfaces/kits/napi/floating_ball_napi/js_fbwindow_module.cpp new file mode 100644 index 0000000000..761650ff15 --- /dev/null +++ b/interfaces/kits/napi/floating_ball_napi/js_fbwindow_module.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025-2025 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 "native_engine/native_engine.h" +#include "js_fb_window_manager.h" + +static napi_module g_winManagerModule = { + .nm_filename = nullptr, + .nm_register_func = OHOS::Rosen::JsFbWindowManagerInit, + .nm_modname = "FloatingBall", +}; + +extern "C" __attribute__((constructor)) void NapiApplicationFbWindowAutoRegister() +{ + napi_module_register(&g_winManagerModule); +} \ No newline at end of file diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h b/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h index ab54c9fa5a..041343695d 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h @@ -92,6 +92,7 @@ enum class ApiWindowType : uint32_t { TYPE_FLOAT_NAVIGATION, TYPE_DYNAMIC, TYPE_MUTISCREEN_COLLABORATION, + TYPE_FB, TYPE_END }; @@ -135,6 +136,7 @@ const std::map NATIVE_JS_TO_WINDOW_TYPE_MAP { { WindowType::WINDOW_TYPE_FLOAT_NAVIGATION, ApiWindowType::TYPE_FLOAT_NAVIGATION }, { WindowType::WINDOW_TYPE_DYNAMIC, ApiWindowType::TYPE_DYNAMIC }, { WindowType::WINDOW_TYPE_MUTISCREEN_COLLABORATION, ApiWindowType::TYPE_MUTISCREEN_COLLABORATION }, + { WindowType::WINDOW_TYPE_FB, ApiWindowType::TYPE_FB }, }; const std::map JS_TO_NATIVE_WINDOW_TYPE_MAP { @@ -165,6 +167,7 @@ const std::map JS_TO_NATIVE_WINDOW_TYPE_MAP { { ApiWindowType::TYPE_FLOAT_NAVIGATION, WindowType::WINDOW_TYPE_FLOAT_NAVIGATION }, { ApiWindowType::TYPE_DYNAMIC, WindowType::WINDOW_TYPE_DYNAMIC }, { ApiWindowType::TYPE_MUTISCREEN_COLLABORATION, WindowType::WINDOW_TYPE_MUTISCREEN_COLLABORATION }, + { ApiWindowType::WINDOW_TYPE_FB, WindowType::WINDOW_TYPE_FB }, }; enum class ApiWindowMode : uint32_t { diff --git a/previewer/include/wm_common.h b/previewer/include/wm_common.h index fd2ef79aaa..60ff474c89 100644 --- a/previewer/include/wm_common.h +++ b/previewer/include/wm_common.h @@ -124,6 +124,7 @@ enum class WindowType : uint32_t { WINDOW_TYPE_DYNAMIC, WINDOW_TYPE_MAGNIFICATION, WINDOW_TYPE_MAGNIFICATION_MENU, + WINDOW_TYPE_FB, ABOVE_APP_SYSTEM_WINDOW_END, SYSTEM_SUB_WINDOW_BASE = 2500, @@ -168,11 +169,13 @@ enum WindowModeSupport : uint32_t { WINDOW_MODE_SUPPORT_SPLIT_PRIMARY = 1 << 2, WINDOW_MODE_SUPPORT_SPLIT_SECONDARY = 1 << 3, WINDOW_MODE_SUPPORT_PIP = 1 << 4, + WINDOW_MODE_SUPPORT_FB = 1 << 5, WINDOW_MODE_SUPPORT_ALL = WINDOW_MODE_SUPPORT_FLOATING | WINDOW_MODE_SUPPORT_FULLSCREEN | WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | WINDOW_MODE_SUPPORT_SPLIT_SECONDARY | - WINDOW_MODE_SUPPORT_PIP + WINDOW_MODE_SUPPORT_PIP | + WINDOW_MODE_SUPPORT_FB }; /** @@ -184,7 +187,8 @@ enum class WindowMode : uint32_t { WINDOW_MODE_SPLIT_PRIMARY = 100, WINDOW_MODE_SPLIT_SECONDARY, WINDOW_MODE_FLOATING, - WINDOW_MODE_PIP + WINDOW_MODE_PIP, + WINDOW_MODE_FB }; /** @@ -256,6 +260,14 @@ enum class WMError : int32_t { WM_ERROR_ILLEGAL_PARAM, WM_ERROR_FILTER_ERROR, WM_ERROR_TIMEOUT, + WM_ERROR_FB_PARAM_INVALID, + WM_ERROR_FB_CREATE_FAILED, + WM_ERROR_FB_REPEAT_CONTROLLER, + WM_ERROR_FB_REPEAT_OPERATION, + WM_ERROR_FB_INTERNAL_ERROR, + WM_ERROR_FB_STATE_ABNORMALLY, + WM_ERROR_FB_INVALID_STATE, + WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED, }; /** @@ -286,6 +298,14 @@ enum class WmErrorCode : int32_t { WM_ERROR_ILLEGAL_PARAM = 1300016, WM_ERROR_FILTER_ERROR = 1300017, WM_ERROR_TIMEOUT = 1300018, + WM_ERROR_FB_PARAM_INVALID = 1300019, + WM_ERROR_FB_CREATE_FAILED = 1300020, + WM_ERROR_FB_REPEAT_CONTROLLER = 1300021, + WM_ERROR_FB_REPEAT_OPERATION = 1300022, + WM_ERROR_FB_INTERNAL_ERROR = 1300023, + WM_ERROR_FB_STATE_ABNORMALLY = 1300024, + WM_ERROR_FB_INVALID_STATE = 1300025, + WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED = 1300026, }; /** diff --git a/test/fuzztest/wms/BUILD.gn b/test/fuzztest/wms/BUILD.gn index 11837d14f9..3e9e215470 100644 --- a/test/fuzztest/wms/BUILD.gn +++ b/test/fuzztest/wms/BUILD.gn @@ -15,6 +15,7 @@ group("fuzztest") { testonly = true deps = [ + "fb_fuzzer:fuzztest", "pip_fuzzer:fuzztest", "window_fuzzer:fuzztest", "windowagent_fuzzer:fuzztest", diff --git a/test/fuzztest/wms/fb_fuzzer/BUILD.gn b/test/fuzztest/wms/fb_fuzzer/BUILD.gn new file mode 100644 index 0000000000..7f8be90a6b --- /dev/null +++ b/test/fuzztest/wms/fb_fuzzer/BUILD.gn @@ -0,0 +1,83 @@ +# Copyright (c) 2023 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. + +import("//build/config/features.gni") +import("//build/test.gni") +import("../../../../windowmanager_aafwk.gni") + +module_output_path = "window_manager/window_manager" + +##############################fuzztest########################################## +ohos_fuzztest("FbFuzzTest") { + fuzz_config_file = "." + module_out_path = module_output_path + include_dirs = [ + "../../../../wm/include", + "../../../../dm/include", + "../../../../wmserver/include", + "../../../../interfaces/innerkits/dm", + "../../../../extension/extension_connection/include", + "../../../../interfaces/innerkits/extension", + "../../../../utils/include", + ] + + configs = [ + "../..:configs_cc_ld", + "../../../../resources/config/build:coverage_flags", + "../../../../resources/config/build:testcase_flags", + ] + + sources = [ "fb_fuzzer.cpp" ] + deps = [ + "${window_base_path}/dm:libdm", + "${window_base_path}/utils:libwmutil", + "${window_base_path}/utils:libwmutil_base", + "${window_base_path}/wm:libwm", + ] + + external_deps = [ + "ability_base:base", + "ability_base:configuration", + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:napi_base_context", + "ability_runtime:runtime", + "ace_engine:ace_uicontent", + "ace_engine:ace_xcomponent_controller", + "c_utils:utils", + "eventhandler:libeventhandler", + "graphic_2d:librender_service_client", + "graphic_2d:window_animation", + "hilog:libhilog", + "image_framework:image_native", + "input:libmmi-client", + "ipc:ipc_single", + "napi:ace_napi", + "window_manager:libwindow_extension_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":FbFuzzTest", + ] +} +############################################################################### diff --git a/test/fuzztest/wms/fb_fuzzer/corpus/init b/test/fuzztest/wms/fb_fuzzer/corpus/init new file mode 100644 index 0000000000..ba919ab968 --- /dev/null +++ b/test/fuzztest/wms/fb_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2023 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. + +FBFUZZTEST \ No newline at end of file diff --git a/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.cpp b/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.cpp new file mode 100644 index 0000000000..7d99cadd86 --- /dev/null +++ b/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023 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 "marshalling_helper.h" +#include +#include +#include "ability_context.h" +#include "ability_context_impl.h" +#include "fb_fuzzer.h" +#include "floating_ball_controller.h" +#include "floating_ball_manager.h" +#include "floating_ball_option.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { +constexpr size_t DATA_MIN_SIZE = 2; +constexpr size_t DATA_MAX_SIZE = 1024; +} + +template +size_t GetObject(T& object, const uint8_t* data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +/* 调用该接口后, 需要释放内存 */ +char *CopyDataToString(const uint8_t* data, size_t size) +{ + if (size > DATA_MAX_SIZE) { + return nullptr; + } + char *string = (char *)malloc(size); + if (string == nullptr) { + std::cout << "malloc failed." << std::endl; + return nullptr; + } + + if (memcpy_s(string, size, data, size) != EOK) { + std::cout << "copy failed." << std::endl; + free(string); + return nullptr; + } + return string; +} + +void CheckFbControllerFunctionsPart(sptr controller, const uint8_t* data, size_t size) +{ + if (data == nullptr || (size < DATA_MIN_SIZE || size > DATA_MAX_SIZE)) { + return; + } + + auto fbLifeCycleListener = sptr::MakeSptr(); + controller->RegisterFbLifecycle(fbLifeCycleListener); + controller->UnRegisterFbLifecycle(fbLifeCycleListener); + + auto fbClickObserverListener = sptr::MakeSptr(); + controller->RegisterFbClickObserver(fbClickObserverListener); + controller->UnRegisterFbClickObserver(fbClickObserverListener); + + std::shared_ptr want = nullptr; + controller->RestoreMainWindow(want); + + want = std::make_shared(); + std::stringstream ss; + for (size_t i = 0; i < size; ++i) { + ss << data[i]; + } + want->SetParam("__startParams", ss.str()); + controller->RestoreMainWindow(want); +} + +bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + size_t startPos = 0; + + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + sptr window = new Window(); + sptr controller = new FloatingBallController(window, windowId, nullptr); + if (controller == nullptr) { + return false; + } + + sptr option = new FbOption(); + + std::string title = ""; + std::string content = ""; + option->SetTitle(title); + option->SetContent(content); + std::shared_ptr pixelMap = nullptr; + option->SetIcon(pixelMap); + + void* contextPtr = nullptr; + controller->contextPtr_ = contextPtr; + controller->CreateFloatingBallWindow(); + + controller->StartFloatingBall(option); + + uint16_t strlen = 10; + char* str = CopyDataToString(data, strlen); + startPos += strlen; + title.assign(str); + free(str); + controller->UpdateFloatingBall(option); + + CheckFbControllerFunctionsPart(controller, data + startPos, size - startPos); + controller->DestroyFloatingBallWindow(); + return true; +} + +void FloatingBallManagerFuzzTest(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + + sptr window = new Window(); + sptr controller = new FloatingBallController(window, windowId, nullptr); + + FloatingBallManager::IsActiveController(controller); + FloatingBallManager::SetActiveController(controller); + FloatingBallManager::RemoveActiveController(controller); +} + +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + OHOS::FloatingBallManagerFuzzTest(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.h b/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.h new file mode 100644 index 0000000000..6b44af69c7 --- /dev/null +++ b/test/fuzztest/wms/fb_fuzzer/fb_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef TEST_FUZZTEST_FB_FUZZER_H +#define TEST_FUZZTEST_FB_FUZZER_H + +#define FUZZ_PROJECT_NAME "fb_fuzzer" + +#endif \ No newline at end of file diff --git a/test/fuzztest/wms/fb_fuzzer/project.xml b/test/fuzztest/wms/fb_fuzzer/project.xml new file mode 100644 index 0000000000..4fdbc407f2 --- /dev/null +++ b/test/fuzztest/wms/fb_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index e0856a9894..aca4faaccd 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -108,6 +108,11 @@ public: return (type == WindowType::WINDOW_TYPE_PIP); } + static inline bool IsFbWindow(WindowType type) + { + return (type == WindowType::WINDOW_TYPE_FB); + } + static inline bool IsBelowSystemWindow(WindowType type) { return (type >= WindowType::BELOW_APP_SYSTEM_WINDOW_BASE && type < WindowType::BELOW_APP_SYSTEM_WINDOW_END); @@ -215,7 +220,7 @@ public: { return mode == WindowMode::WINDOW_MODE_FULLSCREEN || mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || mode == WindowMode::WINDOW_MODE_FLOATING || - mode == WindowMode::WINDOW_MODE_PIP; + mode == WindowMode::WINDOW_MODE_PIP || mode == WindowMode::WINDOW_MODE_FB; } static inline bool IsEmptyRect(const Rect& r) @@ -261,6 +266,8 @@ public: return WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY & windowModeSupportType; case WindowMode::WINDOW_MODE_PIP: return WindowModeSupport::WINDOW_MODE_SUPPORT_PIP & windowModeSupportType; + case WindowMode::WINDOW_MODE_FB: + return WindowModeSupport::WINDOW_MODE_SUPPORT_FB & windowModeSupportType; case WindowMode::WINDOW_MODE_UNDEFINED: return false; default: @@ -284,6 +291,8 @@ public: return WindowMode::WINDOW_MODE_SPLIT_SECONDARY; case WindowModeSupport::WINDOW_MODE_SUPPORT_PIP: return WindowMode::WINDOW_MODE_PIP; + case WindowModeSupport::WINDOW_MODE_SUPPORT_FB: + return WindowMode::WINDOW_MODE_FB; default: return WindowMode::WINDOW_MODE_UNDEFINED; } diff --git a/utils/src/wm_common.cpp b/utils/src/wm_common.cpp index 55d2b1db80..07ea79dddb 100644 --- a/utils/src/wm_common.cpp +++ b/utils/src/wm_common.cpp @@ -47,5 +47,13 @@ const std::map WM_JS_TO_ERROR_CODE_MAP { {WMError::WM_ERROR_INVALID_SESSION, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, {WMError::WM_ERROR_SYSTEM_ABNORMALLY, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY }, {WMError::WM_ERROR_TIMEOUT, WmErrorCode::WM_ERROR_TIMEOUT }, + {WMError::WM_ERROR_FB_PARAM_INVALID, WmErrorCode::WM_ERROR_FB_PARAM_INVALID }, + {WMError::WM_ERROR_FB_CREATE_FAILED, WmErrorCode::WM_ERROR_FB_CREATE_FAILED }, + {WMError::WM_ERROR_FB_REPEAT_CONTROLLER, WmErrorCode::WM_ERROR_FB_REPEAT_CONTROLLER }, + {WMError::WM_ERROR_FB_REPEAT_OPERATION, WmErrorCode::WM_ERROR_FB_REPEAT_OPERATION }, + {WMError::WM_ERROR_FB_INTERNAL_ERROR, WmErrorCode::WM_ERROR_FB_INTERNAL_ERROR }, + {WMError::WM_ERROR_FB_STATE_ABNORMALLY, WmErrorCode::WM_ERROR_FB_STATE_ABNORMALLY }, + {WMError::WM_ERROR_FB_INVALID_STATE, WmErrorCode::WM_ERROR_FB_INVALID_STATE }, + {WMError::WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED, WmErrorCode::WM_ERROR_FB_RESTORE_MAIN_WINDOW_FAILED }, }; } \ No newline at end of file diff --git a/window_scene/common/include/session_permission.h b/window_scene/common/include/session_permission.h index fb91d4c828..ecd698f542 100644 --- a/window_scene/common/include/session_permission.h +++ b/window_scene/common/include/session_permission.h @@ -28,6 +28,7 @@ constexpr const char* PERMISSION_CALLED_EXTENSION_ON_LOCK_SCREEN = "ohos.permiss constexpr const char* PERMISSION_WRITE_APP_LOCK = "ohos.permission.WRITE_APP_LOCK"; constexpr const char* PERMISSION_SET_ABILITY_INSTANCE_INFO = "ohos.permission.SET_ABILITY_INSTANCE_INFO"; constexpr const char* PERMISSION_VISIBLE_WINDOW_INFO = "ohos.permission.VISIBLE_WINDOW_INFO"; +constexpr const char* PERMISSION_FLOATING_BALL = "ohos.permission.USE_FLOAT_BALL"; } class SessionPermission { public: diff --git a/window_scene/common/include/window_session_property.h b/window_scene/common/include/window_session_property.h index 9c82299184..ab431c27ee 100755 --- a/window_scene/common/include/window_session_property.h +++ b/window_scene/common/include/window_session_property.h @@ -26,6 +26,7 @@ #include "dm_common.h" #include #include "pixel_map.h" +#include "floating_ball_template_info.h" namespace OHOS { namespace Rosen { @@ -101,6 +102,7 @@ public: void SetIsNeedUpdateWindowMode(bool isNeedUpdateWindowMode); void SetCallingSessionId(uint32_t sessionId); void SetPiPTemplateInfo(const PiPTemplateInfo& pipTemplateInfo); + void SetFbTemplateInfo(const FloatingBallTemplateInfo& fbTemplateInfo); void SetWindowMask(const std::shared_ptr& windowMask); void SetIsShaped(bool isShaped); void SetIsAppSupportPhoneInPc(bool isSupportPhone); @@ -166,6 +168,7 @@ public: bool GetKeepKeyboardFlag() const; uint32_t GetCallingSessionId() const; PiPTemplateInfo GetPiPTemplateInfo() const; + FloatingBallTemplateInfo GetFbTemplateInfo() const; std::shared_ptr GetWindowMask() const; bool GetIsShaped() const; KeyboardLayoutParams GetKeyboardLayoutParams() const; @@ -179,6 +182,8 @@ public: static void UnMarshallingSystemBarMap(Parcel& parcel, WindowSessionProperty* property); bool MarshallingPiPTemplateInfo(Parcel& parcel) const; static void UnmarshallingPiPTemplateInfo(Parcel& parcel, WindowSessionProperty* property); + bool MarshallingFbTemplateInfo(Parcel& parcel) const; + static void UnmarshallingFbTemplateInfo(Parcel& parcel, WindowSessionProperty* property); bool Marshalling(Parcel& parcel) const override; static WindowSessionProperty* Unmarshalling(Parcel& parcel); bool MarshallingWindowMask(Parcel& parcel) const; @@ -431,6 +436,7 @@ private: WindowLimits configLimitsVP_; float lastVpr_ = 0.0f; PiPTemplateInfo pipTemplateInfo_ = {}; + FloatingBallTemplateInfo fbTemplateInfo_ = {}; KeyboardLayoutParams keyboardLayoutParams_; uint32_t windowModeSupportType_ {WindowModeSupport::WINDOW_MODE_SUPPORT_ALL}; std::unordered_map sysBarPropMap_ { diff --git a/window_scene/common/src/window_session_property.cpp b/window_scene/common/src/window_session_property.cpp index 1d32b3b149..6187eea09f 100755 --- a/window_scene/common/src/window_session_property.cpp +++ b/window_scene/common/src/window_session_property.cpp @@ -820,6 +820,16 @@ PiPTemplateInfo WindowSessionProperty::GetPiPTemplateInfo() const return pipTemplateInfo_; } +void WindowSessionProperty::SetFbTemplateInfo(const FloatingBallTemplateInfo& fbTemplateInfo) +{ + fbTemplateInfo_ = fbTemplateInfo; +} + +FloatingBallTemplateInfo WindowSessionProperty::GetFbTemplateInfo() const +{ + return fbTemplateInfo_; +} + void WindowSessionProperty::SetIsNeedUpdateWindowMode(bool isNeedUpdateWindowMode) { isNeedUpdateWindowMode_ = isNeedUpdateWindowMode; @@ -988,6 +998,26 @@ void WindowSessionProperty::UnmarshallingPiPTemplateInfo(Parcel& parcel, WindowS property->SetPiPTemplateInfo(*pipTemplateInfo); } +bool WindowSessionProperty::MarshallingFbTemplateInfo(Parcel& parcel) const +{ + if (!WindowHelper::IsFbWindow(type_)) { + return true; + } + return parcel.WriteParcelable(&fbTemplateInfo_); +} + +void WindowSessionProperty::UnmarshallingFbTemplateInfo(Parcel& parcel, WindowSessionProperty* property) +{ + if (!WindowHelper::IsFbWindow(property->GetWindowType())) { + return; + } + sptr fbTemplateInfo = parcel.ReadParcelable(); + if (fbTemplateInfo == nullptr) { + return; + } + property->SetFbTemplateInfo(*fbTemplateInfo); +} + bool WindowSessionProperty::MarshallingWindowMask(Parcel& parcel) const { if (!parcel.WriteBool(isShaped_)) { @@ -1281,7 +1311,8 @@ bool WindowSessionProperty::Marshalling(Parcel& parcel) const parcel.WriteBool(isFullScreenWaterfallMode_) && parcel.WriteBool(isAbilityHookOff_) && parcel.WriteBool(isAbilityHook_) && parcel.WriteBool(isFollowScreenChange_) && parcel.WriteParcelable(compatibleModeProperty_) && parcel.WriteBool(subWindowOutlineEnabled_) && - MarshallingShadowsInfo(parcel); + MarshallingShadowsInfo(parcel) && + MarshallingFbTemplateInfo(parcel); } WindowSessionProperty* WindowSessionProperty::Unmarshalling(Parcel& parcel) @@ -1387,6 +1418,7 @@ WindowSessionProperty* WindowSessionProperty::Unmarshalling(Parcel& parcel) property->SetCompatibleModeProperty(parcel.ReadParcelable()); property->SetSubWindowOutlineEnabled(parcel.ReadBool()); UnmarshallingShadowsInfo(parcel, property); + UnmarshallingFbTemplateInfo(parcel, property); return property; } @@ -1434,6 +1466,7 @@ void WindowSessionProperty::CopyFrom(const sptr& property configLimitsVP_ = property->configLimitsVP_; lastVpr_ = property->lastVpr_; pipTemplateInfo_ = property->pipTemplateInfo_; + fbTemplateInfo_ = property->fbTemplateInfo_; keyboardLayoutParams_ = property->keyboardLayoutParams_; windowModeSupportType_ = property->windowModeSupportType_; sysBarPropMap_ = property->sysBarPropMap_; diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp index 3ece40c323..3a488b95d6 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp @@ -22,6 +22,7 @@ #include "session_manager/include/scene_session_manager.h" #include "window_manager_hilog.h" #include "common/include/session_permission.h" +#include "napi_common_want.h" namespace OHOS::Rosen { using namespace AbilityRuntime; @@ -34,6 +35,9 @@ const std::string UPDATE_TRANSITION_ANIMATION_CB = "updateTransitionAnimation"; const std::string BUFFER_AVAILABLE_CHANGE_CB = "bufferAvailableChange"; const std::string SESSION_EVENT_CB = "sessionEvent"; const std::string SESSION_RECT_CHANGE_CB = "sessionRectChange"; +const std::string FLOATING_BALL_UPDATE_CB = "updateFbTemplateInfo"; +const std::string FLOATING_BALL_STOP_CB = "prepareRemoveFb"; +const std::string FLOATING_BALL_RESTORE_MAIN_WINDOW_CB = "restoreFbMainWindow"; const std::string WINDOW_MOVING_CB = "windowMoving"; const std::string SESSION_PIP_CONTROL_STATUS_CHANGE_CB = "sessionPiPControlStatusChange"; const std::string SESSION_AUTO_START_PIP_CB = "autoStartPiP"; @@ -204,6 +208,9 @@ const std::map ListenerFuncMap { {SET_WINDOW_SHADOWS_CB, ListenerFuncType::SET_WINDOW_SHADOWS_CB}, {SET_SUB_WINDOW_SOURCE_CB, ListenerFuncType::SET_SUB_WINDOW_SOURCE_CB}, {ANIMATE_TO_CB, ListenerFuncType::ANIMATE_TO_CB}, + {FLOATING_BALL_UPDATE_CB, ListenerFuncType::FLOATING_BALL_UPDATE_CB}, + {FLOATING_BALL_STOP_CB, ListenerFuncType::FLOATING_BALL_STOP_CB}, + {FLOATING_BALL_RESTORE_MAIN_WINDOW_CB, ListenerFuncType::FLOATING_BALL_RESTORE_MAIN_WINDOW_CB}, }; const std::vector g_syncGlobalPositionPermission { @@ -285,6 +292,27 @@ static napi_value CreatePipTemplateInfo(napi_env env, const PiPTemplateInfo& pip return pipTemplateInfoValue; } +static napi_value CreateFbTemplateInfo(napi_env env, const FloatingBallTemplateInfo& fbTemplateInfo) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "template %{public}d, title %{public}s, content%{public}s", fbTemplateInfo.template_, + fbTemplateInfo.title_.c_str(), fbTemplateInfo.content_.c_str()); + napi_value fbTemplateInfoValue = nullptr; + napi_create_object(env, &fbTemplateInfoValue); + napi_set_named_property(env, fbTemplateInfoValue, "template", + CreateJsValue(env, fbTemplateInfo.template_)); + napi_set_named_property(env, fbTemplateInfoValue, "title", + CreateJsValue(env, fbTemplateInfo.title_)); + napi_set_named_property(env, fbTemplateInfoValue, "content", + CreateJsValue(env, fbTemplateInfo.content_)); + napi_value jsIcon = Media::PixelMapNapi::CreatePixelMap(env, fbTemplateInfo.icon_); + if (jsIcon == nullptr) { + TLOGNE(WmsLogTag::WMS_SYSTEM, "icon is nullptr"); + return nullptr; + } + napi_set_named_property(env, fbTemplateInfoValue, "icon", jsIcon); + return fbTemplateInfoValue; +} + static void ParseMetadataConfiguration(napi_env env, napi_value objValue, const sptr& session) { auto abilityInfo = session->GetSessionInfo().abilityInfo; @@ -371,6 +399,8 @@ napi_value JsSceneSession::Create(napi_env env, const sptr& sessio napi_set_named_property(env, objValue, "isAppType", CreateJsValue(env, session->IsFloatingWindowAppType())); napi_set_named_property(env, objValue, "pipTemplateInfo", CreatePipTemplateInfo(env, session->GetPiPTemplateInfo())); + napi_set_named_property(env, objValue, "fbTemplateInfo", + CreateFbTemplateInfo(env, session->GetFbTemplateInfo())); napi_set_named_property(env, objValue, "keyboardGravity", CreateJsValue(env, static_cast(session->GetKeyboardGravity()))); napi_set_named_property(env, objValue, "isTopmost", @@ -513,6 +543,8 @@ void JsSceneSession::BindNativeMethod(napi_env env, napi_value objValue, const c BindNativeFunction(env, objValue, "toggleCompatibleMode", moduleName, JsSceneSession::ToggleCompatibleMode); BindNativeFunction(env, objValue, "requestSpecificSessionClose", moduleName, JsSceneSession::RequestSpecificSessionClose); + BindNativeFunction(env, objValue, "sendFbActionEvent", moduleName, JsSceneSession::SendFbActionEvent); + BindNativeFunction(env, objValue, "setFbWindowId", moduleName, JsSceneSession::SetFbWindowId); } void JsSceneSession::BindNativeMethodForKeyboard(napi_env env, napi_value objValue, const char* moduleName) @@ -1267,6 +1299,60 @@ void JsSceneSession::ProcessSessionRectChangeRegister() WLOGFD("success"); } +void JsSceneSession::ProcessFloatingBallUpdateRegister() +{ + auto session = weakSession_.promote(); + if (session == nullptr) { + WLOGFE("session is nullptr, id:%{public}d", persistentId_); + return; + } + session->SetFloatingBallUpdateCallback([weakThis = wptr(this)](const FloatingBallTemplateInfo& fbTemplateInfo) { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession) { + TLOGE(WmsLogTag::WMS_LIFE, "ProcessFloatingBallUpdateRegister jsSceneSession is null"); + return; + } + jsSceneSession->OnFloatingBallUpdate(fbTemplateInfo); + }); + WLOGFD("success"); +} + +void JsSceneSession::ProcessFloatingBallStopRegister() +{ + auto session = weakSession_.promote(); + if (session == nullptr) { + WLOGFE("session is nullptr, id:%{public}d", persistentId_); + return; + } + session->SetFloatingBallStopCallback([weakThis = wptr(this)]() { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession) { + TLOGE(WmsLogTag::WMS_LIFE, "ProcessFloatingBallStopRegister jsSceneSession is null"); + return; + } + jsSceneSession->OnFloatingBallStop(); + }); + WLOGFD("success"); +} + +void JsSceneSession::ProcessFloatingBallStartAbilityRegister() +{ + auto session = weakSession_.promote(); + if (session == nullptr) { + WLOGFE("session is nullptr, id:%{public}d", persistentId_); + return; + } + session->SetFloatingBallRestoreAblityCallback([weakThis = wptr(this)](const std::shared_ptr& want) { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession) { + TLOGE(WmsLogTag::WMS_LIFE, "ProcessFloatingBallStartAbilityRegister jsSceneSession is null"); + return; + } + jsSceneSession->OnFloatingBallRestoreMainWindow(want); + }); + WLOGFD("success"); +} + void JsSceneSession::ProcessSessionDisplayIdChangeRegister() { auto session = weakSession_.promote(); @@ -2665,6 +2751,20 @@ napi_value JsSceneSession::SetSidebarBlurMaximize(napi_env env, napi_callback_in return (me != nullptr) ? me->OnSetSidebarBlurMaximize(env, info) : nullptr; } +napi_value JsSceneSession::SendFbActionEvent(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "[NAPI]"); + JsSceneSession* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSendFbActionEvent(env, info) : nullptr; +} + +napi_value JsSceneSession::SetFbWindowId(napi_env env, napi_callback_info info) +{ + TLOGI(WmsLogTag::WMS_SYSTEM, "[SetFbWindowId]"); + JsSceneSession* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSetFbWindowId(env, info) : nullptr; +} + bool JsSceneSession::IsCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "JsSceneSession::IsCallbackRegistered[%s]", type.c_str()); @@ -2970,6 +3070,15 @@ void JsSceneSession::ProcessRegisterCallback(ListenerFuncType listenerFuncType) case static_cast(ListenerFuncType::ANIMATE_TO_CB): ProcessAnimateToTargetPropertyRegister(); break; + case static_cast(ListenerFuncType::FLOATING_BALL_UPDATE_CB): + ProcessFloatingBallUpdateRegister(); + break; + case static_cast(ListenerFuncType::FLOATING_BALL_STOP_CB): + ProcessFloatingBallStopRegister(); + break; + case static_cast(ListenerFuncType::FLOATING_BALL_RESTORE_MAIN_WINDOW_CB): + ProcessFloatingBallStartAbilityRegister(); + break; default: break; } @@ -3717,6 +3826,100 @@ void JsSceneSession::OnSessionRectChange(const WSRect& rect, SizeChangeReason re taskScheduler_->PostMainThreadTask(task, rectInfo); } +void JsSceneSession::OnFloatingBallUpdate(const FloatingBallTemplateInfo& fbTemplateInfo) +{ + WLOGFD("OnFloatingBallUpdate [NAPI]"); + auto task = [weakThis = wptr(this), persistentId = persistentId_, fbTemplateInfo, env = env_] { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "OnFloatingBallUpdate jsSceneSession id:%{public}d has been destroyed", + persistentId); + return; + } + auto jsCallBack = jsSceneSession->GetJSCallback(FLOATING_BALL_UPDATE_CB); + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "jsCallBack is nullptr"); + return; + } + napi_value jsTemplate = CreateJsValue(env, fbTemplateInfo.template_); + if (jsTemplate == nullptr) { + TLOGNE(WmsLogTag::WMS_MAIN, "jsTemplate is nullptr"); + return; + } + napi_value jsTitle = CreateJsValue(env, fbTemplateInfo.title_); + if (jsTitle == nullptr) { + TLOGNE(WmsLogTag::WMS_MAIN, "jsTitle is nullptr"); + return; + } + napi_value jsContent = CreateJsValue(env, fbTemplateInfo.content_); + if (jsContent == nullptr) { + TLOGNE(WmsLogTag::WMS_MAIN, "jsContent is nullptr"); + return; + } + napi_value jsIcon = Media::PixelMapNapi::CreatePixelMap(env, fbTemplateInfo.icon_); + if (jsIcon == nullptr) { + TLOGNE(WmsLogTag::WMS_MAIN, "icon is nullptr"); + return; + } + napi_value fbTemplateInfoValue = nullptr; + napi_create_object(env, &fbTemplateInfoValue); + napi_set_named_property(env, fbTemplateInfoValue, "template", jsTemplate); + napi_set_named_property(env, fbTemplateInfoValue, "title", jsTitle); + napi_set_named_property(env, fbTemplateInfoValue, "content", jsContent); + napi_set_named_property(env, fbTemplateInfoValue, "icon", jsIcon); + napi_value argv[] = {fbTemplateInfoValue}; + napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, __func__); +} + +void JsSceneSession::OnFloatingBallStop() +{ + WLOGFD("[NAPI]"); + auto task = [weakThis = wptr(this), persistentId = persistentId_, env = env_] { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "OnFloatingBallStop jsSceneSession id:%{public}d has been destroyed", + persistentId); + return; + } + auto jsCallBack = jsSceneSession->GetJSCallback(FLOATING_BALL_STOP_CB); + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "jsCallBack is nullptr"); + return; + } + napi_value argv[] = {}; + napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), 0, argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, __func__); +} + +void JsSceneSession::OnFloatingBallRestoreMainWindow(const std::shared_ptr& want) +{ + WLOGFD("[NAPI]"); + auto task = [weakThis = wptr(this), want, persistentId = persistentId_, env = env_] { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "OnFloatingBallStop jsSceneSession id:%{public}d has been destroyed", + persistentId); + return; + } + auto jsCallBack = jsSceneSession->GetJSCallback(FLOATING_BALL_RESTORE_MAIN_WINDOW_CB); + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "jsCallBack is nullptr"); + return; + } + napi_value jsWant = AppExecFwk::WrapWant(env, *want); + if (jsWant == nullptr) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "null jsWant"); + return; + } + napi_value argv[] = {jsWant}; + napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, __func__); +} + void JsSceneSession::OnWindowMoving(DisplayId displayId, int32_t pointerX, int32_t pointerY) { auto task = [weakThis = wptr(this), persistentId = persistentId_, displayId, pointerX, pointerY, env = env_] { @@ -5409,6 +5612,62 @@ napi_value JsSceneSession::OnRequestHideKeyboard(napi_env env, napi_callback_inf return NapiGetUndefined(env); } +napi_value JsSceneSession::OnSendFbActionEvent(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Argc count is invalid: %{public}zu", argc); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + std::string action; + if (!ConvertFromJsValue(env, argv[0], action)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to convert parameter to string"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + + auto session = weakSession_.promote(); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_SYSTEM, "session is nullptr, id:%{public}d", persistentId_); + return NapiGetUndefined(env); + } + session->SendFbActionEvent(action); + return NapiGetUndefined(env); +} + +napi_value JsSceneSession::OnSetFbWindowId(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { // 1: params num + TLOGE(WmsLogTag::WMS_SYSTEM, "Argc count is invalid: %{public}zu", argc); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + uint32_t windowId = 0; + if (!ConvertFromJsValue(env, argv[0], windowId)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Failed to convert parameter to uint32_t"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + auto session = weakSession_.promote(); + if (session == nullptr) { + WLOGFE("session is nullptr, id:%{public}d", persistentId_); + return NapiGetUndefined(env); + } + session->SetFbWindowId(windowId); + TLOGI(WmsLogTag::WMS_SYSTEM, "SetFbWindowId id:%{public}d", windowId); + return NapiGetUndefined(env); +} + napi_value JsSceneSession::OnSetPipActionEvent(napi_env env, napi_callback_info info) { size_t argc = 4; diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h index c60f3ddc73..710b6085f5 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h @@ -106,6 +106,9 @@ enum class ListenerFuncType : uint32_t { SET_SUB_WINDOW_SOURCE_CB, ANIMATE_TO_CB, PENDING_SESSION_TO_BACKGROUND_CB, + FLOATING_BALL_UPDATE_CB, + FLOATING_BALL_STOP_CB, + FLOATING_BALL_RESTORE_MAIN_WINDOW_CB, }; class SceneSession; @@ -238,6 +241,8 @@ private: static napi_value SetCurrentRotation(napi_env env, napi_callback_info info); static napi_value SetSidebarBlurMaximize(napi_env env, napi_callback_info info); static napi_value RequestSpecificSessionClose(napi_env env, napi_callback_info info); + static napi_value SendFbActionEvent(napi_env env, napi_callback_info info); + static napi_value SetFbWindowId(napi_env env, napi_callback_info info); /* * PC Window @@ -325,6 +330,8 @@ private: napi_value OnSetSidebarBlurMaximize(napi_env env, napi_callback_info info); static napi_value GetJsPanelSessionObj(napi_env env, const sptr& session); napi_value OnRequestSpecificSessionClose(napi_env env, napi_callback_info info); + napi_value OnSendFbActionEvent(napi_env env, napi_callback_info info); + napi_value OnSetFbWindowId(napi_env env, napi_callback_info info); /* * PC Window @@ -337,6 +344,9 @@ private: void ProcessCreateSubSessionRegister(); void ProcessBindDialogTargetRegister(); void ProcessSessionRectChangeRegister(); + void ProcessFloatingBallUpdateRegister(); + void ProcessFloatingBallStopRegister(); + void ProcessFloatingBallStartAbilityRegister(); void ProcessSessionDisplayIdChangeRegister(); void ProcessSessionPiPControlStatusChangeRegister(); void ProcessAutoStartPiPStatusChangeRegister(); @@ -419,6 +429,9 @@ private: void OnSessionRectChange(const WSRect& rect, SizeChangeReason reason = SizeChangeReason::UNDEFINED, DisplayId displayId = DISPLAY_ID_INVALID, const RectAnimationConfig& rectAnimationConfig = {}); + void OnFloatingBallUpdate(const FloatingBallTemplateInfo& fbTemplateInfo); + void OnFloatingBallStop(); + void OnFloatingBallRestoreMainWindow(const std::shared_ptr& want); void OnSessionDisplayIdChange(uint64_t displayId); void OnSessionPiPControlStatusChange(WsPiPControlType controlType, WsPiPControlStatus status); void OnAutoStartPiPStatusChange(bool isAutoStart, uint32_t priority, uint32_t width, uint32_t height); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.cpp index aa4b0eb8a3..e3de8c928c 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.cpp @@ -2258,6 +2258,7 @@ napi_value SessionTypeInit(napi_env env) SetTypeProperty(objValue, env, "TYPE_DYNAMIC", JsSessionType::TYPE_DYNAMIC); SetTypeProperty(objValue, env, "TYPE_MAGNIFICATION", JsSessionType::TYPE_MAGNIFICATION); SetTypeProperty(objValue, env, "TYPE_MAGNIFICATION_MENU", JsSessionType::TYPE_MAGNIFICATION_MENU); + SetTypeProperty(objValue, env, "TYPE_FLOATING_BALL", JsSessionType::TYPE_FLOATING_BALL); return objValue; } diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.h index 2ac2b7811d..71564d7cf4 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_utils.h @@ -90,7 +90,8 @@ enum class JsSessionType : uint32_t { TYPE_MUTISCREEN_COLLABORATION, TYPE_DYNAMIC = 41, TYPE_MAGNIFICATION = 42, - TYPE_MAGNIFICATION_MENU = 43 + TYPE_MAGNIFICATION_MENU = 43, + TYPE_FLOATING_BALL = 45, }; const std::map WINDOW_TO_JS_SESSION_TYPE_MAP { @@ -137,6 +138,7 @@ const std::map WINDOW_TO_JS_SESSION_TYPE_MAP { { WindowType::WINDOW_TYPE_DYNAMIC, JsSessionType::TYPE_DYNAMIC }, { WindowType::WINDOW_TYPE_MAGNIFICATION, JsSessionType::TYPE_MAGNIFICATION }, { WindowType::WINDOW_TYPE_MAGNIFICATION_MENU, JsSessionType::TYPE_MAGNIFICATION_MENU }, + { WindowType::WINDOW_TYPE_FB, JsSessionType::TYPE_FB }, }; const std::map JS_SESSION_TO_WINDOW_TYPE_MAP { @@ -183,6 +185,7 @@ const std::map JS_SESSION_TO_WINDOW_TYPE_MAP { { JsSessionType::TYPE_DYNAMIC, WindowType::WINDOW_TYPE_DYNAMIC }, { JsSessionType::TYPE_MAGNIFICATION, WindowType::WINDOW_TYPE_MAGNIFICATION }, { JsSessionType::TYPE_MAGNIFICATION_MENU, WindowType::WINDOW_TYPE_MAGNIFICATION_MENU }, + { JsSessionType::WINDOW_TYPE_FB, WindowType::TYPE_FB }, }; enum class ThrowSlipMode; diff --git a/window_scene/session/container/include/zidl/session_stage_interface.h b/window_scene/session/container/include/zidl/session_stage_interface.h index 043ffe7c19..96c100e81d 100644 --- a/window_scene/session/container/include/zidl/session_stage_interface.h +++ b/window_scene/session/container/include/zidl/session_stage_interface.h @@ -258,6 +258,16 @@ public: virtual WSError SetCurrentRotation(int32_t currentRotation) = 0; virtual WSError NotifyAppForceLandscapeConfigUpdated() = 0; virtual WSError CloseSpecificScene() { return WSError::WS_DO_NOTHING; } + + /** + * @brief Send fb event to client. + * + * Send the fb event to client. Such as close, click events. + * + * @param action Indicates the action name. + * @return Returns WSError::WS_OK if called success, otherwise failed. + */ + virtual WSError SendFbActionEvent(const std::string& action) = 0; }; } // namespace OHOS::Rosen #endif // OHOS_WINDOW_SCENE_SESSION_STAGE_INTERFACE_H diff --git a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h index 9eaa01dfbd..416086d8ae 100644 --- a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h +++ b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h @@ -90,6 +90,7 @@ enum class SessionStageInterfaceCode { TRANS_ID_NOTIFY_WINDOW_ATTACH_STATE_CHANGE, TRANS_ID_NOTIFY_APP_FORCE_LANDSCAPE_CONFIG_UPDATED, TRANS_ID_CLOSE_SPECIFIC_SCENE, + TRANS_ID_SEND_FB_ACTION_EVENT, }; } // namespace Rosen } // namespace OHOS diff --git a/window_scene/session/container/include/zidl/session_stage_proxy.h b/window_scene/session/container/include/zidl/session_stage_proxy.h index 3e6af44247..08353dcad6 100644 --- a/window_scene/session/container/include/zidl/session_stage_proxy.h +++ b/window_scene/session/container/include/zidl/session_stage_proxy.h @@ -109,6 +109,7 @@ public: // Window LifeCycle void NotifyNonInteractiveStatus() override; WMError GetRouterStackInfo(std::string& routerStackInfo) override; + WMError SendFbActionEvent(const std::string& action) override; private: static inline BrokerDelegator delegator_; diff --git a/window_scene/session/container/include/zidl/session_stage_stub.h b/window_scene/session/container/include/zidl/session_stage_stub.h index 615c55f3d1..e82b64c84d 100644 --- a/window_scene/session/container/include/zidl/session_stage_stub.h +++ b/window_scene/session/container/include/zidl/session_stage_stub.h @@ -100,6 +100,7 @@ private: int HandleNotifyAppForceLandscapeConfigUpdated(MessageParcel& data, MessageParcel& reply); int HandleGetRouterStackInfo(MessageParcel& data, MessageParcel& reply); int HandleCloseSpecificScene(MessageParcel& data, MessageParcel& reply); + int HandleSendFbActionEvent(MessageParcel& data, MessageParcel& reply); }; } // namespace OHOS::Rosen #endif // OHOS_WINDOW_SCENE_SESSION_STAGE_STUB_H diff --git a/window_scene/session/container/src/zidl/session_stage_proxy.cpp b/window_scene/session/container/src/zidl/session_stage_proxy.cpp index 05187cb625..3c88223575 100644 --- a/window_scene/session/container/src/zidl/session_stage_proxy.cpp +++ b/window_scene/session/container/src/zidl/session_stage_proxy.cpp @@ -1258,6 +1258,34 @@ WSError SessionStageProxy::SetPipActionEvent(const std::string& action, int32_t return WSError::WS_OK; } +WSError SessionStageProxy::SendFbActionEvent(const std::string& action) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + + if (!data.WriteString(action)) { + WLOGFE("Write params failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFE("remote is null"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(SessionStageInterfaceCode::TRANS_ID_SEND_FB_ACTION_EVENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + return WSError::WS_OK; +} + WSError SessionStageProxy::NotifyPipWindowSizeChange(double width, double height, double scale) { MessageParcel data; diff --git a/window_scene/session/container/src/zidl/session_stage_stub.cpp b/window_scene/session/container/src/zidl/session_stage_stub.cpp index 6375a57199..9c4e0d488e 100644 --- a/window_scene/session/container/src/zidl/session_stage_stub.cpp +++ b/window_scene/session/container/src/zidl/session_stage_stub.cpp @@ -226,6 +226,8 @@ int SessionStageStub::OnRemoteRequest(uint32_t code, MessageParcel& data, Messag return HandleCloseSpecificScene(data, reply); case static_cast(SessionStageInterfaceCode::TRANS_ID_GET_ROUTER_STACK_INFO): return HandleGetRouterStackInfo(data, reply); + case static_cast(SessionStageInterfaceCode::TRANS_ID_SEND_FB_ACTION_EVENT): + return HandleSendFbActionEvent(data, reply); default: WLOGFE("Failed to find function handler!"); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -695,6 +697,18 @@ int SessionStageStub::HandleSetPipActionEvent(MessageParcel& data, MessageParcel return ERR_NONE; } +int SessionStageStub::HandleSendFbActionEvent(MessageParcel& data, MessageParcel& reply) +{ + TLOGD(WmsLogTag::WMS_SYSTEM, "HandleSendFbActionEvent"); + std::string action; + if (!data.ReadString(action)) { + TLOGE(WmsLogTag::WMS_SYSTEM, "Read action failed."); + return ERR_INVALID_VALUE; + } + SendFbActionEvent(action); + return ERR_NONE; +} + int SessionStageStub::HandleSetPiPControlEvent(MessageParcel& data, MessageParcel& reply) { TLOGD(WmsLogTag::WMS_PIP, "called"); -- Gitee